Skip to content

Commit

Permalink
Initial support for SHT2x Temperature/Humidity sensor driver
Browse files Browse the repository at this point in the history
Signed-off-by: Yoshio HANAWA <[email protected]>
  • Loading branch information
hnw authored and deadprogram committed Jun 21, 2020
1 parent 88188d3 commit c2689ef
Show file tree
Hide file tree
Showing 5 changed files with 487 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ drivers provided using the `gobot/drivers/i2c` package:
- MPL115A2 Barometer
- MPU6050 Accelerometer/Gyroscope
- PCA9685 16-channel 12-bit PWM/Servo Driver
- SHT2x Temperature/Humidity
- SHT3x-D Temperature/Humidity
- SSD1306 OLED Display Controller
- TSL2561 Digital Luminosity/Lux/Light Sensor
Expand Down
1 change: 1 addition & 0 deletions drivers/i2c/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Gobot has a extensible system for connecting to hardware devices. The following
- MPL115A2 Barometer
- MPU6050 Accelerometer/Gyroscope
- PCA9685 16-channel 12-bit PWM/Servo Driver
- SHT2x Temperature/Humidity
- SHT3x-D Temperature/Humidity
- SSD1306 OLED Display Controller
- TSL2561 Digital Luminosity/Lux/Light Sensor
Expand Down
259 changes: 259 additions & 0 deletions drivers/i2c/sht2x_driver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
/*
* Copyright (c) 2016-2017 Weston Schmidt <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package i2c

// SHT2xDriver is a driver for the SHT2x based devices.
//
// This module was tested with Sensirion SHT21 Breakout.

import (
"errors"
"time"

"github.com/sigurn/crc8"
"gobot.io/x/gobot"
)

const (
// SHT2xDefaultAddress is the default I2C address for SHT2x
SHT2xDefaultAddress = 0x40

// SHT2xAccuracyLow is the faster, but lower accuracy sample setting
// 0/1 = 8bit RH, 12bit Temp
SHT2xAccuracyLow = byte(0x01)

// SHT2xAccuracyMedium is the medium accuracy and speed sample setting
// 1/0 = 10bit RH, 13bit Temp
SHT2xAccuracyMedium = byte(0x80)

// SHT2xAccuracyHigh is the high accuracy and slowest sample setting
// 0/0 = 12bit RH, 14bit Temp
// Power on default is 0/0
SHT2xAccuracyHigh = byte(0x00)

// SHT2xTriggerTempMeasureHold is the command for measureing temperature in hold master mode
SHT2xTriggerTempMeasureHold = 0xe3

// SHT2xTriggerHumdMeasureHold is the command for measureing humidity in hold master mode
SHT2xTriggerHumdMeasureHold = 0xe5

// SHT2xTriggerTempMeasureNohold is the command for measureing humidity in no hold master mode
SHT2xTriggerTempMeasureNohold = 0xf3

// SHT2xTriggerHumdMeasureNohold is the command for measureing humidity in no hold master mode
SHT2xTriggerHumdMeasureNohold = 0xf5

// SHT2xWriteUserReg is the command for writing user register
SHT2xWriteUserReg = 0xe6

// SHT2xReadUserReg is the command for reading user register
SHT2xReadUserReg = 0xe7

// SHT2xReadUserReg is the command for reading user register
SHT2xSoftReset = 0xfe
)

// SHT2xDriver is a Driver for a SHT2x humidity and temperature sensor
type SHT2xDriver struct {
Units string

name string
connector Connector
connection Connection
Config
sht2xAddress int
accuracy byte
delay time.Duration
crcTable *crc8.Table
}

// NewSHT2xDriver creates a new driver with specified i2c interface
// Params:
// conn Connector - the Adaptor to use with this Driver
//
// Optional params:
// i2c.WithBus(int): bus to use with this driver
// i2c.WithAddress(int): address to use with this driver
//
func NewSHT2xDriver(a Connector, options ...func(Config)) *SHT2xDriver {
// From the document "CRC Checksum Calculation -- For Safe Communication with SHT2x Sensors":
crc8Params := crc8.Params{0x31, 0x00, false, false, 0x00, 0x00, "CRC-8/SENSIRION-SHT2x"}
s := &SHT2xDriver{
Units: "C",
name: gobot.DefaultName("SHT2x"),
connector: a,
Config: NewConfig(),
crcTable: crc8.MakeTable(crc8Params),
}

for _, option := range options {
option(s)
}

return s
}

// Name returns the name for this Driver
func (d *SHT2xDriver) Name() string { return d.name }

// SetName sets the name for this Driver
func (d *SHT2xDriver) SetName(n string) { d.name = n }

// Connection returns the connection for this Driver
func (d *SHT2xDriver) Connection() gobot.Connection { return d.connector.(gobot.Connection) }

// Start initializes the SHT2x
func (d *SHT2xDriver) Start() (err error) {
bus := d.GetBusOrDefault(d.connector.GetDefaultBus())
address := d.GetAddressOrDefault(SHT2xDefaultAddress)

if d.connection, err = d.connector.GetConnection(address, bus); err != nil {
return
}

if err = d.Reset(); err != nil {
return
}

d.sendAccuracy()

return
}

// Halt returns true if devices is halted successfully
func (d *SHT2xDriver) Halt() (err error) { return }

func (d *SHT2xDriver) Accuracy() byte { return d.accuracy }

// SetAccuracy sets the accuracy of the sampling
func (d *SHT2xDriver) SetAccuracy(acc byte) (err error) {
d.accuracy = acc

if d.connection != nil {
err = d.sendAccuracy()
}

return
}

// Reset does a software reset of the device
func (d *SHT2xDriver) Reset() (err error) {
if err = d.connection.WriteByte(SHT2xSoftReset); err != nil {
return
}

time.Sleep(15 * time.Millisecond) // 15ms delay (from the datasheet 5.5)

return
}

// Temperature returns the current temperature, in celsius degrees.
func (d *SHT2xDriver) Temperature() (temp float32, err error) {
var rawT uint16
if rawT, err = d.readSensor(SHT2xTriggerTempMeasureNohold); err != nil {
return
}

// From the datasheet 6.2:
// T[C] = -46.85 + 175.72 * St / 2^16
temp = -46.85 + 175.72/65536.0*float32(rawT)

return
}

// Humidity returns the current humidity in percentage of relative humidity
func (d *SHT2xDriver) Humidity() (humidity float32, err error) {
var rawH uint16
if rawH, err = d.readSensor(SHT2xTriggerHumdMeasureNohold); err != nil {
return
}

// From the datasheet 6.1:
// RH = -6 + 125 * Srh / 2^16
humidity = -6.0 + 125.0/65536.0*float32(rawH)

return
}

// sendCommandDelayGetResponse is a helper function to reduce duplicated code
func (d *SHT2xDriver) readSensor(cmd byte) (read uint16, err error) {
if err = d.connection.WriteByte(cmd); err != nil {
return
}

//Hang out while measurement is taken. 85ms max, page 9 of datasheet.
time.Sleep(85 * time.Millisecond)

//Comes back in three bytes, data(MSB) / data(LSB) / Checksum
buf := make([]byte, 3)
counter := 0
for {
var got int
got, err = d.connection.Read(buf)
counter++
if counter > 50 {
return
}
if err == nil {
if got != 3 {
err = ErrNotEnoughBytes
return
}
break
}
time.Sleep(1 * time.Millisecond)
}

//Store the result
crc := crc8.Checksum(buf[0:2], d.crcTable)
if buf[2] != crc {
err = errors.New("Invalid crc")
return
}
read = uint16(buf[0])<<8 | uint16(buf[1])
read &= 0xfffc // clear two low bits (status bits)

return
}

func (d *SHT2xDriver) sendAccuracy() (err error) {
if err = d.connection.WriteByte(SHT2xReadUserReg); err != nil {
return
}
userRegister, err := d.connection.ReadByte()
if err != nil {
return
}

userRegister &= 0x7e //Turn off the resolution bits
acc := d.accuracy
acc &= 0x81 //Turn off all other bits but resolution bits
userRegister |= acc //Mask in the requested resolution bits

//Request a write to user register
_, err = d.connection.Write([]byte{SHT2xWriteUserReg, userRegister})
if err != nil {
return
}

userRegister, err = d.connection.ReadByte()
if err != nil {
return
}

return
}
Loading

0 comments on commit c2689ef

Please sign in to comment.