mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-27 02:58:41 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c1aaa9a9f | |||
| 3f4a9d82f7 | |||
| 19c9fe6db3 | |||
| 315dbef694 | |||
| ee3842f639 |
+144
@@ -0,0 +1,144 @@
|
||||
// Package dht20 implements a driver for the DHT20 temperature and humidity sensor.
|
||||
//
|
||||
// Datasheet: https://cdn-shop.adafruit.com/product-files/5183/5193_DHT20.pdf
|
||||
|
||||
package dht20
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
var (
|
||||
errUpdateCalledTooSoon = errors.New("Update() called within 80ms is invalid")
|
||||
)
|
||||
|
||||
// Device wraps an I2C connection to a DHT20 device.
|
||||
type Device struct {
|
||||
bus drivers.I2C
|
||||
Address uint16
|
||||
data [8]uint8
|
||||
temperature float32
|
||||
humidity float32
|
||||
prevAccessTime time.Time
|
||||
}
|
||||
|
||||
// New creates a new DHT20 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: defaultAddress, // Using the address defined in registers.go
|
||||
}
|
||||
}
|
||||
|
||||
// Configure sets up the device for communication and initializes the registers if needed.
|
||||
func (d *Device) Configure() error {
|
||||
// Get the status word
|
||||
d.data[0] = 0x71
|
||||
err := d.bus.Tx(d.Address, d.data[:1], d.data[:1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if d.data[0] != 0x18 {
|
||||
// Initialize registers
|
||||
err := d.initRegisters()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Set the previous access time to the current time
|
||||
d.prevAccessTime = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
// initRegisters initializes the registers 0x1B, 0x1C, and 0x1E to 0x00.
|
||||
func (d *Device) initRegisters() error {
|
||||
// Initialize register 0x1B
|
||||
d.data[0] = 0x1B
|
||||
d.data[1] = 0x00
|
||||
err := d.bus.Tx(d.Address, d.data[:2], nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Initialize register 0x1C
|
||||
d.data[0] = 0x1C
|
||||
d.data[1] = 0x00
|
||||
err = d.bus.Tx(d.Address, d.data[:2], nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Initialize register 0x1E
|
||||
d.data[0] = 0x1E
|
||||
d.data[1] = 0x00
|
||||
err = d.bus.Tx(d.Address, d.data[:2], nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update reads data from the sensor and updates the temperature and humidity values.
|
||||
// Note that the values obtained by this function are from the previous call to Update.
|
||||
// If you want to use the most recent values, shorten the interval at which Update is called.
|
||||
func (d *Device) Update(which drivers.Measurement) error {
|
||||
if which&drivers.Temperature == 0 && which&drivers.Humidity == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if 80ms have passed since the last access
|
||||
if time.Since(d.prevAccessTime) < 80*time.Millisecond {
|
||||
return errUpdateCalledTooSoon
|
||||
}
|
||||
|
||||
// Check the status word Bit[7]
|
||||
d.data[0] = 0x71
|
||||
err := d.bus.Tx(d.Address, d.data[:1], d.data[:1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (d.data[0] & 0x80) == 0 {
|
||||
// Read 7 bytes of data from the sensor
|
||||
err := d.bus.Tx(d.Address, nil, d.data[:7])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rawHumidity := uint32(d.data[1])<<12 | uint32(d.data[2])<<4 | uint32(d.data[3])>>4
|
||||
rawTemperature := uint32(d.data[3]&0x0F)<<16 | uint32(d.data[4])<<8 | uint32(d.data[5])
|
||||
|
||||
// Convert raw values to human-readable values
|
||||
d.humidity = float32(rawHumidity) / 1048576.0 * 100
|
||||
d.temperature = float32(rawTemperature)/1048576.0*200 - 50
|
||||
|
||||
// Trigger the next measurement
|
||||
d.data[0] = 0xAC
|
||||
d.data[1] = 0x33
|
||||
d.data[2] = 0x00
|
||||
err = d.bus.Tx(d.Address, d.data[:3], nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update the previous access time to the current time
|
||||
d.prevAccessTime = time.Now()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Temperature returns the last measured temperature.
|
||||
func (d *Device) Temperature() float32 {
|
||||
return d.temperature
|
||||
}
|
||||
|
||||
// Humidity returns the last measured humidity.
|
||||
func (d *Device) Humidity() float32 {
|
||||
return d.humidity
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package dht20
|
||||
|
||||
// Constants/addresses used for I2C.
|
||||
|
||||
// The I2C address which this device listens to.
|
||||
const defaultAddress = 0x38
|
||||
@@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
"tinygo.org/x/drivers/dht20"
|
||||
)
|
||||
|
||||
var (
|
||||
i2c = machine.I2C0
|
||||
)
|
||||
|
||||
func main() {
|
||||
i2c.Configure(machine.I2CConfig{})
|
||||
sensor := dht20.New(i2c)
|
||||
sensor.Configure()
|
||||
|
||||
// Trigger the first measurement
|
||||
sensor.Update(drivers.AllMeasurements)
|
||||
|
||||
for {
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// Update sensor dasta
|
||||
sensor.Update(drivers.AllMeasurements)
|
||||
temp := sensor.Temperature()
|
||||
hum := sensor.Humidity()
|
||||
|
||||
// Note: The sensor values are from the previous measurement (1 second ago)
|
||||
println("Temperature:", strconv.FormatFloat(float64(temp), 'f', 2, 64), "°C")
|
||||
println("Humidity:", strconv.FormatFloat(float64(hum), 'f', 2, 64), "%")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Connects to a pcf8591 ADC via I2C.
|
||||
package main
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/drivers/pcf8591"
|
||||
)
|
||||
|
||||
var (
|
||||
i2c = machine.I2C0
|
||||
)
|
||||
|
||||
func main() {
|
||||
i2c.Configure(machine.I2CConfig{})
|
||||
adc := pcf8591.New(i2c)
|
||||
adc.Configure()
|
||||
|
||||
// get "CH0" aka "machine.ADC" interface to channel 0 from ADC.
|
||||
p := adc.CH0
|
||||
|
||||
for {
|
||||
val := p.Get()
|
||||
println(val)
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
// Package pcf8591 implements a driver for the PCF8591 Analog to Digital/Digital to Analog Converter.
|
||||
//
|
||||
// Datasheet: https://www.nxp.com/docs/en/data-sheet/PCF8591.pdf
|
||||
package pcf8591 // import "tinygo.org/x/drivers/pcf8591"
|
||||
|
||||
import (
|
||||
"machine"
|
||||
|
||||
"errors"
|
||||
|
||||
"tinygo.org/x/drivers"
|
||||
)
|
||||
|
||||
// Device wraps PCF8591 ADC functions.
|
||||
type Device struct {
|
||||
bus drivers.I2C
|
||||
Address uint16
|
||||
CH0 ADCPin
|
||||
CH1 ADCPin
|
||||
CH2 ADCPin
|
||||
CH3 ADCPin
|
||||
}
|
||||
|
||||
// ADCPin is the implementation of the ADConverter interface.
|
||||
type ADCPin struct {
|
||||
machine.Pin
|
||||
d *Device
|
||||
}
|
||||
|
||||
// New returns a new PCF8591 driver. Pass in a fully configured I2C bus.
|
||||
func New(b drivers.I2C) *Device {
|
||||
d := &Device{
|
||||
bus: b,
|
||||
Address: defaultAddress,
|
||||
}
|
||||
|
||||
// setup all channels
|
||||
d.CH0 = d.GetADC(0)
|
||||
d.CH1 = d.GetADC(1)
|
||||
d.CH2 = d.GetADC(2)
|
||||
d.CH3 = d.GetADC(3)
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// Configure here just for interface compatibility.
|
||||
func (d *Device) Configure() {
|
||||
}
|
||||
|
||||
// Read analog data from channel
|
||||
func (d *Device) Read(ch int) (uint16, error) {
|
||||
if ch < 0 || ch > 3 {
|
||||
return 0, errors.New("invalid channel for pcf8591 Read")
|
||||
}
|
||||
|
||||
return d.GetADC(ch).Get(), nil
|
||||
}
|
||||
|
||||
// GetADC returns an ADC for a specific channel.
|
||||
func (d *Device) GetADC(ch int) ADCPin {
|
||||
return ADCPin{machine.Pin(ch), d}
|
||||
}
|
||||
|
||||
// Get the current reading for a specific ADCPin.
|
||||
func (p ADCPin) Get() uint16 {
|
||||
// TODO: also implement DAC
|
||||
tx := make([]byte, 2)
|
||||
tx[0] = byte(p.Pin)
|
||||
|
||||
rx := make([]byte, 2)
|
||||
|
||||
// The result from the measurement triggered by the first write,
|
||||
// however, the second write is required to get the result.
|
||||
// See section 8.4 "A/D Conversion" in the datasheet for more info
|
||||
p.d.bus.Tx(p.d.Address, tx, rx)
|
||||
p.d.bus.Tx(p.d.Address, tx, rx)
|
||||
|
||||
// scale result to 16bit value like other ADCs
|
||||
return uint16(rx[1] << 8)
|
||||
}
|
||||
|
||||
// Configure here just for interface compatibility.
|
||||
func (p ADCPin) Configure() {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package pcf8591
|
||||
|
||||
// PCF8591 Default Address
|
||||
const defaultAddress = 0x48
|
||||
|
||||
// control bit for DAC
|
||||
const PCF8591_ENABLE_DAC = 0x40
|
||||
@@ -99,6 +99,7 @@ tinygo build -size short -o ./build/test.hex -target=hifive1b ./examples/ssd1351
|
||||
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/lis2mdl/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/max72xx/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/dht/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/dht20/main.go
|
||||
# tinygo build -size short -o ./build/test.hex -target=arduino ./examples/keypad4x4/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=feather-rp2040 ./examples/pcf8523/
|
||||
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/alarm/
|
||||
@@ -106,6 +107,7 @@ tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/clk
|
||||
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/time/
|
||||
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/timer/
|
||||
tinygo build -size short -o ./build/test.hex -target=pico ./examples/qmi8658c/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=feather-rp2040 ./examples/pcf8591/
|
||||
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/ina260/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=nucleo-l432kc ./examples/aht20/main.go
|
||||
tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/sdcard/console/
|
||||
|
||||
Reference in New Issue
Block a user