溫濕度感測器實作 – NSHT30數位式溫濕度感測器
電路圖
程式列表
MicroPython - NSHT30.py
|
""" NSHT30 Number Name ------------ 6 VCC 5 4 AL 3 SDA 2 SCL 1 GND ------------ """
from machine import Pin, I2C import utime
NSHT30_I2C_ADDRESS = 0x44 # I2C address B 0x44 ADDR (pin 2) connected to GND # NSHT30_I2C_ADDRESS = 0x45 # I2C address B 0x45 ADDR (pin 2) connected to VDD
class NSHT30: """ NSHT30 sensor driver in pure python based on I2C bus """ POLYNOMIAL = 0x131 # P(x) = x^8 + x^5 + x^4 + 1 = 100110001
ALERT_PENDING_MASK = 0x8000 # 15 HEATER_MASK = 0x2000 # 13 RH_ALERT_MASK = 0x0800 # 11 T_ALERT_MASK = 0x0400 # 10 RESET_MASK = 0x0010 # 4 CMD_STATUS_MASK = 0x0002 # 1 WRITE_STATUS_MASK = 0x0001 # 0
#NSHT30驅動代碼 MEAS_SINGLE_H_CMD = b'\x24\x00' # measurement: SINGLE Mode high repeatability MEAS_SINGLE_M_CMD = b'\x24\x0B' # measurement: SINGLE Mode medium repeatability MEAS_SINGLE_L_CMD = b'\x24\x16' # measurement: SINGLE Mode low repeatability MEAS_PERI_05_H_CMD = b'\x20\x32' # measurement: periodic Mode 0.5 mps high repeatability MEAS_PERI_05_M_CMD = b'\x20\x24' # measurement: periodic Mode 0.5 mps medium repeatability MEAS_PERI_05_L_CMD = b'\x20\x2F' # measurement: periodic Mode 0.5 mps low repeatability MEAS_PERI_1_H_CMD = b'\x21\x30' # measurement: periodic Mode 1 mps high repeatability MEAS_PERI_1_M_CMD = b'\x21\x26' # measurement: periodic Mode 1 mps medium repeatability MEAS_PERI_1_L_CMD = b'\x21\x2D' # measurement: periodic Mode 1 mps low repeatability MEAS_PERI_2_H_CMD = b'\x22\x36' # measurement: periodic Mode 2 mps high repeatability MEAS_PERI_2_M_CMD = b'\x22\x20' # measurement: periodic Mode 2 mps medium repeatability MEAS_PERI_2_L_CMD = b'\x22\x2B' # measurement: periodic Mode 2 mps low repeatability MEAS_PERI_4_H_CMD = b'\x23\x34' # measurement: periodic Mode 4 mps high repeatability MEAS_PERI_4_M_CMD = b'\x23\x22' # measurement: periodic Mode 4 mps medium repeatability MEAS_PERI_4_L_CMD = b'\x23\x29' # measurement: periodic Mode 4 mps low repeatability MEAS_PERI_10_H_CMD = b'\x27\x37' # measurement: periodic Mode 10 mps high repeatability MEAS_PERI_10_M_CMD = b'\x27\x21' # measurement: periodic Mode 10 mps medium repeatability MEAS_PERI_10_L_CMD = b'\x27\x2A' # measurement: periodic Mode 10 mps low repeatability PERIODIC_MODE_READ_CMD = b'\xE0\x00' PERIODIC_MODE_BREAK_CMD = b'\x30\x93'
STATUS_CMD = b'\xF3\x2D' RESET_CMD = b'\x30\xA2' CLEAR_STATUS_CMD = b'\x30\x41' ENABLE_HEATER_CMD = b'\x30\x6D' DISABLE_HEATER_CMD = b'\x30\x66'
HAL_OK = 0 HAL_ERROR = 1
def __init__(self, i2c=None, i2c_address=None): # construct an I2C bus if i2c is None: i2c = I2C(0,I2C.MASTER,baudrate=100000) #Create I2C0 Master Mode, Baudrate=100kHz if i2c_address is None: i2c_address = 0x44 self.i2c = i2c self.i2c_addr = i2c_address utime.sleep_ms(50)
def is_present(self): """ Return true if the sensor is correctly conneced, False otherwise """ return self.i2c_addr in self.i2c.scan()
def _check_crc(self, data): # calculates 8-Bit checksum with given polynomial crc = 0xFF
for b in data[:-1]: crc ^= b for _ in range(8, 0, -1): if crc & 0x80: crc = (crc << 1) ^ NSHT30.POLYNOMIAL else: crc <<= 1 crc_to_check = data[-1] return crc_to_check == crc
def send_cmd(self, cmd_request, response_size=6, read_delay_ms=100): """ Send a command to the sensor and read (optionally) the response The responsed data is validated by CRC """ try: self.i2c.send(cmd_request, self.i2c_addr) # write the given buffer to the peripheral if not response_size: return data = bytearray(response_size) # utime.sleep_ms(read_delay_ms) self.i2c.recv(data,self.i2c_addr)
for i in range(response_size//3): if not self._check_crc(data[i*3:(i+1)*3]): # pos 2 and 5 are CRC raise NSHT30Error(SHT30Error.CRC_ERROR) if data == bytearray(response_size): raise NSHT30Error(SHT30Error.DATA_ERROR) return data except OSError: raise NSHT30Error(SHT30Error.BUS_ERROR) except Exception as ex: raise ex
def clear_status(self): """ Clear the status register """ return self.send_cmd(NSHT30.CLEAR_STATUS_CMD, None)
def reset(self): """ Send a soft-reset to the sensor """ return self.send_cmd(NSHT30.RESET_CMD, None)
def status(self, raw=False): """ Get the sensor status register. It returns a int value or the bytearray(3) if raw==True """ data = self.send_cmd(NSHT30.STATUS_CMD, 3, read_delay_ms=20)
if raw: return data
status_register = data[0] << 8 | data[1] return status_register
def measure(self, cmd, read_delay_ms=100, raw=False): """ If raw==True returns a bytearrya(6) with sensor direct measurement otherwise It gets the temperature (T) and humidity (RH) measurement and return them.
The units are Celsius and percent """ if cmd is None: cmd = NSHT30.MEAS_SINGLE_L_CMD data = self.send_cmd(cmd, 6, read_delay_ms) # read 6 bytes
if raw: return data
t_celsius = (((data[0] << 8 | data[1]) * 175) / 0xFFFF) - 45 rh = (((data[3] << 8 | data[4]) * 100.0) / 0xFFFF) return t_celsius, rh
class NSHT30Error(Exception): """ Custom exception for errors on sensor management """ BUS_ERROR = 0x01 DATA_ERROR = 0x02 CRC_ERROR = 0x03
def __init__(self, error_code=None): self.error_code = error_code super().__init__(self.get_message())
def get_message(self): if self.error_code == NSHT30Error.BUS_ERROR: return "Bus error" elif self.error_code == NSHT30Error.DATA_ERROR: return "Data error" elif self.error_code == NSHT30Error.CRC_ERROR: return "CRC error" else: return "Unknown error" |
MicroPython - NSHT30_main.py
|
""" NSHT30 ePy-Lite Number Name ------------------------- 3V3 6 VCC 5 4 AL P16_SDA0 3 SDA P17_SCL0 2 SCL GND 1 GND ------------------------- """
from machine import Switch #Get button KEY library from machine import Pin, LED, I2C ,UART import utime from NSHT30 import NSHT30
BLEOUT = False DEBUG = True KeyADone = None
I2C_FREQ = 100000
NSHT30_I2C_ADDRESS = 0x44 # I2C address B 0x44 ADDR (pin 2) connected to GND # NSHT30_I2C_ADDRESS = 0x45 # I2C address B 0x45 ADDR (pin 2) connected to VDD
INTERVAL = 5000 # millisecond
def key_int(): global KeyADone KeyADone = True
# Start Function if __name__ == '__main__': ledY = LED('ledy') ledR = LED('ledr') ledY.off() ledR.off()
KeyA = Switch('keya') # Create button A KeyA.callback(key_int) KeyADone = False
i2c = I2C(0,I2C.MASTER,baudrate=I2C_FREQ) # Create I2C0 Master Mode, Baudrate=100kHz sensor = NSHT30(i2c)
if(BLEOUT): ble = UART(1,115200) ble.write('AT+MODE_DATA\r\n')
utime.sleep(2) print("Start humidity measurement.") lastTime=0 while True: currTime = utime.ticks_ms() if (currTime - lastTime > INTERVAL): lastTime = currTime ledY.toggle() temperature, humidity = sensor.measure(sensor.MEAS_SINGLE_L_CMD) print('Temperature: %.2f*C, Humidity: %.2f%%' %(temperature,humidity)) if(BLEOUT): ble.write('T = {}*C, H = {}%\r\n'.format (temperature,humidity)) ledY.toggle()
if KeyADone == True: # Press A Key break
if(BLEOUT): ble.deinit() i2c.deinit() # close the connection to the module KeyA.callback(None) print("Exit humidity measurement.") |
執行結果
Thonny訊息列表
LightBlue APP畫面
參考文獻
l 溫濕度感測器NSHT30使用設計指南(AN-12-0010) - https://www.novosns.com/files/ApplicationNote_wenshiduchuanganqiNSHT30shiyongshejizhinan.pdf