mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 10:38:41 +00:00
aht20: add device
This commit is contained in:
@@ -187,6 +187,8 @@ endif
|
|||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/ina260/main.go
|
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/ina260/main.go
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
|
tinygo build -size short -o ./build/test.hex -target=nucleo-l432kc ./examples/aht20/main.go
|
||||||
|
@md5sum ./build/test.hex
|
||||||
|
|
||||||
DRIVERS = $(wildcard */)
|
DRIVERS = $(wildcard */)
|
||||||
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ The following 62 devices are supported.
|
|||||||
|----------|-------------|
|
|----------|-------------|
|
||||||
| [ADT7410 I2C Temperature Sensor](https://www.analog.com/media/en/technical-documentation/data-sheets/ADT7410.pdf) | I2C |
|
| [ADT7410 I2C Temperature Sensor](https://www.analog.com/media/en/technical-documentation/data-sheets/ADT7410.pdf) | I2C |
|
||||||
| [ADXL345 accelerometer](http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf) | I2C |
|
| [ADXL345 accelerometer](http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf) | I2C |
|
||||||
|
| [AHT20 I2C Temperature and Humidity Sensor](http://www.aosong.com/userfiles/files/media/AHT20%20%E8%8B%B1%E6%96%87%E7%89%88%E8%AF%B4%E6%98%8E%E4%B9%A6%20A0%2020201222.pdf) | I2C |
|
||||||
| [AMG88xx 8x8 Thermal camera sensor](https://cdn-learn.adafruit.com/assets/assets/000/043/261/original/Grid-EYE_SPECIFICATIONS%28Reference%29.pdf) | I2C |
|
| [AMG88xx 8x8 Thermal camera sensor](https://cdn-learn.adafruit.com/assets/assets/000/043/261/original/Grid-EYE_SPECIFICATIONS%28Reference%29.pdf) | I2C |
|
||||||
| [APA102 RGB LED](https://cdn-shop.adafruit.com/product-files/2343/APA102C.pdf) | SPI |
|
| [APA102 RGB LED](https://cdn-shop.adafruit.com/product-files/2343/APA102C.pdf) | SPI |
|
||||||
| [AT24CX 2-wire serial EEPROM](https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/24C32-Datasheet.pdf) | I2C |
|
| [AT24CX 2-wire serial EEPROM](https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/24C32-Datasheet.pdf) | I2C |
|
||||||
|
|||||||
+108
@@ -0,0 +1,108 @@
|
|||||||
|
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&0x08 == 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]&0x04 != 0 && data[0]&0x80 == 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
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package aht20
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
qt "github.com/frankban/quicktest"
|
||||||
|
"tinygo.org/x/drivers/tester"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDefaultI2CAddress(t *testing.T) {
|
||||||
|
c := qt.New(t)
|
||||||
|
bus := tester.NewI2CBus(c)
|
||||||
|
dev := New(bus)
|
||||||
|
c.Assert(uint8(dev.Address), qt.Equals, uint8(Address))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInitialization(t *testing.T) {
|
||||||
|
c := qt.New(t)
|
||||||
|
bus := tester.NewI2CBus(c)
|
||||||
|
fdev := tester.NewI2CDeviceCmd(c, Address)
|
||||||
|
fdev.Commands = defaultCommands()
|
||||||
|
bus.AddDevice(fdev)
|
||||||
|
|
||||||
|
// Set status to uninitialized to force initialization
|
||||||
|
fdev.Commands[CMD_STATUS].Response[0] = 0x0C
|
||||||
|
|
||||||
|
dev := New(bus)
|
||||||
|
dev.Configure()
|
||||||
|
|
||||||
|
// Check initialization command invoked
|
||||||
|
c.Assert(fdev.Commands[CMD_INITIALIZE].Invocations > 0, qt.Equals, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRead(t *testing.T) {
|
||||||
|
c := qt.New(t)
|
||||||
|
bus := tester.NewI2CBus(c)
|
||||||
|
fdev := tester.NewI2CDeviceCmd(c, Address)
|
||||||
|
fdev.Commands = defaultCommands()
|
||||||
|
bus.AddDevice(fdev)
|
||||||
|
|
||||||
|
dev := New(bus)
|
||||||
|
dev.Read()
|
||||||
|
|
||||||
|
// Should be 25deg (250 decidegrees)
|
||||||
|
c.Assert(dev.DeciCelsius(), qt.Equals, int32(250))
|
||||||
|
|
||||||
|
// Should be 36.3% (363 decipercent)
|
||||||
|
c.Assert(dev.DeciRelHumidity(), qt.Equals, int32(363))
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultCommands() map[uint8]*tester.Cmd {
|
||||||
|
return map[uint8]*tester.Cmd{
|
||||||
|
CMD_INITIALIZE: {
|
||||||
|
Command: []byte{0xBE},
|
||||||
|
Mask: []byte{0xFF},
|
||||||
|
Response: []byte{},
|
||||||
|
},
|
||||||
|
CMD_TRIGGER: {
|
||||||
|
Command: []byte{0xAC, 0x33, 0x00},
|
||||||
|
Mask: []byte{0xFF, 0xFF, 0xFF},
|
||||||
|
Response: []byte{0x1C, 0x5D, 0x10, 0x66, 0x01, 0xD2, 0x93},
|
||||||
|
},
|
||||||
|
CMD_SOFTRESET: {
|
||||||
|
Command: []byte{0xBA},
|
||||||
|
Mask: []byte{0xFF},
|
||||||
|
Response: []byte{},
|
||||||
|
},
|
||||||
|
CMD_STATUS: {
|
||||||
|
Command: []byte{0x71},
|
||||||
|
Mask: []byte{0xFF},
|
||||||
|
Response: []byte{0x1C},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package aht20
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
const (
|
||||||
|
Address = 0x38
|
||||||
|
|
||||||
|
CMD_INITIALIZE = 0xBE
|
||||||
|
CMD_STATUS = 0x71
|
||||||
|
CMD_TRIGGER = 0xAC
|
||||||
|
CMD_SOFTRESET = 0xBA
|
||||||
|
|
||||||
|
STATUS_BUSY = 0x80
|
||||||
|
STATUS_CALIBRATED = 0x08
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrBusy = errors.New("device busy")
|
||||||
|
ErrTimeout = errors.New("timeout")
|
||||||
|
)
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/aht20"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
machine.I2C0.Configure(machine.I2CConfig{})
|
||||||
|
|
||||||
|
dev := aht20.New(machine.I2C0)
|
||||||
|
dev.Configure()
|
||||||
|
|
||||||
|
dev.Reset()
|
||||||
|
for {
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
|
||||||
|
err := dev.Read()
|
||||||
|
if err != nil {
|
||||||
|
println("Error", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
println("temp ", fmtD(dev.DeciCelsius(), 3, 1), "C")
|
||||||
|
println("humidity", fmtD(dev.DeciRelHumidity(), 3, 1), "%")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fmtD(val int32, i int, f int) string {
|
||||||
|
result := make([]byte, i+f+1)
|
||||||
|
neg := false
|
||||||
|
|
||||||
|
if val < 0 {
|
||||||
|
val = -val
|
||||||
|
neg = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for p := len(result) - 1; p >= 0; p-- {
|
||||||
|
result[p] = byte(int32('0') + (val % 10))
|
||||||
|
val = val / 10
|
||||||
|
|
||||||
|
if p == i+1 && p > 0 {
|
||||||
|
p--
|
||||||
|
result[p] = '.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if neg {
|
||||||
|
result[0] = '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(result)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user