1

I have an app reading temp + humidity from an AM2301.

Using pigpio. Python 3.4.3. Newest firmware (as of 8/14/15) using rpi-update.

Code is below. Breaks when overclocking the Pi to anything other than the base setting. Doesn't get temp/humid values.

I assume this is due to timing, have not had a chance to get the pigpio source from github and dig into the code. Hoping @joan just knows the answer off the top of his head.

And thank you @joan for providing pigpiod!

Sorry @joan for imcomplete code. I had to escape the <'s.

Relevant code below:


#!/usr/local/bin/python3
'''
    This files gets the readings from the light and temp / humid sensor
'''

import time
import pigpio
import logging
import smbus

_3W = (1 << 9) # I have no idea what this is
_3WN = (15<<10) # I have no idea what this is

SPEED = 200000
BYTES = 130
INTERVAL = 60

# This is for the light sensor, its address in the i2c bus
LIGHT_SENSOR_ADDR = 0x23


class Sensors(object):

    def __init__(self):
        # The light sensor is on i2c bus 1, address 23
        self.bus = smbus.SMBus(1)

        # Connect to local GPIO
        self.pi = pigpio.pi()

        # Connect to temp / humid sensor
        self.am2302 = self.pi.spi_open(0, SPEED, _3W|_3WN)
        return


    '''
        I copied this, don't really understand it
    '''
    def get_bit(self, in_bit, in_byte, buf):
        global BYTES
        v = not (buf[in_byte] & (1<<(7-in_bit))) # Force logical result
        numbit = 1

        while in_byte < BYTES:
            in_bit += 1
            if in_bit > 7:
                in_bit = 0
                in_byte += 1
            nv = not (buf[in_byte] & (1<<(7-in_bit)))
            if nv == v:
                numbit += 1
            else:
                if not v: # Return high edge
                    return (numbit, in_bit, in_byte)

                else: # Skip low edge
                    v = nv
                    numbit = 1
        return (0, 0, 0)

    '''
        Temp and humidity come from the same sensor, so read them together
        I copied this stuff, don't understand much of it
    '''
    def get_temp_humid(self):
        # I don't understand this stuff, but it works
        (c, buf) = self.pi.spi_read(self.am2302, BYTES+1)
        numbit = 1
        in_bit = 0
        in_byte = 0
        (numbit, in_bit, in_byte) = self.get_bit(in_bit, in_byte, buf)
        logging.debug("numbit {0} in bit {1} in byte {2}".format(
                numbit, in_bit, in_byte))
        (numbit, in_bit, in_byte) = self.get_bit(in_bit, in_byte, buf)
        logging.debug("numbit {0} in bit {1} in byte {2}".format(
                numbit, in_bit, in_byte))
        bit = 0
        byte = 0
        val = [0]*5
        temp = 0
        humidity = 0
        while numbit:
            (numbit, in_bit, in_byte) = self.get_bit(in_bit, in_byte, buf)
            if numbit:
                if numbit > 9:
                    val[byte] |= (1<<(7-bit))
                bit += 1
                if bit > 7:
                    bit = 0
                    byte += 1
        checksum = 0
        for i in range(4):
            checksum += val[i]
        if val[4] == (checksum&255):
            humidity = ((val[0]*256) + val[1]) / 10.0

            sign = val[2] & 128
            val[2] &= 0x127
            temp = ((val[2]*256) + val[3]) / 10.0
            if sign:
                temp = -temp
            #convert to F
            temp = (temp * (9.0 / 5.0)) + 32.0
        logging.debug("In Sensor.py: temp {0} humid {1}".format(temp, humidity))
        return (temp, humidity)

    '''
        Get the light level
    '''
    def get_light(self):
        data = self.bus.read_i2c_block_data(LIGHT_SENSOR_ADDR, 0x11)
        light_level = int((data[1] + (256 * data[0])) / 1.2)
        return light_level



# Testing here
if __name__ == "__main__":

    s = Sensors()
    logging.basicConfig(format="%(asctime)s: %(message)s",
                level=logging.DEBUG)

    for i in range(10):
        logging.debug(s.get_light())
        logging.debug(s.get_temp_humid())
        time.sleep(60)


  • The code appears to be incomplete. It's not clear if you are using the pigpio I2C functions or the SMBus functions to read the sensor. However that might be moot as they are both using the underlying Linux driver. – joan Aug 14 '15 at 18:58
  • SMBus to read the light. spi_read for temp/humid. Light still works when overclocked, temp/humid does not. Only change is to overclock. Fixed code issue, the left shift operator was messing with the html. – ifermon Aug 14 '15 at 19:21
  • I have not seen that method of reading the AM2302 used with pigpio before. Where did you get the code? Have you tried to read the AM2302 with the DHT22/AM2302 Python code at abyz.co.uk/rpi/pigpio/examples.html#Python_code. That code should be immune to overclocking. – joan Aug 14 '15 at 19:40
  • 1
    I'll change it. And move the light sensor from SMbus to pigpio while I'm at it. I wish I knew why I always feel the need to change working code. Thank you @joan. – ifermon Aug 15 '15 at 13:52
  • 1
    Re "I wish I knew why I always feel the need to change working code". That is how we learn. The code I have on the web-site are only examples. They could all be improved, they just show one possible way of perhaps getting something to work. – joan Aug 15 '15 at 13:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.