package main import ( "errors" "machine" "time" "tinygo.org/x/drivers/bme280" "tinygo.org/x/drivers/sht4x" ) type ClimateSensor interface { ReadValues() (temp float64, pres float64, hum float64, hasPres bool, err error) Name() string } // ------------------------------------------------------------- // BME280 Adapter // ------------------------------------------------------------- type BME280Adapter struct { dev bme280.Device } func (b *BME280Adapter) ReadValues() (float64, float64, float64, bool, error) { // ReadTemperature returns milli-°C (e.g. 25000 = 25.00°C) tMilli, err := b.dev.ReadTemperature() if err != nil { return 0, 0, 0, false, err } // ReadPressure returns milli-Pa (divide by 100,000 for hPa) pMilli, err := b.dev.ReadPressure() if err != nil { return 0, 0, 0, false, err } // ReadHumidity returns 100 * % (e.g. 4500 = 45.00%) hPct, err := b.dev.ReadHumidity() if err != nil { return 0, 0, 0, false, err } temp := float64(tMilli) / 1000.0 pres := float64(pMilli) / 100000.0 hum := float64(hPct) / 100.0 return temp, pres, hum, true, nil } func (b *BME280Adapter) Name() string { return "BME280" } // ------------------------------------------------------------- // SHT41 Adapter // ------------------------------------------------------------- type SHT41Adapter struct { dev sht4x.Device } func (s *SHT41Adapter) ReadValues() (float64, float64, float64, bool, error) { // ReadTemperatureHumidity takes no parameters. // Returns temp in milli-°C and humidity in milli-% (divide by 1000.0) tMilli, hMilli, err := s.dev.ReadTemperatureHumidity() if err != nil { return 0, 0, 0, false, err } temp := float64(tMilli) / 1000.0 hum := float64(hMilli) / 1000.0 return temp, 0, hum, false, nil } func (s *SHT41Adapter) Name() string { return "SHT41" } // ------------------------------------------------------------- // Factory // ------------------------------------------------------------- func InitSensor(i2c *machine.I2C, sensorType string) (ClimateSensor, error) { // Give the sensors a split-second to wake up before trying to register them time.Sleep(100 * time.Millisecond) switch sensorType { case "bme280": dev := bme280.New(i2c) dev.Configure() if !dev.Connected() { return nil, errors.New("BME280 not found on I2C bus") } return &BME280Adapter{dev: dev}, nil case "sht41": dev := sht4x.New(i2c) dev.Address = 0x45 // Default is 0x44 (sht4x.Address) if _, _, err := dev.ReadTemperatureHumidity(); err != nil { // Try fallback back to 0x44 dev.Address = 0x44 if _, _, err := dev.ReadTemperatureHumidity(); err != nil { return nil, errors.New("SHT41 not found at 0x44 or 0x45") } } return &SHT41Adapter{dev: dev}, nil default: return nil, errors.New("unsupported sensor configured") } }