def read(self): # pull down to low self.__send_and_sleep(0, 0.019) data = pycom.pulses_get(self.__pin,100) self.__pin.init(Pin.OPEN_DRAIN) self.__pin(1) #print(data) bits = [] for a,b in data: if a ==1 and 18 <= b <= 28: bits.append(0) if a ==1 and 65 <= b <= 75: bits.append(1) #print("longueur bits : %d " % len(bits)) if len(bits) != 40: return DTHResult(DTHResult.ERR_MISSING_DATA, 0, 0) #print(bits) # we have the bits, calculate bytes the_bytes = self.__bits_to_bytes(bits) # calculate checksum and check checksum = self.__calculate_checksum(the_bytes) if the_bytes[4] != checksum: return DTHResult(DTHResult.ERR_CRC, 0, 0) # ok, we have valid data, return it [int_rh, dec_rh, int_t, dec_t, csum] = the_bytes if self.__dhttype==0: #dht11 rh = int_rh #dht11 20% ~ 90% t = int_t #dht11 0..50°C else: #dht21,dht22 rh = ((int_rh * 256) + dec_rh)/10 t = (((int_t & 0x7F) * 256) + dec_t)/10 if (int_t & 0x80) > 0: t *= -1 return DTHResult(DTHResult.ERR_NO_ERROR, t, rh)
def calibrate_rtc(self): # the 1.024 factor is because the PIC LF operates at 31 KHz # WDT has a frequency divider to generate 1 ms # and then there is a binary prescaler, e.g., 1, 2, 4 ... 512, 1024 ms # hence the need for the constant self._write(bytes([CMD_CALIBRATE]), wait=False) self.i2c.deinit() Pin('P21', mode=Pin.IN) pulses = pycom.pulses_get('P21', 100) self.i2c.init(mode=I2C.MASTER, pins=(self.sda, self.scl), baudrate=100000) idx = 0 for i in range(len(pulses)): if pulses[i][1] > EXP_RTC_PERIOD: idx = i break try: period = pulses[idx][1] - pulses[(idx - 1)][1] except: period = 0 if period > 0: self.clk_cal_factor = (EXP_RTC_PERIOD / period) * (1000 / 1024) if self.clk_cal_factor > 1.25 or self.clk_cal_factor < 0.75: self.clk_cal_factor = 1
def _send_pulse_and_wait(self): """ Send the pulse to trigger and listen on echo pin. We use the method `machine.time_pulse_us()` to get the microseconds until the echo is received. """ self.trigger.value(0) # Stabilize the sensor time.sleep_us(5) self.trigger.value(1) # Send a 10us pulse. time.sleep_us(10) self.trigger.value(0) try: if (uname().sysname == 'WiPy'): pulse_list = pulses_get(self.echo, self.echo_timeout_us) if (len(pulse_list) == 0): pulse_time = -1 else: pulse_time = pulse_list[0][1] else: pulse_time = time_pulse_us(self.echo, 1, self.echo_timeout_us) return pulse_time except OSError as ex: if ex.args[0] == 110: # 110 = ETIMEDOUT raise OSError('Out of range') raise ex
def calibrate(self): # The microcontroller will send the value of CTRL_0 after setting the bit # and then will send the following pattern through the data line: # # val | 1 | 0 | 1*| 0 | 1*| 0 | 1 # ms | 1 | 1 | 1 | 1 | 8 | 1 | - # # The idea is to measure the real life duration of periods marked with * # and substract them. That will remove any errors common to both measurements # The result is 7 ms as generated by the PIC LF clock. # It can be used to scale any future sleep value. # setbits, but limit the number of received bytes to avoid confusion with pattern self._magic(CTRL_0_ADDR, 0xFF, 1 << 2, 0, 0) self.uart.deinit() self._pulses = pycom.pulses_get(COMM_PIN, 150) self.uart.init(baudrate=10000, pins=(COMM_PIN, ), timeout_chars=5) idx = 0 for i in range(len(self._pulses)): if self._pulses[i][1] > EXP_RTC_PERIOD: idx = i break try: self.clk_cal_factor = (self._pulses[idx][1] - self._pulses[(idx - 1)][1]) / EXP_RTC_PERIOD except: self.clk_cal_factor = 1 if self.clk_cal_factor > 1.25 or self.clk_cal_factor < 0.75: self.clk_cal_factor = 1
def calibrate(self): """ The microcontroller will send the value of CTRL_0 after setting the bit and then will send the following pattern through the data line: val | 1 | 0 | 1*| 0 | 1*| 0 | 1 ms | 1 | 1 | 1 | 1 | 8 | 1 | - The idea is to measure the real life duration of periods marked with * and substract them. That will remove any errors common to both measurements The result is 7 ms as generated by the PIC LF clock. It can be used to scale any future sleep value. """ # setbits, but limit the number of received bytes to avoid confusion with pattern self._magic(CTRL_0_ADDR, 0xFF, 1 << 2, 0, 0) self._pulses = pycom.pulses_get(COMM_PIN, 50) self.uart.init(baudrate=10000, pins=(COMM_PIN, ), timeout_chars=3) try: if len(self._pulses) > 6: self.clk_cal_factor = (self._pulses[6][1] - self._pulses[4][1]) / EXP_RTC_PERIOD else: self.clk_cal_factor = (self._pulses[5][1] - self._pulses[3][1]) / EXP_RTC_PERIOD except: pass if self.clk_cal_factor > 1.25 or self.clk_cal_factor < 0.75: self.clk_cal_factor = 1 # flush the buffer self.uart.read() self.get_wake_status()
def calibrate_rtc(self): self._write(bytes([CMD_CALIBRATE]), wait=False) self.i2c.deinit() Pin('P21', mode=Pin.IN) pulses = pycom.pulses_get('P21', 50000) self.i2c.init(mode=I2C.MASTER, pins=(self.sda, self.scl)) period = pulses[2][1] - pulses[0][1] if period > 0: self.clk_cal_factor = (EXP_RTC_PERIOD / period) * 0.98
def calibrate_rtc(self): # the 1.024 factor is because the PIC LF operates at 31 KHz # WDT has a frequency divider to generate 1 ms # and then there is a binary prescaler, e.g., 1, 2, 4 ... 512, 1024 ms # hence the need for the constant self._write(bytes([CMD_CALIBRATE]), wait=False) self.i2c.deinit() Pin('P21', mode=Pin.IN) pulses = pycom.pulses_get('P21', 50000) self.i2c.init(mode=I2C.MASTER, pins=(self.sda, self.scl)) period = pulses[2][1] - pulses[0][1] if period > 0: self.clk_cal_factor = (EXP_RTC_PERIOD / period) * (1000 / 1024)
def get_pulses(): data = [(0,0)] cnt = 0 tester = True pulses = 100 while(tester): pin = Pin('P21', mode=Pin.OPEN_DRAIN) pin(0) sleep_ms(20) pin(1) data = pulses_get(pin, pulses) # Fetches all pulses > 100ms tester = not (data[0][0] == 1 and len(data) == 80) return data
def calibrate_rtc(self): # the 1.024 factor is because the PIC LF operates at 31 KHz # WDT has a frequency divider to generate 1 ms # and then there is a binary prescaler, e.g., 1, 2, 4 ... 512, 1024 ms # hence the need for the constant self._write(bytes([CMD_CALIBRATE]), wait=False) self.i2c.deinit() Pin('P21', mode=Pin.IN) pulses = pycom.pulses_get('P21', 50) self.i2c.init(mode=I2C.MASTER, pins=(self.sda, self.scl)) try: period = pulses[2][1] - pulses[0][1] except: pass if period > 0: self.clk_cal_factor = (EXP_RTC_PERIOD / period) * (1000 / 1024)
def trigger(self): # quick fix: # re-init pin on each trigger, otherwise no subsequent readings? # cf. https://github.com/erikdelange/WiPy-2.0-DHT22/issues/1 self.pin = Pin(self.pinnumber, mode=Pin.OPEN_DRAIN) self.pin(1) # enforce two second read interval time.sleep(2) self.pin(0) # send start signal (1ms low). time.sleep_ms(1) pulses = pycom.pulses_get(self.pin, 100) # capture communication if len(pulses) != 82: # 40 data bit plus one acknowledge expected self.status = "ReadError" return False bits = [] for level, duration in pulses[1:]: if level == 1: bits.append(0 if duration < 50 else 1) # convert to 0 or 1 data = [] for n in range(5): byte = 0 for i in range(8): # shift 8 bits into a byte byte <<= 1 byte += bits[n * 8 + i] data.append(byte) int_rh, dec_rh, int_t, dec_t, csum = data if ((int_rh + dec_rh + int_t + dec_t) & 0xFF) != csum: self.status = "Checksum Error" return False self.humidity = ((int_rh * 256) + dec_rh) / 10 self.temperature = (((int_t & 0x7F) * 256) + dec_t) / 10 if (int_t & 0x80) > 0: self.temperature *= -1 self.status = "OK" self.pin(0) return True
def trigger(self): # quick fix: # re-init pin on each trigger, otherwise no subsequent readings? # cf. https://github.com/erikdelange/WiPy-2.0-DHT22/issues/1 self.pin = Pin(self.pinnumber, mode=Pin.OPEN_DRAIN) self.pin(1) # enforce two second read interval time.sleep(2) self.pin(0) # send start signal (1ms low). time.sleep_ms(1) pulses = pycom.pulses_get(self.pin, 100) # capture communication if len(pulses) != 82: # 40 data bit plus one acknowledge expected self.status = "ReadError" return False bits = [] for level, duration in pulses[1:]: if level == 1: bits.append(0 if duration < 50 else 1) # convert to 0 or 1 data = [] for n in range(5): byte = 0 for i in range(8): # shift 8 bits into a byte byte <<= 1 byte += bits[n * 8 + i] data.append(byte) int_rh, dec_rh, int_t, dec_t, csum = data if ((int_rh + dec_rh + int_t + dec_t) & 0xFF) != csum: self.status = "Checksum Error" return False self.humidity = ((int_rh * 256) + dec_rh) / 10 self.temperature = (((int_t & 0x7F) * 256) + dec_t) / 10 if (int_t & 0x80) > 0: self.temperature *= -1 self.status = "OK" self.pin(0) return True
def trigger(self): self.pin.init(Pin.OUT) self.pin(1) time.sleep(2) # enforce two second read interval self.pin(0) # send start signal (1ms low). time.sleep_ms(20) pulses = pycom.pulses_get(self.pin, 100) # capture communication time.sleep(2) self.pin.init(Pin.OPEN_DRAIN) if len(pulses) != 82: # 40 data bit plus one acknowledge expected self.status = "ReadError - received {} only pulses".format(len(pulses)) return False bits = [] for level, duration in pulses[1:]: if level == 1: bits.append(0 if duration < 50 else 1) # convert to 0 or 1 data = [] for n in range(5): byte = 0 for i in range(8): # shift 8 bits into a byte byte <<= 1 byte += bits[n * 8 + i] data.append(byte) int_rh, dec_rh, int_t, dec_t, csum = data print(data) if ((int_rh + dec_rh + int_t + dec_t) & 0xFF) != csum: self.status = "Checksum Error" return False self.humidity = (int_rh +(dec_rh*0.1)) self.temperature = (int_t + dec_t*0.1) if (int_t & 0x80) > 0: self.temperature *= -1 self.status = "OK" return True
def __measure(self): if time.ticks_ms() - self.__last_measurement < 1000: return pin = self.__pin # pull down to low pin(0) time.sleep_ms(20) # changed from 19 to 20 # listen for pulses on data line data = pycom.pulses_get(pin, 100) # reset pin pin.init(Pin.OPEN_DRAIN) pin(1) # convert the received pulses to usable bits bits = [] for value, length in data: if value == 1 and 18 <= length <= 28: bits.append(0) if value == 1 and 65 <= length <= 75: bits.append(1) # should have 40 bits / 5 bytes if len(bits) != 40: return buffer = bits_to_bytes(bits) # calculate checksum and check checksum = buffer[0] + buffer[1] + buffer[2] + buffer[3] & 255 if buffer[4] != checksum: return # humidity, temperature self.__humidity = buffer[0] self.__temperature = buffer[2] self.__last_measurement = time.ticks_ms()
def calibrate(self): """ The microcontroller will send the value of CTRL_0 after setting the bit and then will send the following pattern through the data line: val | 1 | 0 | 1*| 0 | 1*| 0 | 1 ms | 1 | 1 | 1 | 1 | 8 | 1 | - The idea is to measure the real life duration of periods marked with * and substract them. That will remove any errors common to both measurements The result is 7 ms as generated by the PIC LF clock. It can be used to scale any future sleep value.""" # setbits, but limit the number of received bytes to avoid confusion with pattern self._magic(CTRL_0_ADDR, 0xFF, 1 << 2, 0, 7) self.uart.deinit() Pin(COMM_PIN, mode=Pin.IN) pulses = pycom.pulses_get(COMM_PIN, 50000) self.uart = UART(1, baudrate=10000, pins=(COMM_PIN, )) self.clk_cal_factor = (pulses[3][1] - pulses[1][1]) / EXP_RTC_PERIOD if self.clk_cal_factor > 1.25 or self.clk_cal_factor < 0.75: self.clk_cal_factor = 1
def calibrate(self): """ The microcontroller will send the value of CTRL_0 after setting the bit and then will send the following pattern through the data line: val | 1 | 0 | 1*| 0 | 1*| 0 | 1 ms | 1 | 1 | 1 | 1 | 8 | 1 | - The idea is to measure the real life duration of periods marked with * and substract them. That will remove any errors common to both measurements The result is 7 ms as generated by the PIC LF clock. It can be used to scale any future sleep value. """ # setbits, but limit the number of received bytes to avoid confusion with pattern self._magic(CTRL_0_ADDR, 0xFF, 1 << 2, 0, 0) self.uart.deinit() self._pulses = pycom.pulses_get(COMM_PIN, 50) self.uart = UART(1, baudrate=10000, pins=(COMM_PIN, )) try: self.clk_cal_factor = (self._pulses[4][1] - self._pulses[1][1]) / EXP_RTC_PERIOD except: pass if self.clk_cal_factor > 1.25 or self.clk_cal_factor < 0.75: self.clk_cal_factor = 1
def calibrate_rtc(self): # the 1.024 factor is because the PIC LF operates at 31 KHz # WDT has a frequency divider to generate 1 ms # and then there is a binary prescaler, e.g., 1, 2, 4 ... 512, 1024 ms # hence the need for the constant self._write(bytes([CMD_CALIBRATE]), wait=False) self.i2c.deinit() Pin('P21', mode=Pin.IN) pulses = pycom.pulses_get('P21', 100) self.i2c.init(mode=I2C.MASTER, pins=(self.sda, self.scl)) idx = 0 for i in range(len(pulses)): if pulses[i][1] > EXP_RTC_PERIOD: idx = i break try: period = pulses[idx][1] - pulses[(idx - 1)][1] except: period = 0 if period > 0: self.clk_cal_factor = (EXP_RTC_PERIOD / period) * (1000 / 1024) if self.clk_cal_factor > 1.25 or self.clk_cal_factor < 0.75: self.clk_cal_factor = 1
def read(self): """ read Reads data from DHT sensor """ # pull down to low self.__send_and_sleep(0, 0.019) data = pycom.pulses_get(self.__pin, 100) # pylint: disable=E1101 self.__pin.init(Pin.OPEN_DRAIN) self.__pin(1) bits = [] for a, b in data: if a == 1 and 18 <= b <= 28: bits.append(0) if a == 1 and 65 <= b <= 75: bits.append(1) if len(bits) != 40: return DHTResult(DHTResult.ERR_MISSING_DATA, 0, 0) # we have the bits, calculate bytes the_bytes = bits_to_bytes(bits) # calculate checksum and check checksum = calculate_checksum(the_bytes) if the_bytes[4] != checksum: return DHTResult(DHTResult.ERR_CRC, 0, 0) # ok, we have valid data, return it [int_rh, dec_rh, int_t, dec_t, csum] = the_bytes # pylint: disable=E0632,W0612 if self.__dhttype == 0: #dht11 rh = int_rh #dht11 20% ~ 90% t = int_t #dht11 0..50 deg C else: #dht21,dht22 rh = ((int_rh * 256) + dec_rh)/10 t = (((int_t & 0x7F) * 256) + dec_t)/10 if (int_t & 0x80) != 0: t = -t return DHTResult(DHTResult.ERR_NO_ERROR, t, rh)
# Enforce a 2 seconds waiting time between measurements. pin(1) time.sleep(2) # Send start signal = 1ms low. pin(0) time.sleep_ms(1) # The DHT22 will repond with an acknowledge signal of 80 us high. # Then 5 bytes with data are emited, so in total 40 bits. # Each bit is represented by the duration of the high-time of a pulse, and # every bit is preceded by a 50 us low. # List 'pulses' will store the duration of the low- and high-pulses (in us). pulses = pycom.pulses_get(pin, 100) pin.init(Pin.OPEN_DRAIN) # Display the raw measurements if 1: print(len(pulses), "pulses measured") for i, (level, duration) in enumerate(pulses): print("i = {:2} level: {} duration: {} us".format(i, level, duration)) # Extract the relevant bits to list 'bits' and skip the acknowledge high bits = [] for level, duration in pulses[1:]: if level == 1: bits.append(