diff --git a/samples/sht1x.go b/samples/sht1x.go new file mode 100644 index 0000000..bd595d1 --- /dev/null +++ b/samples/sht1x.go @@ -0,0 +1,60 @@ +// +build ignore + +package main + +import ( + "flag" + "fmt" + "os" + "os/signal" + "time" + + "github.com/kidoman/embd" + "github.com/kidoman/embd/sensor/sht1x" + + _ "github.com/kidoman/embd/host/all" +) + +func main() { + flag.Parse() + + if err := embd.InitGPIO(); err != nil { + panic(err) + } + defer embd.CloseGPIO() + + data, err := embd.NewDigitalPin(4) + if err != nil { + panic(err) + } + defer data.Close() + + clock, err := embd.NewDigitalPin(3) + if err != nil { + panic(err) + } + defer clock.Close() + + sensor := sht1x.New(data, clock) + + quit := make(chan os.Signal, 1) + signal.Notify(quit, os.Interrupt, os.Kill) + defer signal.Stop(quit) + + ticker := time.NewTicker(2 * time.Second) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + m, err := sensor.Measure() + if err != nil { + fmt.Printf("err: %v\n", err) + } + fmt.Printf("Temperature: %.1fC, Relative Humidity: %.1f%%, Dew Point: %.1fC\n", m.Temperature, m.RelativeHumidity, m.DewPoint) + + case <-quit: + return + } + } +} diff --git a/sensor/sht1x/sht1x.go b/sensor/sht1x/sht1x.go new file mode 100644 index 0000000..a0cf32c --- /dev/null +++ b/sensor/sht1x/sht1x.go @@ -0,0 +1,298 @@ +// Package sht1x allows interfacing with Sensirion SHT1x family of humidity +// and temperature sensors. +package sht1x + +import ( + "errors" + "math" + "sync" + "time" + + "github.com/kidoman/embd" +) + +// Constants and implementation derived from +// http://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity/Sensirion_Humidity_SHT1x_Datasheet_V5.pdf +const ( + d1 = -40.1 + d2 = 0.01 + c1 = -2.0468 + c2 = 0.0367 + c3 = -0.0000015955 + t1 = 0.01 + t2 = 0.00008 + tnA0 = 243.12 + mA0 = 17.62 + tnB0 = 272.62 + mB0 = 22.46 + measureTemperatureCommand = 3 + measureHumidityCommand = 5 +) + +// Measurement represents a measurement of temperature in degrees Celsius, +// relative humidity in percent, and dew point in degrees Celsius. +type Measurement struct { + Temperature float64 + RelativeHumidity float64 + DewPoint float64 +} + +// SHT1x represents a SHT1x humidity and temperature sensor. +type SHT1x struct { + DataPin, ClockPin embd.DigitalPin + m sync.RWMutex +} + +// New returns a handle to a SHT1x sensor. +func New(dataPin, clockPin embd.DigitalPin) *SHT1x { + return &SHT1x{ + DataPin: dataPin, + ClockPin: clockPin, + } +} + +// Measure returns a Measurement with temperature in degrees Celsius, +// relative humidity in percent, and dew point in degrees Celsius. +func (d *SHT1x) Measure() (*Measurement, error) { + rawTemperature, err := d.rawTemperature() + if err != nil { + return nil, err + } + + rawHumidity, err := d.rawHumidity() + if err != nil { + return nil, err + } + + temperature := temperatureFromRaw(rawTemperature) + relativeHumidity := humidityFromRaw(rawHumidity, temperature) + dewPoint := calculateDewPoint(relativeHumidity, temperature) + + measurement := &Measurement{ + Temperature: temperature, + RelativeHumidity: relativeHumidity, + DewPoint: dewPoint, + } + + return measurement, nil +} + +// Temperature returns a temperature measurement in degrees Celsius. +func (d *SHT1x) Temperature() (float64, error) { + raw, err := d.rawTemperature() + if err != nil { + return 0, err + } + + temperature := temperatureFromRaw(raw) + + return temperature, nil +} + +// RelativeHumidity returns a relative humidity measurement in percent. +func (d *SHT1x) RelativeHumidity() (float64, error) { + rawTemperature, err := d.rawTemperature() + if err != nil { + return 0, err + } + + rawHumidity, err := d.rawHumidity() + if err != nil { + return 0, err + } + + temperature := temperatureFromRaw(rawTemperature) + relativeHumidity := humidityFromRaw(rawHumidity, temperature) + + return relativeHumidity, nil +} + +// DewPoint returns a dew point measurement in degrees Celsius. +func (d *SHT1x) DewPoint() (float64, error) { + rawTemperature, err := d.rawTemperature() + if err != nil { + return 0, err + } + + rawHumidity, err := d.rawHumidity() + if err != nil { + return 0, err + } + + temperature := temperatureFromRaw(rawTemperature) + relativeHumidity := humidityFromRaw(rawHumidity, temperature) + + dewPoint := calculateDewPoint(relativeHumidity, temperature) + return dewPoint, nil +} + +func (d *SHT1x) sendCommand(command int) error { + d.DataPin.SetDirection(embd.Out) + d.ClockPin.SetDirection(embd.Out) + + d.DataPin.Write(embd.High) + d.ClockPin.Write(embd.High) + d.DataPin.Write(embd.Low) + d.ClockPin.Write(embd.Low) + d.ClockPin.Write(embd.High) + d.DataPin.Write(embd.High) + d.ClockPin.Write(embd.Low) + + for i := 0; i < 8; i++ { + bitSet := (command&(1< 0 { + tn = tnA0 + m = mA0 + } + + return tn * (math.Log(humidity/100.0) + (m*temperature)/(tn+temperature)) / (m - math.Log(humidity/100.0) - m*temperature/(tn+temperature)) +}