From 1d0f04af6b533decb08218eeab50680edc7326f0 Mon Sep 17 00:00:00 2001 From: BCG Date: Thu, 26 Dec 2019 07:53:06 -0500 Subject: [PATCH] Support for ADT7410 temperature sensor (#109) * ADT7410: add support for i2c temperature sensor --- Makefile | 2 + README.md | 1 + adt7410/adt7410.go | 90 ++++++++++++++++++++++++++++++++++++++++ adt7410/registers.go | 24 +++++++++++ examples/adt7410/main.go | 27 ++++++++++++ 5 files changed, 144 insertions(+) create mode 100644 adt7410/adt7410.go create mode 100644 adt7410/registers.go create mode 100644 examples/adt7410/main.go diff --git a/Makefile b/Makefile index fc1a11c..7a4c86e 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,8 @@ fmt-check: smoke-test: @mkdir -p build + tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adt7410/main.go + @md5sum ./build/test.hex tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adxl345/main.go @md5sum ./build/test.hex tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/main.go diff --git a/README.md b/README.md index 18914bd..4601fb3 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ The following 35 devices are supported. | Device Name | Interface Type | |----------|-------------| +| [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 | | [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 | diff --git a/adt7410/adt7410.go b/adt7410/adt7410.go new file mode 100644 index 0000000..bdd6c6d --- /dev/null +++ b/adt7410/adt7410.go @@ -0,0 +1,90 @@ +package adt7410 + +import ( + "machine" + "time" +) + +type Error uint8 + +const ( + ErrInvalidID Error = 0x1 +) + +func (e Error) Error() string { + switch e { + case ErrInvalidID: + return "Invalid chip ID" + default: + return "Unknown error" + } +} + +type Device struct { + bus *machine.I2C + buf []byte + addr uint8 +} + +// New returns ADT7410 device for the provided I2C bus and address. The ADT7410 +// has a default address of 0x48 (1001000). The last 2 bits of the address +// can be set using by connecting to the A1 and A0 pins to VDD or GND (for a +// total of up to 4 devices on a I2C bus). Also note that 10k pullups are +// recommended for the SDA and SCL lines. +func New(i2c *machine.I2C, addressBits uint8) *Device { + return &Device{ + bus: i2c, + buf: make([]byte, 2), + addr: Address | (addressBits & 0x3), + } +} + +func (dev *Device) Configure() (err error) { + + // verify the chip ID + // TODO: According to datasheet, the check below should work; however + // this does not seem to be working right, but is not exactly + // necessary, so can revisit later to see if there is a bug + //id := dev.ReadByte(RegID) & 0xF8 + //if id != 0xC8 { + // err = ErrInvalidID + //} + + // reset the chip + dev.writeByte(RegReset, 0xFF) + time.Sleep(10 * time.Millisecond) + return + +} + +// ReadTemperature returns the temperature in celsius milli degrees (ÂșC/1000) +func (d *Device) ReadTemperature() (temperature int32, err error) { + return (int32(d.readUint16(RegTempValueMSB)) * 1000) / 128, nil +} + +// ReadTempC returns the value in the temperature value register, in Celcius +func (d *Device) ReadTempC() float32 { + t := d.readUint16(RegTempValueMSB) + return float32(int(t)) / 128.0 +} + +// ReadTempF returns the value in the temperature value register, in Fahrenheit +func (d *Device) ReadTempF() float32 { + return d.ReadTempC()*1.8 + 32.0 +} + +func (d *Device) writeByte(reg uint8, data byte) { + d.buf[0] = reg + d.buf[1] = data + d.bus.Tx(uint16(d.addr), d.buf, nil) +} + +func (d *Device) readByte(reg uint8) byte { + d.bus.ReadRegister(d.addr, reg, d.buf) + return d.buf[0] +} + +func (d *Device) readUint16(reg uint8) uint16 { + d.bus.ReadRegister(d.addr, reg, d.buf) + return uint16(d.buf[0])<<8 | uint16(d.buf[1]) +} diff --git a/adt7410/registers.go b/adt7410/registers.go new file mode 100644 index 0000000..c9fe7a5 --- /dev/null +++ b/adt7410/registers.go @@ -0,0 +1,24 @@ +package adt7410 + +const ( + // Default I2C address + Address = 0x48 + + // Temperature Value MSB Register + RegTempValueMSB = 0x0 + + // Temperature Value LSB Register + RegTempValueLSB = 0x1 + + // Status Register + RegStatus = 0x2 + + // Config Register + RegConfig = 0x3 + + // ID Register + RegID = 0x0B + + // Software Reset Register + RegReset = 0x2F +) diff --git a/examples/adt7410/main.go b/examples/adt7410/main.go new file mode 100644 index 0000000..03010d7 --- /dev/null +++ b/examples/adt7410/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "fmt" + "machine" + "time" + + "tinygo.org/x/drivers/adt7410" +) + +var ( + i2c = &machine.I2C0 + sensor = adt7410.New(i2c, 0) +) + +func main() { + + i2c.Configure(machine.I2CConfig{Frequency: machine.TWI_FREQ_400KHZ}) + sensor.Configure() + + for { + temp := sensor.ReadTempF() + fmt.Printf("temperature: %f\r\n", temp) + time.Sleep(time.Second) + } + +}