From 6763521eff84ed1219c30b9b26fd71dd16547bec Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Thu, 21 Oct 2021 23:17:32 +0200 Subject: [PATCH] all: introduce a temperature type This type should be used whenever a sensor (or actuator?) works with a temperature. For example, this commit changes the signature: ReadTemperature() (int32, error) to the following: ReadTemperature() (drivers.Temperature, error) I believe this is much clearer in intent. It also makes it trivial to introduce common conversions. For example, there are already Celsius() and Fahrenheit() methods to convert to the given units, as a floating point. More units could be added as needed, for example a CelsiusInt(). --- Makefile | 2 +- adt7410/adt7410.go | 15 ++------------- bme280/bme280.go | 4 ++-- bmi160/bmi160.go | 4 ++-- bmp180/bmp180.go | 4 ++-- bmp280/bmp280.go | 4 ++-- bmp388/bmp388.go | 8 ++++---- dht/constants.go | 15 --------------- dht/thermometer.go | 21 ++++++--------------- dht/timesafethermometer.go | 17 ++++------------- ds3231/ds3231.go | 4 ++-- examples/adt7410/main.go | 4 ++-- examples/bme280/main.go | 2 +- examples/bmi160/main.go | 2 +- examples/bmp180/main.go | 2 +- examples/bmp280/main.go | 2 +- examples/bmp388/main.go | 4 ++-- examples/ds3231/main.go | 2 +- examples/lsm6ds3/main.go | 4 ++-- examples/lsm6dsox/main.go | 5 +++-- examples/mag3110/main.go | 2 +- examples/tmp102/main.go | 2 +- lsm303agr/lsm303agr.go | 4 ++-- lsm6ds3/lsm6ds3.go | 4 ++-- lsm6dsox/lsm6dsox.go | 4 ++-- mag3110/mag3110.go | 4 ++-- sht3x/sht3x.go | 10 +++++----- thermistor/thermistor.go | 6 ++++-- tmp102/tmp102.go | 6 +++--- units.go | 17 +++++++++++++++++ units_test.go | 26 ++++++++++++++++++++++++++ 31 files changed, 106 insertions(+), 104 deletions(-) create mode 100644 units.go create mode 100644 units_test.go diff --git a/Makefile b/Makefile index f4526f22a..b8f9a43c3 100644 --- a/Makefile +++ b/Makefile @@ -214,6 +214,6 @@ NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 micropho TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS)) unit-test: - @go test -v $(addprefix ./,$(TESTS)) + @go test -v . $(addprefix ./,$(TESTS)) test: clean fmt-check unit-test smoke-test diff --git a/adt7410/adt7410.go b/adt7410/adt7410.go index 814e3a807..477504631 100644 --- a/adt7410/adt7410.go +++ b/adt7410/adt7410.go @@ -60,19 +60,8 @@ func (d *Device) Connected() bool { } // 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 Celsius. -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) ReadTemperature() (temperature drivers.Temperature, err error) { + return (drivers.Temperature(d.readUint16(RegTempValueMSB)) * 1000) / 128, nil } func (d *Device) writeByte(reg uint8, data byte) { diff --git a/bme280/bme280.go b/bme280/bme280.go index 3b2503231..b694e3f4f 100644 --- a/bme280/bme280.go +++ b/bme280/bme280.go @@ -114,14 +114,14 @@ func (d *Device) Reset() { } // ReadTemperature returns the temperature in celsius milli degrees (°C/1000) -func (d *Device) ReadTemperature() (int32, error) { +func (d *Device) ReadTemperature() (drivers.Temperature, error) { data, err := d.readData() if err != nil { return 0, err } temp, _ := d.calculateTemp(data) - return temp, nil + return drivers.Temperature(temp), nil } // ReadPressure returns the pressure in milli pascals mPa diff --git a/bmi160/bmi160.go b/bmi160/bmi160.go index cd3e88237..a6e82b2a4 100644 --- a/bmi160/bmi160.go +++ b/bmi160/bmi160.go @@ -81,7 +81,7 @@ func (d *DeviceSPI) Reset() error { } // ReadTemperature returns the temperature in celsius milli degrees (°C/1000). -func (d *DeviceSPI) ReadTemperature() (temperature int32, err error) { +func (d *DeviceSPI) ReadTemperature() (temperature drivers.Temperature, err error) { data := d.buf[:3] data[0] = 0x80 | reg_TEMPERATURE_0 data[1] = 0 @@ -109,7 +109,7 @@ func (d *DeviceSPI) ReadTemperature() (temperature int32, err error) { // rawTemperature * 1000 * 64 / 0x8000 + 23000 // rawTemperature * 64000 / 0x8000 + 23000 // rawTemperature * 125 / 64 + 23000 - temperature = int32(rawTemperature)*125/64 + 23000 + temperature = drivers.Temperature(rawTemperature)*125/64 + 23000 return } diff --git a/bmp180/bmp180.go b/bmp180/bmp180.go index 984c338f1..d42aad498 100644 --- a/bmp180/bmp180.go +++ b/bmp180/bmp180.go @@ -81,14 +81,14 @@ func (d *Device) Configure() { } // ReadTemperature returns the temperature in celsius milli degrees (°C/1000). -func (d *Device) ReadTemperature() (temperature int32, err error) { +func (d *Device) ReadTemperature() (temperature drivers.Temperature, err error) { rawTemp, err := d.rawTemp() if err != nil { return } b5 := d.calculateB5(rawTemp) t := (b5 + 8) >> 4 - return 100 * t, nil + return drivers.Temperature(100 * t), nil } // ReadPressure returns the pressure in milli pascals (mPa). diff --git a/bmp280/bmp280.go b/bmp280/bmp280.go index edd64da2e..00a36eb90 100644 --- a/bmp280/bmp280.go +++ b/bmp280/bmp280.go @@ -132,7 +132,7 @@ func (d *Device) PrintCali() { } // ReadTemperature returns the temperature in celsius milli degrees (°C/1000). -func (d *Device) ReadTemperature() (temperature int32, err error) { +func (d *Device) ReadTemperature() (temperature drivers.Temperature, err error) { data, err := d.readData(REG_TEMP, 3) if err != nil { return @@ -150,7 +150,7 @@ func (d *Device) ReadTemperature() (temperature int32, err error) { // Convert from degrees to milli degrees by multiplying by 10. // Will output 30250 milli degrees celsius for 30.25 degrees celsius - temperature = 10 * ((tFine*5 + 128) >> 8) + temperature = drivers.Temperature(10 * ((tFine*5 + 128) >> 8)) return } diff --git a/bmp388/bmp388.go b/bmp388/bmp388.go index 27b5cf605..5f4ead398 100644 --- a/bmp388/bmp388.go +++ b/bmp388/bmp388.go @@ -133,16 +133,16 @@ func (d *Device) tlinCompensate() (int64, error) { } -// ReadTemperature returns the temperature in centicelsius, i.e 2426 / 100 = 24.26 C -func (d *Device) ReadTemperature() (int32, error) { +// ReadTemperature returns the temperature in milli degrees Celsius, i.e 24260 / 1000 = 24.26°C. +func (d *Device) ReadTemperature() (drivers.Temperature, error) { tlin, err := d.tlinCompensate() if err != nil { return 0, err } - temp := (tlin * 25) / 16384 - return int32(temp), nil + temp := (tlin * 125) / 8192 + return drivers.Temperature(temp), nil } // ReadPressure returns the pressure in centipascals, i.e 10132520 / 100 = 101325.20 Pa diff --git a/dht/constants.go b/dht/constants.go index 8bed1a3c1..ff62d4135 100644 --- a/dht/constants.go +++ b/dht/constants.go @@ -35,18 +35,6 @@ func (d DeviceType) extractData(buf []byte) (temp int16, hum uint16) { return } -// Celsius and Fahrenheit temperature scales -type TemperatureScale uint8 - -func (t TemperatureScale) convertToFloat(temp int16) float32 { - if t == C { - return float32(temp) / 10 - } else { - // Fahrenheit - return float32(temp)*(9.0/50.) + 32. - } -} - // All functions return ErrorCode instance as error. This class can be used for more efficient error processing type ErrorCode uint8 @@ -57,9 +45,6 @@ const ( DHT11 DeviceType = iota DHT22 - C TemperatureScale = iota - F - ChecksumError ErrorCode = iota NoSignalError NoDataError diff --git a/dht/thermometer.go b/dht/thermometer.go index 2ee3d9339..03bf9b6a8 100644 --- a/dht/thermometer.go +++ b/dht/thermometer.go @@ -9,14 +9,15 @@ package dht // import "tinygo.org/x/drivers/dht" import ( "machine" "time" + + "tinygo.org/x/drivers" ) // DummyDevice provides a basic interface for DHT devices. type DummyDevice interface { ReadMeasurements() error Measurements() (temperature int16, humidity uint16, err error) - Temperature() (int16, error) - TemperatureFloat(scale TemperatureScale) (float32, error) + Temperature() (drivers.Temperature, error) Humidity() (uint16, error) HumidityFloat() (float32, error) } @@ -49,23 +50,13 @@ func (t *device) ReadMeasurements() error { return err } -// Getter for temperature. Temperature method returns temperature as it is sent by device. -// The temperature is measured temperature in Celsius multiplied by 10. -// If no successful measurements for this device was performed, returns UninitializedDataError. -func (t *device) Temperature() (int16, error) { - if !t.initialized { - return 0, UninitializedDataError - } - return t.temperature, nil -} - -// Getter for temperature. TemperatureFloat returns temperature in a given scale. +// Getter for temperature. The temperature is returned in milli degrees Celsius. // If no successful measurements for this device was performed, returns UninitializedDataError. -func (t *device) TemperatureFloat(scale TemperatureScale) (float32, error) { +func (t *device) Temperature() (drivers.Temperature, error) { if !t.initialized { return 0, UninitializedDataError } - return scale.convertToFloat(t.temperature), nil + return drivers.Temperature(t.temperature) * 100, nil } // Getter for humidity. Humidity returns humidity as it is sent by device. diff --git a/dht/timesafethermometer.go b/dht/timesafethermometer.go index 3c4ff4761..8d6ff256e 100644 --- a/dht/timesafethermometer.go +++ b/dht/timesafethermometer.go @@ -9,6 +9,8 @@ package dht // import "tinygo.org/x/drivers/dht" import ( "machine" "time" + + "tinygo.org/x/drivers" ) // Device interface provides main functionality of the DHTXX sensors. @@ -35,10 +37,9 @@ func (m *managedDevice) Measurements() (temperature int16, humidity uint16, err return m.t.Measurements() } -// Getter for temperature. Temperature method returns temperature as it is sent by device. -// The temperature is measured temperature in Celsius multiplied by 10. +// Getter for temperature. The temperature is returned in milli degrees Celsius. // Depending on the UpdatePolicy of the device may update cached measurements. -func (m *managedDevice) Temperature() (temp int16, err error) { +func (m *managedDevice) Temperature() (temp drivers.Temperature, err error) { err = m.checkForUpdateOnDataRequest() if err != nil { return 0, err @@ -64,16 +65,6 @@ func (m *managedDevice) checkForUpdateOnDataRequest() (err error) { return err } -// Getter for temperature. TemperatureFloat returns temperature in a given scale. -// Depending on the UpdatePolicy of the device may update cached measurements. -func (m *managedDevice) TemperatureFloat(scale TemperatureScale) (float32, error) { - err := m.checkForUpdateOnDataRequest() - if err != nil { - return 0, err - } - return m.t.TemperatureFloat(scale) -} - // Getter for humidity. Humidity returns humidity as it is sent by device. // The humidity is measured in percentages multiplied by 10. // Depending on the UpdatePolicy of the device may update cached measurements. diff --git a/ds3231/ds3231.go b/ds3231/ds3231.go index d29495b75..06935ffe8 100644 --- a/ds3231/ds3231.go +++ b/ds3231/ds3231.go @@ -134,13 +134,13 @@ func (d *Device) ReadTime() (dt time.Time, err error) { } // ReadTemperature returns the temperature in millicelsius (mC) -func (d *Device) ReadTemperature() (int32, error) { +func (d *Device) ReadTemperature() (drivers.Temperature, error) { data := make([]uint8, 2) err := d.bus.ReadRegister(uint8(d.Address), REG_TEMP, data) if err != nil { return 0, err } - return int32(data[0])*1000 + int32((data[1]>>6)*25)*10, nil + return drivers.Temperature(int32(data[0])*1000 + int32((data[1]>>6)*25)*10), nil } // uint8ToBCD converts a byte to BCD for the DS3231 diff --git a/examples/adt7410/main.go b/examples/adt7410/main.go index 132b77b6b..482bc2da9 100644 --- a/examples/adt7410/main.go +++ b/examples/adt7410/main.go @@ -19,8 +19,8 @@ func main() { sensor.Configure() for { - temp := sensor.ReadTempF() - fmt.Printf("temperature: %f\r\n", temp) + temp, _ := sensor.ReadTemperature() + fmt.Printf("temperature: %f°C\r\n", temp.Celsius()) time.Sleep(time.Second) } diff --git a/examples/bme280/main.go b/examples/bme280/main.go index 3b7d33357..65c3c9644 100644 --- a/examples/bme280/main.go +++ b/examples/bme280/main.go @@ -22,7 +22,7 @@ func main() { for { temp, _ := sensor.ReadTemperature() - println("Temperature:", strconv.FormatFloat(float64(temp)/1000, 'f', 2, 64), "°C") + println("Temperature:", strconv.FormatFloat(float64(temp.Celsius()), 'f', 2, 64), "°C") press, _ := sensor.ReadPressure() println("Pressure:", strconv.FormatFloat(float64(press)/100000, 'f', 2, 64), "hPa") hum, _ := sensor.ReadHumidity() diff --git a/examples/bmi160/main.go b/examples/bmi160/main.go index 364fef751..a363cb535 100644 --- a/examples/bmi160/main.go +++ b/examples/bmi160/main.go @@ -27,7 +27,7 @@ func main() { println("Error reading temperature", err) continue } - fmt.Printf("Temperature: %.2f °C\n", float32(t)/1000) + fmt.Printf("Temperature: %.2f °C\n", t.Celsius()) accelX, accelY, accelZ, err := sensor.ReadAcceleration() if err != nil { diff --git a/examples/bmp180/main.go b/examples/bmp180/main.go index 9b4e34de2..548d4bb46 100644 --- a/examples/bmp180/main.go +++ b/examples/bmp180/main.go @@ -22,7 +22,7 @@ func main() { for { temp, _ := sensor.ReadTemperature() - println("Temperature:", float32(temp)/1000, "°C") + println("Temperature:", temp.Celsius(), "°C") pressure, _ := sensor.ReadPressure() println("Pressure", float32(pressure)/100000, "hPa") diff --git a/examples/bmp280/main.go b/examples/bmp280/main.go index b88d2ba76..c97ec81f3 100644 --- a/examples/bmp280/main.go +++ b/examples/bmp280/main.go @@ -30,7 +30,7 @@ func main() { println("Error reading temperature") } // Temperature in degrees Celsius - fmt.Printf("Temperature: %.2f °C\n", float32(t)/1000) + fmt.Printf("Temperature: %.2f °C\n", t.Celsius()) p, err := sensor.ReadPressure() if err != nil { diff --git a/examples/bmp388/main.go b/examples/bmp388/main.go index 06bc9e212..52c8ec4bd 100644 --- a/examples/bmp388/main.go +++ b/examples/bmp388/main.go @@ -38,13 +38,13 @@ func main() { } for { - temp, err := sensor.ReadTemperature() // returns the temperature in centicelsius + temp, err := sensor.ReadTemperature() // returns the temperature in millicelsius press, err := sensor.ReadPressure() // returns the pressure in centipascals if err != nil { println(err) } else { - println("Temperature: " + strconv.FormatInt(int64(temp), 10) + " cC") + println("Temperature:", temp/1000, "C") println("Pressure: " + strconv.FormatInt(int64(press), 10) + " cPa\n") } diff --git a/examples/ds3231/main.go b/examples/ds3231/main.go index 7046a9d99..36e98cba7 100644 --- a/examples/ds3231/main.go +++ b/examples/ds3231/main.go @@ -38,7 +38,7 @@ func main() { fmt.Printf("Date: %d/%s/%02d %02d:%02d:%02d \r\n", dt.Year(), dt.Month(), dt.Day(), dt.Hour(), dt.Minute(), dt.Second()) } temp, _ := rtc.ReadTemperature() - fmt.Printf("Temperature: %.2f °C \r\n", float32(temp)/1000) + fmt.Printf("Temperature: %.2f °C \r\n", temp.Celsius()) time.Sleep(time.Second * 1) } diff --git a/examples/lsm6ds3/main.go b/examples/lsm6ds3/main.go index 88b85d138..2754a6049 100644 --- a/examples/lsm6ds3/main.go +++ b/examples/lsm6ds3/main.go @@ -23,8 +23,8 @@ func main() { println("Acceleration:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000) x, y, z = accel.ReadRotation() println("Gyroscope:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000) - x, _ = accel.ReadTemperature() - println("Degrees C", float32(x)/1000, "\n\n") + t, _ := accel.ReadTemperature() + println("Degrees C", t.Celsius(), "\n\n") time.Sleep(time.Millisecond * 1000) } } diff --git a/examples/lsm6dsox/main.go b/examples/lsm6dsox/main.go index e962d29db..1041c859e 100644 --- a/examples/lsm6dsox/main.go +++ b/examples/lsm6dsox/main.go @@ -6,6 +6,7 @@ import ( "machine" "time" + "tinygo.org/x/drivers" "tinygo.org/x/drivers/lsm6dsox" ) @@ -76,7 +77,7 @@ func calibrateGyro(device *lsm6dsox.Device) { } // Arduino IDE's Serial Plotter -func printPlotter(ax, ay, az, gx, gy, gz, t int32) { +func printPlotter(ax, ay, az, gx, gy, gz int32, t drivers.Temperature) { if SHOW_ACCELERATION { fmt.Printf("AX:%f, AY:%f, AZ:%f,", axis(ax, 0), axis(ay, 0), axis(az, 0)) } @@ -84,7 +85,7 @@ func printPlotter(ax, ay, az, gx, gy, gz, t int32) { fmt.Printf("GX:%f, GY:%f, GZ:%f,", axis(gx, cal[0]), axis(gy, cal[1]), axis(gz, cal[2])) } if SHOW_TEMPERATURE { - fmt.Printf("T:%f", float32(t)/1000) + fmt.Printf("T:%f", t.Celsius()) } println() } diff --git a/examples/mag3110/main.go b/examples/mag3110/main.go index 34f12ae97..074575e80 100644 --- a/examples/mag3110/main.go +++ b/examples/mag3110/main.go @@ -19,7 +19,7 @@ func main() { println("Magnetic readings:", x, y, z) c, _ := mag.ReadTemperature() - println("Temperature:", float32(c)/1000, "°C") + println("Temperature:", c.Celsius(), "°C") time.Sleep(time.Millisecond * 100) } diff --git a/examples/tmp102/main.go b/examples/tmp102/main.go index 5d764b42a..2fd40f0e3 100644 --- a/examples/tmp102/main.go +++ b/examples/tmp102/main.go @@ -20,7 +20,7 @@ func main() { temp, _ := thermo.ReadTemperature() - print(fmt.Sprintf("%.2f°C\r\n", float32(temp)/1000.0)) + print(fmt.Sprintf("%.2f°C\r\n", temp.Celsius())) time.Sleep(time.Millisecond * 1000) } diff --git a/lsm303agr/lsm303agr.go b/lsm303agr/lsm303agr.go index 665a7e997..668de0dcf 100644 --- a/lsm303agr/lsm303agr.go +++ b/lsm303agr/lsm303agr.go @@ -191,14 +191,14 @@ func (d *Device) ReadCompass() (h int32) { } // ReadTemperature returns the temperature in Celsius milli degrees (°C/1000) -func (d *Device) ReadTemperature() (c int32, e error) { +func (d *Device) ReadTemperature() (c drivers.Temperature, e error) { data1, data2 := []byte{0}, []byte{0} d.bus.ReadRegister(uint8(d.AccelAddress), OUT_TEMP_H_A, data1) d.bus.ReadRegister(uint8(d.AccelAddress), OUT_TEMP_L_A, data2) t := int16((uint16(data1[0])<<8 | uint16(data2[0]))) >> 4 // temperature offsef from 25 °C - c = int32((float32(25) + float32(t)/8) * 1000) + c = drivers.Temperature(t)*125 + 25000 e = nil return } diff --git a/lsm6ds3/lsm6ds3.go b/lsm6ds3/lsm6ds3.go index 79d5f4ba4..27053a486 100644 --- a/lsm6ds3/lsm6ds3.go +++ b/lsm6ds3/lsm6ds3.go @@ -165,13 +165,13 @@ func (d *Device) ReadRotation() (x int32, y int32, z int32) { } // ReadTemperature returns the temperature in celsius milli degrees (°C/1000) -func (d *Device) ReadTemperature() (int32, error) { +func (d *Device) ReadTemperature() (drivers.Temperature, error) { d.bus.ReadRegister(uint8(d.Address), OUT_TEMP_L, d.dataBufferTwo) // From "Table 5. Temperature sensor characteristics" // temp = value/16 + 25 t := 25000 + (int32(int16((int16(d.dataBufferTwo[1])<<8)|int16(d.dataBufferTwo[0])))*125)/2 - return t, nil + return drivers.Temperature(t), nil } // ReadSteps returns the steps of the pedometer diff --git a/lsm6dsox/lsm6dsox.go b/lsm6dsox/lsm6dsox.go index 050728f9a..23209729f 100644 --- a/lsm6dsox/lsm6dsox.go +++ b/lsm6dsox/lsm6dsox.go @@ -110,11 +110,11 @@ func (d *Device) ReadRotation() (x int32, y int32, z int32) { } // ReadTemperature returns the temperature in celsius milli degrees (°C/1000) -func (d *Device) ReadTemperature() (int32, error) { +func (d *Device) ReadTemperature() (drivers.Temperature, error) { d.bus.ReadRegister(uint8(d.Address), OUT_TEMP_L, d.dataBufferTwo) // From "Table 4. Temperature sensor characteristics" // temp = value/256 + 25 t := 25000 + (int32(int16((int16(d.dataBufferTwo[1])<<8)|int16(d.dataBufferTwo[0])))*125)/32 - return t, nil + return drivers.Temperature(t), nil } diff --git a/mag3110/mag3110.go b/mag3110/mag3110.go index 0fe7d6720..6195745ed 100644 --- a/mag3110/mag3110.go +++ b/mag3110/mag3110.go @@ -49,8 +49,8 @@ func (d Device) ReadMagnetic() (x int16, y int16, z int16) { // ReadTemperature reads and returns the current die temperature in // celsius milli degrees (°C/1000). -func (d Device) ReadTemperature() (int32, error) { +func (d Device) ReadTemperature() (drivers.Temperature, error) { data := make([]byte, 1) d.bus.ReadRegister(uint8(d.Address), DIE_TEMP, data) - return int32(data[0]) * 1000, nil + return drivers.Temperature(data[0]) * 1000, nil } diff --git a/sht3x/sht3x.go b/sht3x/sht3x.go index 423258fc2..142c1ec8a 100644 --- a/sht3x/sht3x.go +++ b/sht3x/sht3x.go @@ -31,9 +31,9 @@ func New(bus drivers.I2C) Device { } // Read returns the temperature in celsius milli degrees (°C/1000). -func (d *Device) ReadTemperature() (tempMilliCelsius int32, err error) { +func (d *Device) ReadTemperature() (tempMilliCelsius drivers.Temperature, err error) { tempMilliCelsius, _, err = d.ReadTemperatureHumidity() - return tempMilliCelsius, err + return drivers.Temperature(tempMilliCelsius), err } // Read returns the relative humidity in hundredths of a percent. @@ -43,15 +43,15 @@ func (d *Device) ReadHumidity() (relativeHumidity int16, err error) { } // Read returns both the temperature and relative humidity. -func (d *Device) ReadTemperatureHumidity() (tempMilliCelsius int32, relativeHumidity int16, err error) { +func (d *Device) ReadTemperatureHumidity() (tempMilliCelsius drivers.Temperature, relativeHumidity int16, err error) { var rawTemp, rawHum, errx = d.rawReadings() if errx != nil { err = errx return } - tempMilliCelsius = (35000 * int32(rawTemp) / 13107) - 45000 + tempMilliCelsius = drivers.Temperature((35000 * int32(rawTemp) / 13107) - 45000) relativeHumidity = int16(2000 * int32(rawHum) / 13107) - return tempMilliCelsius, relativeHumidity, err + return } // rawReadings returns the sensor's raw values of the temperature and humidity diff --git a/thermistor/thermistor.go b/thermistor/thermistor.go index 92175d8f0..5a3511924 100644 --- a/thermistor/thermistor.go +++ b/thermistor/thermistor.go @@ -29,6 +29,8 @@ package thermistor // import "tinygo.org/x/drivers/thermistor" import ( "machine" "math" + + "tinygo.org/x/drivers" ) // Device holds the ADC pin and the needed settings for calculating the @@ -61,7 +63,7 @@ func (d *Device) Configure() { } // ReadTemperature returns the temperature in celsius milli degrees (°C/1000) -func (d *Device) ReadTemperature() (temperature int32, err error) { +func (d *Device) ReadTemperature() (temperature drivers.Temperature, err error) { var reading uint32 if d.HighSide { // Thermistor connected from analog input to high logic level. @@ -82,5 +84,5 @@ func (d *Device) ReadTemperature() (temperature int32, err error) { steinhart = 1.0 / steinhart // Invert steinhart -= 273.15 // convert to C - return int32(steinhart * 1000), nil + return drivers.Temperature(steinhart * 1000), nil } diff --git a/tmp102/tmp102.go b/tmp102/tmp102.go index 9e6329bab..4b8176f49 100644 --- a/tmp102/tmp102.go +++ b/tmp102/tmp102.go @@ -46,7 +46,7 @@ func (d *Device) Connected() bool { } // Reads the temperature from the sensor and returns it in celsius milli degrees (°C/1000). -func (d *Device) ReadTemperature() (temperature int32, err error) { +func (d *Device) ReadTemperature() (temperature drivers.Temperature, err error) { tmpData := make([]byte, 2) @@ -62,7 +62,7 @@ func (d *Device) ReadTemperature() (temperature int32, err error) { temperatureSum |= int32(0xf800) } - temperature = temperatureSum * 625 + temperature = drivers.Temperature(temperatureSum * 625 / 10) - return temperature / 10, nil + return temperature, nil } diff --git a/units.go b/units.go new file mode 100644 index 000000000..b5d3ec90b --- /dev/null +++ b/units.go @@ -0,0 +1,17 @@ +package drivers + +// This file contains some common units that can be used in a sensor driver. + +// Temperature is a temperature in Celsius milli degrees (°C/1000). For example, +// the value 25000 is 25°C. +type Temperature int32 + +// Celsius returns the temperature in degrees Celsius. +func (t Temperature) Celsius() float32 { + return float32(t) / 1000 +} + +// Fahrenheit returns the temperature in degrees Fahrenheit. +func (t Temperature) Fahrenheit() float32 { + return t.Celsius()*1.8 + 32 +} diff --git a/units_test.go b/units_test.go new file mode 100644 index 000000000..ae0867ded --- /dev/null +++ b/units_test.go @@ -0,0 +1,26 @@ +package drivers + +import "testing" + +func TestTemperature(t *testing.T) { + tests := []struct { + t Temperature + c float32 // Celsius + f float32 // Fahrenheit + }{ + {-40000, -40, -40}, // -40°C + {0, 0, 32}, // 0°C + {20000, 20, 68}, // 20°C + {25000, 25, 77}, // 25°C + } + for _, tc := range tests { + c := tc.t.Celsius() + f := tc.t.Fahrenheit() + if c != tc.c { + t.Errorf("expected value %d to be %f°C, but got %f°C", tc.t, tc.c, c) + } + if f != tc.f { + t.Errorf("expected value %d to be %f°F, but got %f°F", tc.t, tc.f, f) + } + } +}