改善の餘地はたくさんあるが問題なく動くには動いたので現状で固めておく。
mbed 用:
#define HTDU21D_ADDRESS 0x40<<1 #define TRIGGER_TEMP_MEASURE_HOLD 0xE3 #define TRIGGER_HUMD_MEASURE_HOLD 0xE5 #define SHIFTED_DIVISOR 0x988000UL #define WRITE_USER_REG 0xE6 #define READ_USER_REG 0xE7 #define SOFT_RESET 0xFE #define RH12_TEMP14 0b00000000 #define RH08_TEMP12 0b00000001 #define RH10_TEMP13 0b10000000 #define RH11_TEMP11 0b10000001 class HTU21D{ public: HTU21D(); float readTemp(void); float readHumid(void); char read_user_register(void); void setResolution(char resolution); void softReset(void); private: unsigned short check_crc(char msb, char lsb, char crc); };
#include "HTU21D.h" #include "MicroBit.h" MicroBitI2C i2c(I2C_SDA0, I2C_SCL0); HTU21D::HTU21D(){ } unsigned short HTU21D::check_crc(char msb, char lsb, char crc){ unsigned int divisor = SHIFTED_DIVISOR; unsigned int remainder = msb<<16 | lsb<<8 | crc; for(int i=23; i>7; i--){ if(remainder & 1<<i){ remainder ^= divisor; } divisor >>= 1; } return (remainder == 0) ? 0 : 999; } float HTU21D::readTemp(){ char buf[3] = {TRIGGER_TEMP_MEASURE_HOLD}; i2c.write(HTDU21D_ADDRESS, buf, 1); i2c.read (HTDU21D_ADDRESS, buf, 3); unsigned short raw = (buf[0]<<8 | buf[1]) & 0xfffc; unsigned short crcResult = check_crc(buf[0], buf[1], buf[2]); return (crcResult == 0) ? -46.85F + 175.72F * (float)raw / 65536.0F : crcResult; } float HTU21D::readHumid(){ char buf[3] = {TRIGGER_HUMD_MEASURE_HOLD}; i2c.write(HTDU21D_ADDRESS, buf, 1); i2c.read (HTDU21D_ADDRESS, buf, 3); unsigned short raw = (buf[0]<<8 | buf[1]) & 0xfffc; unsigned short crcResult = check_crc(buf[0], buf[1], buf[2]); return (crcResult == 0) ? -6.0F + 125.0F * (float)raw / 65536.0F : crcResult; } char HTU21D::read_user_register(void){ char buf[] = {READ_USER_REG}; i2c.write(HTDU21D_ADDRESS, buf, 1); i2c.read (HTDU21D_ADDRESS, buf, 1); return buf[0]; } void HTU21D::setResolution(char resolution){ char userRegister = read_user_register(); userRegister &= 0b01111110; resolution &= 0b10000001; userRegister |= resolution; char buf[] = {WRITE_USER_REG, userRegister}; i2c.write(HTDU21D_ADDRESS, buf, 2); } void HTU21D::softReset(void){ char buf[] = {SOFT_RESET}; i2c.write(HTDU21D_ADDRESS, buf, 1); }
#include "MicroBit.h" #include "HTU21D.h" MicroBit uBit; HTU21D HTU; int main(void){ uBit.init(); //HTU.softReset(); //HTU.setResolution(RH12_TEMP14); //HTU.setResolution(RH08_TEMP12); //HTU.setResolution(RH10_TEMP13); //HTU.setResolution(RH11_TEMP11); while(1){ //printf("User Register: 0x%X\n", HTU.read_user_register()); float temp = HTU.readTemp(); float humid = HTU.readHumid(); printf("%.1f C, %.1f %%\n", temp, humid); wait(1.0); } release_fiber(); return 0; }
MicroPython 用:
from microbit import * class HTU21D: def __init__(self): self.HTDU21D_ADDRESS = 0x40 self.TRIGGER_TEMP_MEASURE_HOLD = 0xE3 self.TRIGGER_HUMD_MEASURE_HOLD = 0xE5 self.SHIFTED_DIVISOR = (2**8 + 2**5 + 2**4 + 1)<<15 self.READ_USER_REG = 0xE7 self.WRITE_USER_REG = 0xE6 self.SOFT_RESET = 0xFE self.RH12_TEMP14 = 0b00000000 self.RH08_TEMP12 = 0b00000001 self.RH10_TEMP13 = 0b10000000 self.RH11_TEMP11 = 0b10000001 def readTemp(self): buf = bytes([self.TRIGGER_TEMP_MEASURE_HOLD]) i2c.write(self.HTDU21D_ADDRESS, buf) msb, lsb, crc = i2c.read(self.HTDU21D_ADDRESS, 3) crcResult = self.__check_crc(msb, lsb, crc) raw = (msb<<8 | lsb) & 0xfffc temp = -46.85 + 175.72 * raw / 65536.0 return temp if crcResult == 0 else crcResult def readHumid(self): buf = bytes([self.TRIGGER_HUMD_MEASURE_HOLD]) i2c.write(self.HTDU21D_ADDRESS, buf) msb, lsb, crc = i2c.read(self.HTDU21D_ADDRESS, 3) crcResult = self.__check_crc(msb, lsb, crc) raw = (msb<<8 | lsb) & 0xfffc humid = -6.0 + 125.0 * raw / 65536.0 return humid if crcResult == 0 else crcResult def __check_crc(self, msb, lsb, crc): divisor = self.SHIFTED_DIVISOR remainder = msb<<16 | lsb<<8 | crc for i in range(23, 7, -1): if remainder & 1<<i: remainder ^= divisor divisor >>= 1 return 0 if remainder == 0 else 999 def readUserRegister(self): buf = bytes([self.READ_USER_REG]) i2c.write(self.HTDU21D_ADDRESS, buf) return i2c.read(self.HTDU21D_ADDRESS, 1) def setResolution(self, resolution): userRegister = self.readUserRegister()[0] userRegister &= 0b01111110 resolution &= 0b10000001 userRegister |= resolution buf = bytes([self.WRITE_USER_REG, userRegister]) i2c.write(self.HTDU21D_ADDRESS, buf) def softReset(self): buf = bytes([self.SOFT_RESET]) i2c.write(self.HTDU21D_ADDRESS, buf) ############## # how to use # ############## if __name__ == "__main__": HTU = HTU21D() # Instantiate the HTU21D class. #HTU.softReset() # To soft-reset the HTU21D, uncomment this line. #HTU.setResolution(HTU.RH12_TEMP14) # You can select one of the four resolutions. #HTU.setResolution(HTU.RH08_TEMP12) #HTU.setResolution(HTU.RH10_TEMP13) #HTU.setResolution(HTU.RH11_TEMP11) while True: #print(HTU.readUserRegister()) # To serial.print() the user register, uncomment this line. temp = HTU.readTemp() humid = HTU.readHumid() print("%.1f C, %.1f %%" % (temp, humid)) sleep(1000)