package aht20 import ( "time" "tinygo.org/x/drivers" ) // Device wraps an I2C connection to an AHT20 device. type Device struct { bus drivers.I2C Address uint16 humidity uint32 temp uint32 } // New creates a new AHT20 connection. The I2C bus must already be // configured. // // This function only creates the Device object, it does not touch the device. func New(bus drivers.I2C) Device { return Device{ bus: bus, Address: Address, } } // Configure the device func (d *Device) Configure() { // Check initialization state status := d.Status() if status&STATUS_CALIBRATED == 1 { // Device is initialized return } // Force initialization d.bus.Tx(d.Address, []byte{CMD_INITIALIZE, 0x08, 0x00}, nil) time.Sleep(10 * time.Millisecond) } // Reset the device func (d *Device) Reset() { d.bus.Tx(d.Address, []byte{CMD_SOFTRESET}, nil) } // Status of the device func (d *Device) Status() byte { data := []byte{0} d.bus.Tx(d.Address, []byte{CMD_STATUS}, data) return data[0] } // Read the temperature and humidity // // The actual temperature and humidity are stored // and can be accessed using `Temp` and `Humidity`. func (d *Device) Read() error { d.bus.Tx(d.Address, []byte{CMD_TRIGGER, 0x33, 0x00}, nil) data := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} for retry := 0; retry < 3; retry++ { time.Sleep(80 * time.Millisecond) err := d.bus.Tx(d.Address, nil, data) if err != nil { return err } // If measurement complete, store values if data[0]&STATUS_CALIBRATED != 0 && data[0]&STATUS_BUSY == 0 { d.humidity = uint32(data[1])<<12 | uint32(data[2])<<4 | uint32(data[3])>>4 d.temp = (uint32(data[3])&0xF)<<16 | uint32(data[4])<<8 | uint32(data[5]) return nil } } return ErrTimeout } func (d *Device) RawHumidity() uint32 { return d.humidity } func (d *Device) RawTemp() uint32 { return d.temp } func (d *Device) RelHumidity() float32 { return (float32(d.humidity) * 100) / 0x100000 } func (d *Device) DeciRelHumidity() int32 { return (int32(d.humidity) * 1000) / 0x100000 } // Temperature in degrees celsius func (d *Device) Celsius() float32 { return (float32(d.temp*200.0) / 0x100000) - 50 } // Temperature in mutiples of one tenth of a degree celsius // // Using this method avoids floating point calculations. func (d *Device) DeciCelsius() int32 { return ((int32(d.temp) * 2000) / 0x100000) - 500 }