diff --git a/devices/bmxx80/bmp180.go b/devices/bmxx80/bmp180.go index fcdd8e9..814fb61 100644 --- a/devices/bmxx80/bmp180.go +++ b/devices/bmxx80/bmp180.go @@ -8,13 +8,13 @@ import ( "encoding/binary" "time" - "periph.io/x/periph/devices" + "periph.io/x/periph/conn/physic" ) // sense180 reads the device's registers for bmp180. // // It must be called with d.mu lock held. -func (d *Dev) sense180(env *devices.Environment) error { +func (d *Dev) sense180(e *physic.Env) error { // Request temperature conversion and read measurement. if err := d.writeCommands([]byte{0xF4, 0x20 | 0x0E}); err != nil { return d.wrap(err) @@ -38,8 +38,9 @@ func (d *Dev) sense180(env *devices.Environment) error { } up := (int32(pressureBuf[0])<<16 + int32(pressureBuf[1])<<8 | int32(pressureBuf[2])) >> (8 - d.os) pressure := d.cal180.compensatePressure(up, int32(rawTemp), uint(d.os)) - env.Temperature = devices.Celsius(temp * 100) - env.Pressure = devices.KPascal(pressure) + // Convert DeciCelsius to Kelvin. + e.Temperature = physic.Temperature(temp)*100*physic.MilliCelsius + physic.ZeroCelsius + e.Pressure = physic.Pressure(pressure) * physic.Pascal return nil } diff --git a/devices/bmxx80/bmp180_test.go b/devices/bmxx80/bmp180_test.go index c56ce48..9b86b95 100644 --- a/devices/bmxx80/bmp180_test.go +++ b/devices/bmxx80/bmp180_test.go @@ -9,7 +9,7 @@ import ( "time" "periph.io/x/periph/conn/i2c/i2ctest" - "periph.io/x/periph/devices" + "periph.io/x/periph/conn/physic" ) var opts180 = &Opts{Temperature: O1x, Pressure: O1x} @@ -74,13 +74,13 @@ func TestSense180_success(t *testing.T) { values := []struct { o Oversampling c byte - p devices.KPascal + p physic.Pressure }{ - {Oversampling(42), 0x34, 100567}, - {O1x, 0x34, 100567}, - {O2x, 0x74, 100567}, - {O4x, 0xB4, 100568}, - {O8x, 0xF4, 100568}, + {Oversampling(42), 0x34, 100567 * physic.Pascal}, + {O1x, 0x34, 100567 * physic.Pascal}, + {O2x, 0x74, 100567 * physic.Pascal}, + {O4x, 0xB4, 100568 * physic.Pascal}, + {O8x, 0xF4, 100568 * physic.Pascal}, } for _, line := range values { bus := i2ctest.Playback{ @@ -110,18 +110,18 @@ func TestSense180_success(t *testing.T) { if s := dev.String(); s != "BMP180{playback(119)}" { t.Fatal(s) } - env := devices.Environment{} - if err := dev.Sense(&env); err != nil { + e := physic.Env{} + if err := dev.Sense(&e); err != nil { t.Fatal(err) } - if env.Temperature != 25300 { - t.Fatalf("temp %d", env.Temperature) + if e.Temperature != 25300*physic.MilliCelsius+physic.ZeroCelsius { + t.Fatalf("temp %d", e.Temperature) } - if env.Pressure != line.p { - t.Fatalf("pressure %d", env.Pressure) + if e.Pressure != line.p { + t.Fatalf("pressure %d", e.Pressure) } - if env.Humidity != 0 { - t.Fatalf("humidity %d", env.Humidity) + if e.Humidity != 0 { + t.Fatalf("humidity %d", e.Humidity) } if err := dev.Halt(); err != nil { t.Fatal(err) @@ -151,8 +151,8 @@ func TestSense180_fail_1(t *testing.T) { if err != nil { t.Fatal(err) } - env := devices.Environment{} - if dev.Sense(&env) == nil { + e := physic.Env{} + if dev.Sense(&e) == nil { t.Fatal("sensing should have failed") } if err := bus.Close(); err != nil { @@ -181,8 +181,8 @@ func TestSense180_fail_2(t *testing.T) { if err != nil { t.Fatal(err) } - env := devices.Environment{} - if dev.Sense(&env) == nil { + e := physic.Env{} + if dev.Sense(&e) == nil { t.Fatal("sensing should have failed") } if err := bus.Close(); err != nil { @@ -213,8 +213,8 @@ func TestSense180_fail_3(t *testing.T) { if err != nil { t.Fatal(err) } - env := devices.Environment{} - if dev.Sense(&env) == nil { + e := physic.Env{} + if dev.Sense(&e) == nil { t.Fatal("sensing should have failed") } if err := bus.Close(); err != nil { @@ -247,8 +247,8 @@ func TestSense180_fail_4(t *testing.T) { if err != nil { t.Fatal(err) } - env := devices.Environment{} - if dev.Sense(&env) == nil { + e := physic.Env{} + if dev.Sense(&e) == nil { t.Fatal("sensing should have failed") } if err := bus.Close(); err != nil { @@ -294,18 +294,18 @@ func TestSenseContinuous180_success(t *testing.T) { if err != nil { t.Fatal(err) } - env := <-c - if env.Temperature != 25300 { - t.Fatalf("temp %d", env.Temperature) + e := <-c + if e.Temperature != 25300*physic.MilliCelsius+physic.ZeroCelsius { + t.Fatalf("temp %d", e.Temperature) } - if env.Pressure != 100567 { - t.Fatalf("pressure %d", env.Pressure) + if e.Pressure != 100567*physic.Pascal { + t.Fatalf("pressure %d", e.Pressure) } - if env.Humidity != 0 { - t.Fatalf("humidity %d", env.Humidity) + if e.Humidity != 0 { + t.Fatalf("humidity %d", e.Humidity) } - if dev.Sense(&env) == nil { + if dev.Sense(&e) == nil { t.Fatal("Sense() should have failed") } @@ -314,7 +314,7 @@ func TestSenseContinuous180_success(t *testing.T) { t.Fatal(err) } - env = <-c2 + e = <-c2 if _, ok := <-c; ok { t.Fatal("c should be closed") diff --git a/devices/bmxx80/bmx280.go b/devices/bmxx80/bmx280.go index eca708a..133e84a 100644 --- a/devices/bmxx80/bmx280.go +++ b/devices/bmxx80/bmx280.go @@ -7,13 +7,13 @@ package bmxx80 import ( "time" - "periph.io/x/periph/devices" + "periph.io/x/periph/conn/physic" ) // sense280 reads the device's registers for bme280/bmp280. // // It must be called with d.mu lock held. -func (d *Dev) sense280(env *devices.Environment) error { +func (d *Dev) sense280(e *physic.Env) error { // All registers must be read in a single pass, as noted at page 21, section // 4.1. // Pressure: 0xF7~0xF9 @@ -32,18 +32,21 @@ func (d *Dev) sense280(env *devices.Environment) error { tRaw := int32(buf[3])<<12 | int32(buf[4])<<4 | int32(buf[5])>>4 t, tFine := d.cal280.compensateTempInt(tRaw) - env.Temperature = devices.Celsius(t * 10) + // Convert CentiCelsius to Kelvin. + e.Temperature = physic.Temperature(t)*10*physic.MilliCelsius + physic.ZeroCelsius if d.opts.Pressure != Off { p := d.cal280.compensatePressureInt64(pRaw, tFine) - env.Pressure = devices.KPascal((int32(p) + 127) / 256) + // It has 8 bits of fractional Pascal. + e.Pressure = physic.Pressure(p) * 15625 * physic.MicroPascal / 4 } if d.opts.Humidity != Off { // This value is 16 bits as per doc. hRaw := int32(buf[6])<<8 | int32(buf[7]) - h := d.cal280.compensateHumidityInt(hRaw, tFine) - env.Humidity = devices.RelativeHumidity((int32(h)*100 + 511) / 1024) + h := physic.RelativeHumidity(d.cal280.compensateHumidityInt(hRaw, tFine)) + // Convert base 1024 to base 1000. + e.Humidity = h * physic.MicroRH * 1000 / 1024 } return nil } diff --git a/devices/bmxx80/bmx280_test.go b/devices/bmxx80/bmx280_test.go index b0afc98..0fa5203 100644 --- a/devices/bmxx80/bmx280_test.go +++ b/devices/bmxx80/bmx280_test.go @@ -17,7 +17,6 @@ import ( "periph.io/x/periph/conn/physic" "periph.io/x/periph/conn/spi" "periph.io/x/periph/conn/spi/spitest" - "periph.io/x/periph/devices" ) // Real data extracted from a device. @@ -87,21 +86,21 @@ func TestSPISenseBME280_success(t *testing.T) { if s := dev.String(); s != "BME280{playback}" { t.Fatal(s) } - env := devices.Environment{} - if err := dev.Sense(&env); err != nil { + e := physic.Env{} + if err := dev.Sense(&e); err != nil { t.Fatal(err) } // TODO(maruel): The values do not make sense but I think I burned my SPI // BME280 by misconnecting it in reverse for a few minutes. It still "work" // but fail to read data. It could also be a bug in the driver. :( - if env.Temperature != 62680 { - t.Fatalf("temp %d", env.Temperature) + if e.Temperature != 62680*physic.MilliCelsius+physic.ZeroCelsius { + t.Fatalf("temp %d", e.Temperature) } - if env.Pressure != 99576 { - t.Fatalf("pressure %d", env.Pressure) + if e.Pressure != 99575933593750*physic.NanoPascal { + t.Fatalf("pressure %d", e.Pressure) } - if env.Humidity != 995 { - t.Fatalf("humidity %d", env.Humidity) + if e.Humidity != 9950*physic.MicroRH { + t.Fatalf("humidity %d", e.Humidity) } if err := s.Close(); err != nil { t.Fatal(err) @@ -288,7 +287,7 @@ func TestI2CSenseBME280_fail(t *testing.T) { if err != nil { t.Fatal(err) } - if dev.Sense(&devices.Environment{}) == nil { + if dev.Sense(&physic.Env{}) == nil { t.Fatal("sense fail read") } // The I/O didn't occur. @@ -328,18 +327,18 @@ func TestI2CSenseBMP280_success(t *testing.T) { if s := dev.String(); s != "BMP280{playback(118)}" { t.Fatal(s) } - env := devices.Environment{} - if err := dev.Sense(&env); err != nil { + e := physic.Env{} + if err := dev.Sense(&e); err != nil { t.Fatal(err) } - if env.Temperature != 23720 { - t.Fatalf("temp %d", env.Temperature) + if e.Temperature != 23720*physic.MilliCelsius+physic.ZeroCelsius { + t.Fatalf("temp %d", e.Temperature) } - if env.Pressure != 100943 { - t.Fatalf("pressure %d", env.Pressure) + if e.Pressure != 100942695312500*physic.NanoPascal { + t.Fatalf("pressure %d", e.Pressure) } - if env.Humidity != 0 { - t.Fatalf("humidity %d", env.Humidity) + if e.Humidity != 0 { + t.Fatalf("humidity %d", e.Humidity) } if err := dev.Halt(); err != nil { t.Fatal(err) @@ -381,18 +380,18 @@ func TestI2CSenseBME280_success(t *testing.T) { if s := dev.String(); s != "BME280{playback(118)}" { t.Fatal(s) } - env := devices.Environment{} - if err := dev.Sense(&env); err != nil { + e := physic.Env{} + if err := dev.Sense(&e); err != nil { t.Fatal(err) } - if env.Temperature != 23720 { - t.Fatalf("temp %d", env.Temperature) + if e.Temperature != 23720*physic.MilliCelsius+physic.ZeroCelsius { + t.Fatalf("temp %d", e.Temperature) } - if env.Pressure != 100943 { - t.Fatalf("pressure %d", env.Pressure) + if e.Pressure != 100942695312500*physic.NanoPascal { + t.Fatalf("pressure %d", e.Pressure) } - if env.Humidity != 6531 { - t.Fatalf("humidity %d", env.Humidity) + if e.Humidity != 65305*physic.MicroRH { + t.Fatalf("humidity %d", e.Humidity) } if err := dev.Halt(); err != nil { t.Fatal(err) @@ -430,8 +429,8 @@ func TestI2CSense280_idle_fail(t *testing.T) { if s := dev.String(); s != "BME280{playback(118)}" { t.Fatal(s) } - env := devices.Environment{} - if dev.Sense(&env) == nil { + e := physic.Env{} + if dev.Sense(&e) == nil { t.Fatal("isIdle() should have failed") } } @@ -466,8 +465,8 @@ func TestI2CSense280_command_fail(t *testing.T) { if s := dev.String(); s != "BME280{playback(118)}" { t.Fatal(s) } - env := devices.Environment{} - if dev.Sense(&env) == nil { + e := physic.Env{} + if dev.Sense(&e) == nil { t.Fatal("isIdle() should have failed") } } @@ -511,20 +510,20 @@ func TestI2CSenseContinuous280_success(t *testing.T) { if err != nil { t.Fatal(err) } - env := devices.Environment{} + e := physic.Env{} select { - case env = <-c: + case e = <-c: case <-time.After(2 * time.Second): t.Fatal("failed") } - if env.Temperature != 23720 { - t.Fatalf("temp %d", env.Temperature) + if e.Temperature != 23720*physic.MilliCelsius+physic.ZeroCelsius { + t.Fatalf("temp %d", e.Temperature) } - if env.Pressure != 100943 { - t.Fatalf("pressure %d", env.Pressure) + if e.Pressure != 100942695312500*physic.NanoPascal { + t.Fatalf("pressure %d", e.Pressure) } - if env.Humidity != 6531 { - t.Fatalf("humidity %d", env.Humidity) + if e.Humidity != 65305*physic.MicroRH { + t.Fatalf("humidity %d", e.Humidity) } // This cancels the previous channel and resets the interval. @@ -537,26 +536,26 @@ func TestI2CSenseContinuous280_success(t *testing.T) { t.Fatal("c should be closed") } select { - case env = <-c2: + case e = <-c2: case <-time.After(2 * time.Second): t.Fatal("failed") } select { - case env = <-c2: + case e = <-c2: case <-time.After(2 * time.Second): t.Fatal("failed") } - if env.Temperature != 23720 { - t.Fatalf("temp %d", env.Temperature) + if e.Temperature != 23720*physic.MilliCelsius+physic.ZeroCelsius { + t.Fatalf("temp %d", e.Temperature) } - if env.Pressure != 100943 { - t.Fatalf("pressure %d", env.Pressure) + if e.Pressure != 100942695312500*physic.NanoPascal { + t.Fatalf("pressure %d", e.Pressure) } - if env.Humidity != 6531 { - t.Fatalf("humidity %d", env.Humidity) + if e.Humidity != 65305*physic.MicroRH { + t.Fatalf("humidity %d", e.Humidity) } - if dev.Sense(&env) == nil { + if dev.Sense(&e) == nil { t.Fatal("can't Sense() during SenseContinously") } diff --git a/devices/bmxx80/bmx280smoketest/bmx280smoketest.go b/devices/bmxx80/bmx280smoketest/bmx280smoketest.go index 9d89639..51857b8 100644 --- a/devices/bmxx80/bmx280smoketest/bmx280smoketest.go +++ b/devices/bmxx80/bmx280smoketest/bmx280smoketest.go @@ -15,10 +15,10 @@ import ( "periph.io/x/periph/conn/i2c" "periph.io/x/periph/conn/i2c/i2creg" "periph.io/x/periph/conn/i2c/i2ctest" + "periph.io/x/periph/conn/physic" "periph.io/x/periph/conn/spi" "periph.io/x/periph/conn/spi/spireg" "periph.io/x/periph/conn/spi/spitest" - "periph.io/x/periph/devices" "periph.io/x/periph/devices/bmxx80" ) @@ -154,8 +154,8 @@ func run(i2cBus i2c.Bus, i2cAddr uint16, spiPort spi.PortCloser) (err error) { } }() - i2cEnv := devices.Environment{} - spiEnv := devices.Environment{} + i2cEnv := physic.Env{} + spiEnv := physic.Env{} if err2 := i2cDev.Sense(&i2cEnv); err2 != nil { return err2 } @@ -164,7 +164,7 @@ func run(i2cBus i2c.Bus, i2cAddr uint16, spiPort spi.PortCloser) (err error) { return err2 } printEnv(spiDev, &spiEnv) - delta := devices.Environment{ + delta := physic.Env{ Temperature: i2cEnv.Temperature - spiEnv.Temperature, Pressure: i2cEnv.Pressure - spiEnv.Pressure, Humidity: i2cEnv.Humidity - spiEnv.Humidity, @@ -186,6 +186,6 @@ func run(i2cBus i2c.Bus, i2cAddr uint16, spiPort spi.PortCloser) (err error) { return nil } -func printEnv(dev interface{}, env *devices.Environment) { - fmt.Printf("%-18s: %8s %10s %9s\n", dev, env.Temperature, env.Pressure, env.Humidity) +func printEnv(dev interface{}, e *physic.Env) { + fmt.Printf("%-18s: %8s %10s %9s\n", dev, e.Temperature, e.Pressure, e.Humidity) } diff --git a/devices/bmxx80/bmxx80.go b/devices/bmxx80/bmxx80.go index 5c9201b..09e6eb8 100644 --- a/devices/bmxx80/bmxx80.go +++ b/devices/bmxx80/bmxx80.go @@ -38,8 +38,8 @@ import ( "periph.io/x/periph/conn" "periph.io/x/periph/conn/i2c" "periph.io/x/periph/conn/mmr" + "periph.io/x/periph/conn/physic" "periph.io/x/periph/conn/spi" - "periph.io/x/periph/devices" ) // Oversampling affects how much time is taken to measure each of temperature, @@ -245,7 +245,7 @@ func (d *Dev) String() string { // Sense requests a one time measurement as °C, kPa and % of relative humidity. // // The very first measurements may be of poor quality. -func (d *Dev) Sense(env *devices.Environment) error { +func (d *Dev) Sense(e *physic.Env) error { d.mu.Lock() defer d.mu.Unlock() if d.stop != nil { @@ -266,9 +266,9 @@ func (d *Dev) Sense(env *devices.Environment) error { return d.wrap(err) } } - return d.sense280(env) + return d.sense280(e) } - return d.sense180(env) + return d.sense180(e) } // SenseContinuous returns measurements as °C, kPa and % of relative humidity @@ -279,7 +279,7 @@ func (d *Dev) Sense(env *devices.Environment) error { // // It's the responsibility of the caller to retrieve the values from the // channel as fast as possible, otherwise the interval may not be respected. -func (d *Dev) SenseContinuous(interval time.Duration) (<-chan devices.Environment, error) { +func (d *Dev) SenseContinuous(interval time.Duration) (<-chan physic.Env, error) { d.mu.Lock() defer d.mu.Unlock() if d.stop != nil { @@ -302,7 +302,7 @@ func (d *Dev) SenseContinuous(interval time.Duration) (<-chan devices.Environmen } } - sensing := make(chan devices.Environment) + sensing := make(chan physic.Env) d.stop = make(chan struct{}) d.wg.Add(1) go func() { @@ -433,14 +433,14 @@ func (d *Dev) makeDev(opts *Opts) error { return nil } -func (d *Dev) sensingContinuous(interval time.Duration, sensing chan<- devices.Environment, stop <-chan struct{}) { +func (d *Dev) sensingContinuous(interval time.Duration, sensing chan<- physic.Env, stop <-chan struct{}) { t := time.NewTicker(interval) defer t.Stop() var err error for { // Do one initial sensing right away. - var e devices.Environment + e := physic.Env{} d.mu.Lock() if d.is280 { err = d.sense280(&e) @@ -514,5 +514,5 @@ var defaults = Opts{ var doSleep = time.Sleep var _ conn.Resource = &Dev{} -var _ devices.Environmental = &Dev{} +var _ physic.SenseEnv = &Dev{} var _ fmt.Stringer = &Dev{} diff --git a/devices/bmxx80/example_test.go b/devices/bmxx80/example_test.go index ced88b3..602d72f 100644 --- a/devices/bmxx80/example_test.go +++ b/devices/bmxx80/example_test.go @@ -9,7 +9,7 @@ import ( "log" "periph.io/x/periph/conn/i2c/i2creg" - "periph.io/x/periph/devices" + "periph.io/x/periph/conn/physic" "periph.io/x/periph/devices/bmxx80" "periph.io/x/periph/host" ) @@ -30,7 +30,7 @@ func Example() { if err != nil { log.Fatalf("failed to initialize bme280: %v", err) } - e := devices.Environment{} + e := physic.Env{} if err := d.Sense(&e); err != nil { log.Fatal(err) } diff --git a/devices/devices.go b/devices/devices.go index d3eb19d..a44c76f 100644 --- a/devices/devices.go +++ b/devices/devices.go @@ -8,7 +8,6 @@ import ( "image" "image/color" "io" - "time" "periph.io/x/periph/conn" ) @@ -41,22 +40,3 @@ type Display interface { // To be compatible with draw.Drawer, this function doesn't return an error. Draw(r image.Rectangle, src image.Image, sp image.Point) } - -// Environment represents measurements from an environmental sensor. -// -// Deprecated: This interface will be removed in v3. Use physic.Env instead. -type Environment struct { - Temperature Celsius - Pressure KPascal - Humidity RelativeHumidity -} - -// Environmental represents an environmental sensor. -// -// Deprecated: This interface will be removed in v3. Use physic.SenseEnv -// instead. -type Environmental interface { - conn.Resource - Sense(env *Environment) error - SenseContinuous(interval time.Duration) (<-chan Environment, error) -} diff --git a/devices/ds18b20/ds18b20.go b/devices/ds18b20/ds18b20.go index 97434ce..4126ffe 100644 --- a/devices/ds18b20/ds18b20.go +++ b/devices/ds18b20/ds18b20.go @@ -28,7 +28,7 @@ import ( "periph.io/x/periph/conn" "periph.io/x/periph/conn/onewire" - "periph.io/x/periph/devices" + "periph.io/x/periph/conn/physic" ) // ConvertAll performs a conversion on all DS18B20 devices on the bus. @@ -109,7 +109,7 @@ func (d *Dev) Halt() error { } // Temperature performs a conversion and returns the temperature. -func (d *Dev) Temperature() (devices.Celsius, error) { +func (d *Dev) Temperature() (physic.Temperature, error) { if err := d.onewire.TxPower([]byte{0x44}, nil); err != nil { return 0, err } @@ -121,7 +121,7 @@ func (d *Dev) Temperature() (devices.Celsius, error) { // device. // // It is useful in combination with ConvertAll. -func (d *Dev) LastTemp() (devices.Celsius, error) { +func (d *Dev) LastTemp() (physic.Temperature, error) { // Read the scratchpad memory. spad, err := d.readScratchpad() if err != nil { @@ -129,9 +129,10 @@ func (d *Dev) LastTemp() (devices.Celsius, error) { } // spad[1] is MSB, spad[0] is LSB and has 4 fractional bits. Need to do sign - // extension multiply by 1000 to get devices.Millis, divide by 16 due to 4 - // fractional bits. Datasheet p.4. - c := (devices.Celsius(int8(spad[1]))<<8 + devices.Celsius(spad[0])) * 1000 / 16 + // extension multiply by 1000 to get Millis, divide by 16 due to 4 fractional + // bits. Datasheet p.4. + v := (int(int8(spad[1]))<<8 + int(spad[0])) * 1000 / 16 + c := physic.Temperature(v)*physic.MilliKelvin + physic.ZeroCelsius // The device powers up with a value of 85°C, so if we read that odds are // very high that either no conversion was performed or that the conversion diff --git a/devices/ds18b20/ds18b20_test.go b/devices/ds18b20/ds18b20_test.go index da3fba8..b8a2806 100644 --- a/devices/ds18b20/ds18b20_test.go +++ b/devices/ds18b20/ds18b20_test.go @@ -11,7 +11,7 @@ import ( "periph.io/x/periph/conn/onewire" "periph.io/x/periph/conn/onewire/onewiretest" - "periph.io/x/periph/devices" + "periph.io/x/periph/conn/physic" ) func TestNew_fail_resolution(t *testing.T) { @@ -52,7 +52,7 @@ func TestTemperature(t *testing.T) { }, } var addr onewire.Address = 0x740000070e41ac28 - var temp devices.Celsius = 30000 // 30.000°C + temp := 30*physic.Celsius + physic.ZeroCelsius bus := onewiretest.Playback{Ops: ops} dev, err := New(&bus, addr, 10) if err != nil { @@ -187,7 +187,7 @@ func TestRecordTemp(t *testing.T) { t.Logf(" %#v,", op) } t.Log("}") - t.Logf("var temp devices.Celsius = %d // %s", temp, temp.String()) + t.Logf("var temp physic.Temperature = %d // %s", temp, temp.String()) } // diff --git a/devices/lepton/cci/cci.go b/devices/lepton/cci/cci.go index 48b8f89..f40a7a8 100644 --- a/devices/lepton/cci/cci.go +++ b/devices/lepton/cci/cci.go @@ -31,7 +31,7 @@ import ( "periph.io/x/periph/conn" "periph.io/x/periph/conn/i2c" "periph.io/x/periph/conn/mmr" - "periph.io/x/periph/devices" + "periph.io/x/periph/conn/physic" "periph.io/x/periph/devices/lepton/internal" ) @@ -132,7 +132,7 @@ type FFCMode struct { ShutterTempLockoutState ShutterTempLockoutState // Default: ShutterTempLockoutStateInactive ElapsedTimeSinceLastFFC time.Duration // Uptime DesiredFFCPeriod time.Duration // Default: 300s - DesiredFFCTempDelta devices.Celsius // Default: 3K + DesiredFFCTempDelta physic.Temperature // Default: 3K ImminentDelay uint16 // Default: 52 VideoFreezeDuringFFC bool // Default: true FFCDesired bool // Default: false @@ -256,25 +256,25 @@ func (d *Dev) GetUptime() (time.Duration, error) { if err := d.c.get(sysUptime, &v); err != nil { return 0, err } - return v.ToD(), nil + return v.Duration(), nil } // GetTemp returns the temperature inside the camera. -func (d *Dev) GetTemp() (devices.Celsius, error) { +func (d *Dev) GetTemp() (physic.Temperature, error) { var v internal.CentiK if err := d.c.get(sysTemperature, &v); err != nil { return 0, err } - return v.ToC(), nil + return v.Temperature(), nil } // GetTempHousing returns the temperature of the camera housing. -func (d *Dev) GetTempHousing() (devices.Celsius, error) { +func (d *Dev) GetTempHousing() (physic.Temperature, error) { var v internal.CentiK if err := d.c.get(sysHousingTemperature, &v); err != nil { return 0, err } - return v.ToC(), nil + return v.Temperature(), nil } // GetFFCModeControl returns the internal state with regards to calibration. @@ -286,9 +286,9 @@ func (d *Dev) GetFFCModeControl() (*FFCMode, error) { return &FFCMode{ FFCShutterMode: FFCShutterMode(v.FFCShutterMode), ShutterTempLockoutState: ShutterTempLockoutState(v.ShutterTempLockoutState), - ElapsedTimeSinceLastFFC: v.ElapsedTimeSinceLastFFC.ToD(), - DesiredFFCPeriod: v.DesiredFFCPeriod.ToD(), - DesiredFFCTempDelta: devices.Celsius(v.DesiredFFCTempDelta * 10), + ElapsedTimeSinceLastFFC: v.ElapsedTimeSinceLastFFC.Duration(), + DesiredFFCPeriod: v.DesiredFFCPeriod.Duration(), + DesiredFFCTempDelta: v.DesiredFFCTempDelta.Temperature(), ImminentDelay: v.ImminentDelay, VideoFreezeDuringFFC: v.VideoFreezeDuringFFC == internal.Enabled, FFCDesired: v.FFCDesired == internal.Enabled, diff --git a/devices/lepton/internal/internal.go b/devices/lepton/internal/internal.go index 0895478..371dcd2 100644 --- a/devices/lepton/internal/internal.go +++ b/devices/lepton/internal/internal.go @@ -8,7 +8,7 @@ import ( "encoding/binary" "time" - "periph.io/x/periph/devices" + "periph.io/x/periph/conn/physic" ) // Flag is used in FFCMode. @@ -25,8 +25,8 @@ const ( // It is an implementation detail of the protocol. type DurationMS uint32 -// ToD converts a millisecond based timing to time.Duration. -func (d DurationMS) ToD() time.Duration { +// Duration converts a millisecond based timing to time.Duration. +func (d DurationMS) Duration() time.Duration { return time.Duration(d) * time.Millisecond } @@ -35,10 +35,9 @@ func (d DurationMS) ToD() time.Duration { // It is an implementation detail of the protocol. type CentiK uint16 -// ToC converts a Kelvin measurement to Celsius. -func (c CentiK) ToC() devices.Celsius { - v := (int(c) - 27315) * 10 - return devices.Celsius(v) +// Temperature converts a Kelvin measurement to Temperature. +func (c CentiK) Temperature() physic.Temperature { + return physic.Temperature(c) * 10 * physic.MilliKelvin } // Status returns the camera status as returned by the camera. @@ -57,7 +56,7 @@ type FFCMode struct { ElapsedTimeSinceLastFFC DurationMS // Uptime in ms. DesiredFFCPeriod DurationMS // Default: 300000 ExplicitCommandToOpen Flag // Default: Disabled - DesiredFFCTempDelta uint16 // Default: 300 + DesiredFFCTempDelta CentiK // Default: 300 ImminentDelay uint16 // Default: 52 // These are documented at page 51 but not listed in the structure. diff --git a/devices/lepton/internal/internal_test.go b/devices/lepton/internal/internal_test.go index f070d22..774e0ba 100644 --- a/devices/lepton/internal/internal_test.go +++ b/devices/lepton/internal/internal_test.go @@ -8,16 +8,18 @@ import ( "bytes" "testing" "time" + + "periph.io/x/periph/conn/physic" ) func TestDuration(t *testing.T) { - if d := DurationMS(100).ToD(); d != 100*time.Millisecond { + if d := DurationMS(100).Duration(); d != 100*time.Millisecond { t.Fatal(d) } } func TestCentiK(t *testing.T) { - if c := CentiK(100).ToC(); c != -272150 { + if c := CentiK(100).Temperature(); c != physic.Kelvin { t.Fatal(c) } } diff --git a/devices/lepton/lepton.go b/devices/lepton/lepton.go index d51ffdd..99c5c3f 100644 --- a/devices/lepton/lepton.go +++ b/devices/lepton/lepton.go @@ -29,27 +29,27 @@ import ( "periph.io/x/periph/conn" "periph.io/x/periph/conn/gpio" "periph.io/x/periph/conn/i2c" + "periph.io/x/periph/conn/physic" "periph.io/x/periph/conn/spi" - "periph.io/x/periph/devices" "periph.io/x/periph/devices/lepton/cci" "periph.io/x/periph/devices/lepton/internal" ) // Metadata is constructed from telemetry data, which is sent with each frame. type Metadata struct { - SinceStartup time.Duration // - FrameCount uint32 // Number of frames since the start of the camera, in 27fps (not 9fps). - AvgValue uint16 // Average value of the buffer. - Temp devices.Celsius // Temperature inside the camera. - TempHousing devices.Celsius // Camera housing temperature. - RawTemp uint16 // - RawTempHousing uint16 // - FFCSince time.Duration // Time since last internal calibration. - FFCTemp devices.Celsius // Temperature at last internal calibration. - FFCTempHousing devices.Celsius // - FFCState cci.FFCState // Current calibration state. - FFCDesired bool // Asserted at start-up, after period (default 3m) or after temperature change (default 3K). Indicates that a calibration should be triggered as soon as possible. - Overtemp bool // true 10s before self-shutdown. + SinceStartup time.Duration // + FrameCount uint32 // Number of frames since the start of the camera, in 27fps (not 9fps). + AvgValue uint16 // Average value of the buffer. + Temp physic.Temperature // Temperature inside the camera. + TempHousing physic.Temperature // Camera housing temperature. + RawTemp uint16 // + RawTempHousing uint16 // + FFCSince time.Duration // Time since last internal calibration. + FFCTemp physic.Temperature // Temperature at last internal calibration. + FFCTempHousing physic.Temperature // + FFCState cci.FFCState // Current calibration state. + FFCDesired bool // Asserted at start-up, after period (default 3m) or after temperature change (default 3K). Indicates that a calibration should be triggered as soon as possible. + Overtemp bool // true 10s before self-shutdown. } // Frame is a FLIR Lepton frame, containing 14 bits resolution intensity stored @@ -334,16 +334,16 @@ func (m *Metadata) parseTelemetry(data []byte) error { if err := binary.Read(bytes.NewBuffer(data), internal.Big16, &rowA); err != nil { return err } - m.SinceStartup = rowA.TimeCounter.ToD() + m.SinceStartup = rowA.TimeCounter.Duration() m.FrameCount = rowA.FrameCounter m.AvgValue = rowA.FrameMean - m.Temp = rowA.FPATemp.ToC() - m.TempHousing = rowA.HousingTemp.ToC() + m.Temp = rowA.FPATemp.Temperature() + m.TempHousing = rowA.HousingTemp.Temperature() m.RawTemp = rowA.FPATempCounts m.RawTempHousing = rowA.HousingTempCounts - m.FFCSince = rowA.TimeCounterLastFFC.ToD() - m.FFCTemp = rowA.FPATempLastFFC.ToC() - m.FFCTempHousing = rowA.HousingTempLastFFC.ToC() + m.FFCSince = rowA.TimeCounterLastFFC.Duration() + m.FFCTemp = rowA.FPATempLastFFC.Temperature() + m.FFCTempHousing = rowA.HousingTempLastFFC.Temperature() if rowA.StatusBits&statusMaskNil != 0 { return fmt.Errorf("lepton: (Status: 0x%08X) & (Mask: 0x%08X) = (Extra: 0x%08X) in 0x%08X", rowA.StatusBits, statusMask, rowA.StatusBits&statusMaskNil, statusMaskNil) } diff --git a/devices/lepton/lepton_test.go b/devices/lepton/lepton_test.go index 423346e..90e7bb5 100644 --- a/devices/lepton/lepton_test.go +++ b/devices/lepton/lepton_test.go @@ -18,9 +18,9 @@ import ( "periph.io/x/periph/conn/gpio" "periph.io/x/periph/conn/gpio/gpiotest" "periph.io/x/periph/conn/i2c/i2ctest" + "periph.io/x/periph/conn/physic" "periph.io/x/periph/conn/spi" "periph.io/x/periph/conn/spi/spitest" - "periph.io/x/periph/devices" "periph.io/x/periph/devices/lepton/internal" ) @@ -192,7 +192,7 @@ func TestNextFrame(t *testing.T) { if err := d.NextFrame(&f); err != nil { t.Fatal(err) } - if f.Metadata.TempHousing != devices.Celsius(2000) { + if f.Metadata.TempHousing != 2*physic.Celsius+physic.ZeroCelsius { t.Fatal(f.Metadata.TempHousing) } // Compare the frame with the reference image. It should match. @@ -268,7 +268,7 @@ func TestReadImg(t *testing.T) { if err != nil { t.Fatal(err) } - if f.Metadata.TempHousing != devices.Celsius(2000) { + if f.Metadata.TempHousing != 2*physic.Celsius+physic.ZeroCelsius { t.Fatal(f.Metadata.TempHousing) } if err := i.Close(); err != nil { diff --git a/devices/units.go b/devices/units.go deleted file mode 100644 index f29dc28..0000000 --- a/devices/units.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2016 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -package devices - -import ( - "strconv" -) - -// Milli is a fixed point value with 0.001 precision. -// -// Deprecated: This interface will be removed in v3. -type Milli int32 - -// Float64 returns the value as float64 with 0.001 precision. -func (m Milli) Float64() float64 { - return float64(m) * .001 -} - -// String returns the value formatted as a string. -func (m Milli) String() string { - d := m % 1000 - if d < 0 { - d = -d - } - return strconv.Itoa(int(m)/1000) + "." + prefixZeros(3, int(d)) -} - -// Celsius is a temperature at a precision of 0.001°C. -// -// Deprecated: This interface will be removed in v3. Use physic.Temperature -// instead. -type Celsius Milli - -// Float64 returns the value as float64 with 0.001 precision. -func (c Celsius) Float64() float64 { - return Milli(c).Float64() -} - -// String returns the temperature formatted as a string. -func (c Celsius) String() string { - return Milli(c).String() + "°C" -} - -// ToF returns the temperature as Fahrenheit, a unit used in the United States. -func (c Celsius) ToF() Fahrenheit { - return Fahrenheit((c*9+2)/5 + 32000) -} - -// Fahrenheit is an unsound unit used in the United States. -// -// Deprecated: This interface will be removed in v3. Use physic.Temperature -// instead. -type Fahrenheit Milli - -// Float64 returns the value as float64 with 0.001 precision. -func (f Fahrenheit) Float64() float64 { - return Milli(f).Float64() -} - -// String returns the temperature formatted as a string. -func (f Fahrenheit) String() string { - return Milli(f).String() + "°F" -} - -// KPascal is pressure at precision of 1Pa. -// -// Deprecated: This interface will be removed in v3. Use physic.Pressure -// instead. -type KPascal Milli - -// Float64 returns the value as float64 with 0.001 precision. -func (k KPascal) Float64() float64 { - return Milli(k).Float64() -} - -// String returns the pressure formatted as a string. -func (k KPascal) String() string { - return Milli(k).String() + "KPa" -} - -// RelativeHumidity is humidity level in %rH with 0.01%rH precision. -// -// Deprecated: This interface will be removed in v3. Use -// physic.RelativeHumidity instead. -type RelativeHumidity int32 - -// Float64 returns the value in %. -func (r RelativeHumidity) Float64() float64 { - return float64(r) * .01 -} - -// String returns the humidity formatted as a string. -func (r RelativeHumidity) String() string { - m := r % 100 - if m < 0 { - m = -m - } - return strconv.Itoa(int(r)/100) + "." + prefixZeros(2, int(m)) + "%rH" -} - -// - -func prefixZeros(digits, v int) string { - // digits is expected to be around 2~3. - s := strconv.Itoa(v) - for len(s) < digits { - // O(n²) but since digits is expected to run 2~3 times at most, it doesn't matter. - s = "0" + s - } - return s -} diff --git a/devices/units_test.go b/devices/units_test.go deleted file mode 100644 index 5a98830..0000000 --- a/devices/units_test.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2016 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -package devices - -import "testing" - -func TestMilli(t *testing.T) { - o := Milli(10010) - if s := o.String(); s != "10.010" { - t.Fatalf("%#v", s) - } - if f := o.Float64(); f > 10.011 || f < 10.009 { - t.Fatalf("%f", f) - } -} - -func TestMilli_neg(t *testing.T) { - o := Milli(-10010) - if s := o.String(); s != "-10.010" { - t.Fatalf("%#v", s) - } - if f := o.Float64(); f > -10.009 || f < -10.011 { - t.Fatalf("%f", f) - } -} - -func TestCelsius(t *testing.T) { - o := Celsius(10010) - if s := o.String(); s != "10.010°C" { - t.Fatalf("%#v", s) - } - if f := o.Float64(); f > 10.011 || f < 10.009 { - t.Fatalf("%f", f) - } - if f := o.ToF(); f != 50018 { - t.Fatalf("%d", f) - } -} - -func TestFahrenheit(t *testing.T) { - o := Fahrenheit(10010) - if s := o.String(); s != "10.010°F" { - t.Fatalf("%#v", s) - } - if f := o.Float64(); f > 10.011 || f < 10.009 { - t.Fatalf("%f", f) - } -} - -func TestKPascal(t *testing.T) { - o := KPascal(10010) - if s := o.String(); s != "10.010KPa" { - t.Fatalf("%#v", s) - } - if f := o.Float64(); f > 10.011 || f < 10.009 { - t.Fatalf("%f", f) - } -} - -func TestRelativeHumidity(t *testing.T) { - o := RelativeHumidity(5006) - if s := o.String(); s != "50.06%rH" { - t.Fatalf("%#v", s) - } - if f := o.Float64(); f >= 50.07 || f <= 50.05 { - t.Fatalf("%f", f) - } -} - -func TestRelativeHumidity_neg(t *testing.T) { - o := RelativeHumidity(-5010) - if s := o.String(); s != "-50.10%rH" { - t.Fatalf("%#v", s) - } - if f := o.Float64(); f <= -50.11 || f >= -50.09 { - t.Fatalf("%f", f) - } -}