sht1x: Initial implementation

This driver was developed with a DFRobot SHT10 Temperature and Humidity
sensor.  This driver should work on all SHT1X devices.

It requires a 10K pull-up resistor connected to the data pin.
The sensor can be run at differing voltages from 2.5v to 5v.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
This commit is contained in:
Jon Trulson 2016-09-16 16:50:09 -06:00
parent 5d4fc3cbf5
commit 239ab49d6b
19 changed files with 1482 additions and 0 deletions

View File

@ -306,6 +306,7 @@ add_example (bh1750)
add_example (hka5)
add_example (dfrorp)
add_example (dfrec)
add_example (sht1x)
# These are special cases where you specify example binary, source file and module(s)
include_directories (${PROJECT_SOURCE_DIR}/src)

77
examples/c++/sht1x.cxx Normal file
View File

@ -0,0 +1,77 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <iostream>
#include <signal.h>
#include "sht1x.hpp"
using namespace std;
bool shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main()
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate a SHT1X sensor using D2 as the clock, and D3 as the
// data pin.
upm::SHT1X *sensor = new upm::SHT1X(2, 3);
// Every 2 seconds, update and print values
while (shouldRun)
{
sensor->update();
cout << "Temperature: "
<< sensor->getTemperature()
<< " C"
<< endl;
cout << "Humidity: "
<< sensor->getHumidity()
<< " RH"
<< endl;
cout << endl;
sleep(2);
}
//! [Interesting]
cout << "Exiting" << endl;
delete sensor;
return 0;
}

View File

@ -118,6 +118,7 @@ add_example (moisture)
add_example (led)
add_example (ds18b20)
add_example (dfrec)
add_example (sht1x)
# Custom examples
add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps)

77
examples/c/sht1x.c Normal file
View File

@ -0,0 +1,77 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <signal.h>
#include "sht1x.h"
bool shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main()
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate a SHT1X sensor using D2 as the clock, and D3 as the
// data pin.
sht1x_context sensor = sht1x_init(2, 3);
if (!sensor)
{
printf("sht1x_init() failed.\n");
return 1;
}
// Every 2 seconds, update and print values
while (shouldRun)
{
if (sht1x_update(sensor))
{
printf("sht1x_update() failed, exiting.\n");
break;
}
printf("Temperature: %f C\n", sht1x_get_temperature(sensor));
printf("Humidity: %f RH\n", sht1x_get_humidity(sensor));
printf("\n");
sleep(2);
}
//! [Interesting]
printf("Exiting\n");
sht1x_close(sensor);
return 0;
}

View File

@ -156,6 +156,7 @@ add_example(BH1750_Example bh1750)
add_example(HKA5_Example hka5)
add_example(DFRORP_Example dfrorp)
add_example(DFREC_Example dfrec)
add_example(SHT1X_Example sht1x)
add_example_with_path(Jhd1313m1_lcdSample lcd i2clcd)
add_example_with_path(Jhd1313m1Sample lcd i2clcd)

View File

@ -0,0 +1,55 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import upm_sht1x.SHT1X;
public class SHT1X_Example
{
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// Instantiate a SHT1X sensor using D2 as the clock, and D3 as the
// data pin.
SHT1X sensor = new SHT1X(2, 3);
// Every 2 seconds, update and print values
while (true)
{
sensor.update();
System.out.println("Temperature: "
+ sensor.getTemperature()
+ " C");
System.out.println("Humidity: "
+ sensor.getHumidity()
+ " RH");
System.out.println();
Thread.sleep(2000);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,55 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var sensorObj = require('jsupm_sht1x');
// Instantiate a SHT1X sensor using D2 as the clock, and D3 as the
// data pin.
var sensor = new sensorObj.SHT1X(2, 3);
// Every 2 seconds, update and print values
setInterval(function()
{
sensor.update();
console.log("Temperature: "
+ sensor.getTemperature()
+ " C");
console.log("Humidity: "
+ sensor.getHumidity()
+ " RH");
console.log();
}, 2000);
// exit on ^C
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting.");
process.exit(0);
});

53
examples/python/sht1x.py Normal file
View File

@ -0,0 +1,53 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 Intel Corporation.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import time, sys, signal, atexit
import pyupm_sht1x as sensorObj
# Instantiate a SHT1X sensor using D2 as the clock, and D3 as the
# data pin.
sensor = sensorObj.SHT1X(2, 3)
## Exit handlers ##
# This function stops python from printing a stacktrace when you hit control-C
def SIGINTHandler(signum, frame):
raise SystemExit
# This function lets you run code on exit
def exitHandler():
print "Exiting"
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
# Every 2 seconds, update and print values
while (True):
sensor.update()
print "Temperature:", sensor.getTemperature(), "C"
print "Humidity: ", sensor.getHumidity(), "RH"
print
time.sleep(2)

View File

@ -0,0 +1,42 @@
/*
* Authors: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef UPM_HUMIDITY_H_
#define UPM_HUMIDITY_H_
#ifdef __cplusplus
extern "C" {
#endif
// Humidity function table
typedef struct _upm_humidity_ft {
upm_result_t (*upm_humidity_set_scale) (void* dev, float scale);
upm_result_t (*upm_humidity_set_offset) (void* dev, float offset);
upm_result_t (*upm_humidity_get_value) (void* dev, float* value);
} upm_humidity_ft;
#ifdef __cplusplus
}
#endif
#endif /* UPM_HUMIDITY_H_ */

View File

@ -1,5 +1,6 @@
/*
* Authors:
* Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
@ -118,6 +119,7 @@ typedef struct _upm_sensor_ft* (*func_get_upm_sensor_ft)(upm_sensor_t sensor_typ
#include <fti/upm_stream.h>
#include <fti/upm_orp.h>
#include <fti/upm_ec.h>
#include <fti/upm_humidity.h>
#ifdef __cplusplus
}

9
src/sht1x/CMakeLists.txt Normal file
View File

@ -0,0 +1,9 @@
upm_mixed_module_init (NAME sht1x
DESCRIPTION "UPM driver for the SHT1X temperature/humidity sensor"
C_HDR sht1x.h
C_SRC sht1x.c
CPP_HDR sht1x.hpp
CPP_SRC sht1x.cxx
FTI_SRC sht1x_fti.c
CPP_WRAPS_C
REQUIRES mraa)

21
src/sht1x/javaupm_sht1x.i Normal file
View File

@ -0,0 +1,21 @@
%module javaupm_sht1x
%include "../upm.i"
%include "std_string.i"
%include "stdint.i"
%include "typemaps.i"
%include "sht1x.hpp"
%{
#include "sht1x.hpp"
%}
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("javaupm_sht1x");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}

8
src/sht1x/jsupm_sht1x.i Normal file
View File

@ -0,0 +1,8 @@
%module jsupm_sht1x
%include "../upm.i"
%include "std_string.i"
%include "sht1x.hpp"
%{
#include "sht1x.hpp"
%}

12
src/sht1x/pyupm_sht1x.i Normal file
View File

@ -0,0 +1,12 @@
// Include doxygen-generated documentation
%include "pyupm_doxy2swig.i"
%module pyupm_sht1x
%include "../upm.i"
%include "std_string.i"
%feature("autodoc", "3");
%include "sht1x.hpp"
%{
#include "sht1x.hpp"
%}

401
src/sht1x/sht1x.c Normal file
View File

@ -0,0 +1,401 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include <assert.h>
#include "upm_utilities.h"
#include "sht1x.h"
sht1x_context sht1x_init(unsigned int clk_pin, unsigned int data_pin)
{
sht1x_context dev =
(sht1x_context)malloc(sizeof(struct _sht1x_context));
if (!dev)
return NULL;
// zero out context
memset((void *)dev, 0, sizeof(struct _sht1x_context));
dev->gpio_clk = NULL;
dev->gpio_data = NULL;
// initialize the MRAA contexts
// clock
if (!(dev->gpio_clk = mraa_gpio_init(clk_pin)))
{
printf("%s: mraa_gpio_init(clk) failed.\n", __FUNCTION__);
sht1x_close(dev);
return NULL;
}
mraa_gpio_dir(dev->gpio_clk, MRAA_GPIO_OUT);
if (mraa_gpio_use_mmaped(dev->gpio_clk, 1))
{
// not fatal, just slower
printf("%s: warning, mraa_gpio_use_mmaped(clk) failed.\n",
__FUNCTION__);
}
// data
if (!(dev->gpio_data = mraa_gpio_init(data_pin)))
{
printf("%s: mraa_gpio_init(data) failed.\n", __FUNCTION__);
sht1x_close(dev);
return NULL;
}
mraa_gpio_dir(dev->gpio_data, MRAA_GPIO_OUT);
mraa_gpio_mode(dev->gpio_data, MRAA_GPIO_PULLUP);
if (mraa_gpio_use_mmaped(dev->gpio_data, 1))
{
// not fatal, just slower
printf("%s: warning, mraa_gpio_use_mmaped(data) failed.\n",
__FUNCTION__);
}
// max init time
upm_delay_ms(15);
// now read the status register to see if we are highres (14b) or not
uint8_t status;
if (sht1x_read_status(dev, &status))
{
printf("%s: sht1x_read_status() failed.\n", __FUNCTION__);
sht1x_close(dev);
return NULL;
}
if (status & SHT1X_STATUS_RESOLUTION_LOW)
dev->hires = false;
else
dev->hires = true;
// setup our coefficients (see the datasheet). We always assume 5v
// here. We also only deal with Celcius.
// this will set coeff_d1
sht1x_set_volts(dev, SHT1X_VOLTS_5);
dev->coeff_c1 = -2.0468;
dev->coeff_t1 = 0.01;
if (dev->hires)
{
dev->coeff_d2 = 0.01;
dev->coeff_c2 = 0.0367;
dev->coeff_c3 = -1.5955e-6;
dev->coeff_t2 = 0.00008;
}
else
{
dev->coeff_d2 = 0.04;
dev->coeff_c2 = 0.5872;
dev->coeff_c3 = -4.0845e-4;
dev->coeff_t2 = 0.00128;
}
return dev;
}
void sht1x_close(sht1x_context dev)
{
assert(dev != NULL);
if (dev->gpio_clk)
mraa_gpio_close(dev->gpio_clk);
if (dev->gpio_data)
mraa_gpio_close(dev->gpio_data);
free(dev);
}
upm_result_t sht1x_update(const sht1x_context dev)
{
assert(dev != NULL);
// byte 3 is the checksum which we currently ignore
uint8_t byte1, byte2, byte3;
// first read the temperature
sht1x_send_command(dev, SHT1X_CMD_MEAS_TEMPERATURE);
if (sht1x_wait_for_response(dev))
{
printf("%s: wait_for_response(temp) failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
sht1x_read_8bits(dev, &byte1);
sht1x_read_8bits(dev, &byte2);
sht1x_read_8bits(dev, &byte3);
int temp = (byte1 << 8) | byte2;
// printf("temp %d (0x%04x)\n", temp, temp);
// compute temperature
dev->temperature = dev->coeff_d1 + dev->coeff_d2 * (float)temp;
// now get humidity
sht1x_send_command(dev, SHT1X_CMD_MEAS_HUMIDITY);
if (sht1x_wait_for_response(dev))
{
printf("%s: wait_for_response(hum) failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
sht1x_read_8bits(dev, &byte1);
sht1x_read_8bits(dev, &byte2);
sht1x_read_8bits(dev, &byte3);
temp = (byte1 << 8) | byte2;
// first we compute a linear humidity reading, then apply temperature
// compensation
float linHumidity = dev->coeff_c1 + dev->coeff_c2 * (float)temp
+ dev->coeff_c3 * (float)temp * (float)temp;
// convert to "true" RH (temperature compensated)
dev->humidity = (dev->temperature - 25.0) * (dev->coeff_t1 + dev->coeff_t2)
+ linHumidity;
if (dev->humidity > 99.0)
dev->humidity = 100.0;
return UPM_SUCCESS;
}
void sht1x_start_xmit(const sht1x_context dev)
{
mraa_gpio_dir(dev->gpio_data, MRAA_GPIO_OUT);
// start sequence
mraa_gpio_write(dev->gpio_data, 1);
mraa_gpio_write(dev->gpio_clk, 1);
mraa_gpio_write(dev->gpio_data, 0);
mraa_gpio_write(dev->gpio_clk, 0);
mraa_gpio_write(dev->gpio_clk, 1);
mraa_gpio_write(dev->gpio_data, 1);
mraa_gpio_write(dev->gpio_clk, 0);
}
upm_result_t sht1x_write_8bits(const sht1x_context dev, uint8_t byte)
{
// send the byte
mraa_gpio_dir(dev->gpio_data, MRAA_GPIO_OUT);
int i;
for (i=0; i<8; i++)
{
if (byte & 0x80)
mraa_gpio_write(dev->gpio_data, 1);
else
mraa_gpio_write(dev->gpio_data, 0);
mraa_gpio_write(dev->gpio_clk, 1);
mraa_gpio_write(dev->gpio_clk, 0);
byte <<= 1;
}
// now wait for the ack response. After the falling edge of the 8th
// clock (above), the data line should be pulled low. Then, after
// the falling edge of the ninth clock pulse, the data line should
// go high. We check the data line after the rising edge of the
// ninth clock to make sure it went low.
bool ackError = false;
mraa_gpio_dir(dev->gpio_data, MRAA_GPIO_IN);
// start 9th clock
mraa_gpio_write(dev->gpio_clk, 1);
// should be low. If it's high, there is a problem.
if (mraa_gpio_read(dev->gpio_data))
ackError = true;
// finish 9th clock
mraa_gpio_write(dev->gpio_clk, 0);
if (ackError)
{
printf("%s: didn't receive proper ACK from SHT1X.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
return UPM_SUCCESS;
}
upm_result_t sht1x_send_command(const sht1x_context dev, SHT1X_CMD_T cmd)
{
assert(dev != NULL);
sht1x_start_xmit(dev);
// send the command
return sht1x_write_8bits(dev, (uint8_t)cmd);
}
upm_result_t sht1x_wait_for_response(const sht1x_context dev)
{
assert(dev != NULL);
const int maxRetries = 500;
int r = 0;
mraa_gpio_dir(dev->gpio_data, MRAA_GPIO_IN);
// we wait for some time (about .5 seconds, more than enough time)
// for the data line to be pulled low.
while (r++ < maxRetries)
{
if (!mraa_gpio_read(dev->gpio_data))
break;
upm_delay_ms(1);
}
if (r >= maxRetries)
{
printf("%s: no response to measurement request.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
// printf("%s: retries: %d\n", __FUNCTION__, r);
return UPM_SUCCESS;
}
void sht1x_read_8bits(const sht1x_context dev, uint8_t *value)
{
assert(dev != NULL);
// we need to read a byte, and acknowlege it
uint8_t byte = 0;
mraa_gpio_dir(dev->gpio_data, MRAA_GPIO_IN);
int i;
for (i=0; i<8; i++)
{
mraa_gpio_write(dev->gpio_clk, 1);
if (mraa_gpio_read(dev->gpio_data))
byte |= 1;
// don't shift on the last bit!
if (i != 7)
byte <<= 1;
mraa_gpio_write(dev->gpio_clk, 0);
}
*value = byte;
// send the ack
mraa_gpio_dir(dev->gpio_data, MRAA_GPIO_OUT);
// pull data line low
mraa_gpio_write(dev->gpio_data, 0);
// cycle the clock
mraa_gpio_write(dev->gpio_clk, 1);
mraa_gpio_write(dev->gpio_clk, 0);
// release data line
mraa_gpio_write(dev->gpio_data, 1);
}
float sht1x_get_temperature(const sht1x_context dev)
{
assert(dev != NULL);
return dev->temperature;
}
float sht1x_get_humidity(const sht1x_context dev)
{
assert(dev != NULL);
return dev->humidity;
}
void sht1x_reset(const sht1x_context dev)
{
assert(dev != NULL);
sht1x_send_command(dev, SHT1X_CMD_SOFT_RESET);
upm_delay_ms(20);
}
upm_result_t sht1x_read_status(const sht1x_context dev, uint8_t *status)
{
assert(dev != NULL);
upm_result_t rv;
if ((rv = sht1x_send_command(dev, SHT1X_CMD_READ_STATUS)))
{
printf("%s: send_command() failed.\n", __FUNCTION__);
return rv;
}
sht1x_read_8bits(dev, status);
return UPM_SUCCESS;
}
upm_result_t sht1x_write_status(const sht1x_context dev, uint8_t status)
{
assert(dev != NULL);
upm_result_t rv;
if ((rv = sht1x_send_command(dev, SHT1X_CMD_WRITE_STATUS)))
{
printf("%s: send_command() failed.\n", __FUNCTION__);
return rv;
}
return sht1x_write_8bits(dev, status);
}
void sht1x_set_volts(const sht1x_context dev, SHT1X_VOLTS_T volts)
{
assert(dev != NULL);
switch (volts)
{
case SHT1X_VOLTS_5: dev->coeff_d1 = -40.1; break;
case SHT1X_VOLTS_4: dev->coeff_d1 = -39.8; break;
case SHT1X_VOLTS_3_5: dev->coeff_d1 = -39.7; break;
case SHT1X_VOLTS_3: dev->coeff_d1 = -39.6; break;
case SHT1X_VOLTS_2_5: dev->coeff_d1 = -39.4; break;
}
}

116
src/sht1x/sht1x.cxx Normal file
View File

@ -0,0 +1,116 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <iostream>
#include <stdexcept>
#include "sht1x.hpp"
using namespace upm;
using namespace std;
SHT1X::SHT1X(unsigned int clk_pin, unsigned int data_pin) :
m_sht1x(sht1x_init(clk_pin, data_pin))
{
if (!m_sht1x)
throw std::runtime_error(string(__FUNCTION__)
+ ": sht1x_init() failed");
}
SHT1X::~SHT1X()
{
sht1x_close(m_sht1x);
}
void SHT1X::reset()
{
sht1x_reset(m_sht1x);
}
void SHT1X::update()
{
if (sht1x_update(m_sht1x))
throw std::runtime_error(string(__FUNCTION__)
+ ": sht1x_update() failed");
}
float SHT1X::getTemperature()
{
return sht1x_get_temperature(m_sht1x);
}
float SHT1X::getHumidity()
{
return sht1x_get_humidity(m_sht1x);
}
uint8_t SHT1X::readStatus()
{
uint8_t status;
if (sht1x_read_status(m_sht1x, &status))
throw std::runtime_error(string(__FUNCTION__)
+ ": sht1x_read_status() failed");
return status;
}
upm_result_t SHT1X::writeStatus(uint8_t status)
{
return sht1x_write_status(m_sht1x, status);
}
void SHT1X::setVolts(SHT1X_VOLTS_T volts)
{
sht1x_set_volts(m_sht1x, volts);
}
upm_result_t SHT1X::sendCommand(SHT1X_CMD_T cmd)
{
return sht1x_send_command(m_sht1x, cmd);
}
upm_result_t SHT1X::waitForResponse()
{
return sht1x_wait_for_response(m_sht1x);
}
void SHT1X::startXmit()
{
sht1x_start_xmit(m_sht1x);
}
uint8_t SHT1X::read8Bits()
{
uint8_t value;
sht1x_read_8bits(m_sht1x, &value);
return value;
}
upm_result_t SHT1X::write8Bits(uint8_t byte)
{
return sht1x_write_8bits(m_sht1x, byte);
}

243
src/sht1x/sht1x.h Normal file
View File

@ -0,0 +1,243 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <stdint.h>
#include "upm.h"
#include "mraa/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief SHT1X Temperature and Humidity Sensor
*
* This driver was tested with a DFRobot SHT10 Temperature and
* Humidity sensor. This driver should work on all SHT1X devices.
*
* It requires a 10K pull-up resistor connected to the data pin.
* The sensor can be run at differing voltages from 2.5v to 5v.
*
* @snippet sht1x.c Interesting
*/
/**
* Device context
*/
typedef struct _sht1x_context {
mraa_gpio_context gpio_clk;
mraa_gpio_context gpio_data;
// high res? (temp/hum 14/12b vs. 12/8b)
bool hires;
// our data
float temperature;
float humidity;
// temperature coeff (we only care about C)
float coeff_d1;
float coeff_d2;
// humidity coeff
float coeff_c1;
float coeff_c2;
float coeff_c3;
float coeff_t1;
float coeff_t2;
} *sht1x_context;
// SHT1X commands. The first 3 msb's are the address, which are
// always 0. The following 5 bits are the actual command.
typedef enum {
SHT1X_CMD_MEAS_TEMPERATURE = 0x03,
SHT1X_CMD_MEAS_HUMIDITY = 0x05,
SHT1X_CMD_WRITE_STATUS = 0x06,
SHT1X_CMD_READ_STATUS = 0x07,
SHT1X_CMD_SOFT_RESET = 0x1e
} SHT1X_CMD_T;
// status register bits
typedef enum {
SHT1X_STATUS_RESOLUTION_LOW = 0x01, // 0=12b RH/14b temp (dflt)
SHT1X_STATUS_NO_RELOAD_FROM_OTP = 0x02,
SHT1X_STATUS_HEATER_EN = 0x04,
// 0x08-0x20 reserved
SHT1X_STATUS_LOW_VOLT = 0x40 // low battery
// 0x80 reserved
} SHT1X_STATUS_BITS_T;
// The Vdd voltage can affect the temperature coefficients, so we
// provide a way to indicate the closest voltage and set up the
// compensation accordingly.
typedef enum {
SHT1X_VOLTS_5 = 0, // 5 volts
SHT1X_VOLTS_4 = 1,
SHT1X_VOLTS_3_5 = 2, // 3.5v
SHT1X_VOLTS_3 = 3,
SHT1X_VOLTS_2_5 = 4
} SHT1X_VOLTS_T;
/**
* SHT1X Initializer
*
* @param clk_pin Specify the GPIO pin to use for the clock.
* @param data_pin Specify the GPIO pin to use for data.
* @return an initialized device context on success, NULL on error.
*/
sht1x_context sht1x_init(unsigned int clk_pin, unsigned int data_pin);
/**
* SHT1X sensor close function
*/
void sht1x_close(sht1x_context dev);
/**
* Perform a soft reset of the device.
*
* @param dev sensor context
* @return UPM result
*/
void sht1x_reset(const sht1x_context dev);
/**
* Query the device and store the latest values. You must call this
* function before querying the temperature or the humidity.
*
* @param dev sensor context
* @return UPM result
*/
upm_result_t sht1x_update(const sht1x_context dev);
/**
* Query the temperature in degrees Celsius. sht1x_update() must
* have been called prior to calling this function.
*
* @param dev sensor context
* @return The temperature in Celsius
*/
float sht1x_get_temperature(const sht1x_context dev);
/**
* Query the relative humidity. sht1x_update() must have been
* called prior to calling this function.
*
* @param dev sensor context
* @return The relative humidity.
*/
float sht1x_get_humidity(const sht1x_context dev);
/**
* Read the status register.
*
* @param dev sensor context
* @param status The pointer to a uint8_t the status register will
* be stored in.
* @return UPM result
*/
upm_result_t sht1x_read_status(const sht1x_context dev, uint8_t *status);
/**
* Write a value to the status register.
*
* @param dev sensor context
* @param status The uint8_t to write to the register.
* @return UPM result
*/
upm_result_t sht1x_write_status(const sht1x_context dev, uint8_t status);
/**
* The Vdd voltage the sensor is being driven at can affect the
* temperature measurements. This function allows you to specify a
* voltage as close as you are using to power the sensor, so that
* the appropriate compensation can be made. By default, the
* coefficients are set for 5v operation.
*
* @param dev sensor context
* @param volts One of the SHT1X_VOLTS_T values.
*/
void sht1x_set_volts(const sht1x_context dev, SHT1X_VOLTS_T volts);
/**
* Send a command to the device. This is a low level command that
* should not be used directly unless you know exactly what you are
* doing.
*
* @param dev sensor context
* @param cmd One of the SHT1X_CMD_T values.
* @return UPM result
*/
upm_result_t sht1x_send_command(const sht1x_context dev, SHT1X_CMD_T cmd);
/**
* Wait for the appropriate response when starting a temperature or
* humidity measurement. This is a low level command that should
* not be used directly unless you know exactly what you are doing.
*
* @param dev sensor context
* @return UPM result
*/
upm_result_t sht1x_wait_for_response(const sht1x_context dev);
/**
* Issue the start transmission sequence. This is a low level
* command that should not be used directly unless you know exactly
* what you are doing.
*
* @param dev sensor context
* @return UPM result
*/
void sht1x_start_xmit(const sht1x_context dev);
/**
* Read 8 bits (a byte) from the device. This is a low level
* command that should not be used directly unless you know exactly
* what you are doing.
*
* @param dev sensor context
* @param value Pointer to a uint8_t that will hold the received byte.
* @return UPM result
*/
void sht1x_read_8bits(const sht1x_context dev, uint8_t *value);
/**
* Write 8 bits (a byte) to the device. This is a low level command
* that should not be used directly unless you know exactly what you
* are doing.
*
* @param dev sensor context
* @param value A uint8_t that will be sent to the device.
* @return UPM result
*/
upm_result_t sht1x_write_8bits(const sht1x_context dev, uint8_t byte);
#ifdef __cplusplus
}
#endif

183
src/sht1x/sht1x.hpp Normal file
View File

@ -0,0 +1,183 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <string>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include "sht1x.h"
namespace upm {
/**
* @brief SHT1X Temperature and Humidity Sensor
* @defgroup sht1x libupm-sht1x
* @ingroup gpio temp
*/
/**
* @library sht1x
* @sensor sht1x
* @comname SHT1X Temperature and Humidity Sensor
* @type temp
* @man dfrobot
* @con gpio
*
* @brief SHT1X Temperature and Humidity Sensor
*
* This driver was tested with a DFRobot SHT10 Temperature and
* Humidity sensor. This driver should work on all SHT1X devices.
*
* It requires a 10K pull-up resistor connected to the data pin.
* The sensor can be run at differing voltages from 2.5v to 5v.
*
* @snippet sht1x.cxx Interesting
*/
class SHT1X {
public:
/**
* SHT1X object constructor
*
* @param clk_pin Specify the GPIO pin to use for the clock.
* @param data_pin Specify the GPIO pin to use for data.
*/
SHT1X(unsigned int clk_pin, unsigned int data_pin);
/**
* SHT1X object destructor
*/
~SHT1X();
/**
* Perform a soft reset of the device.
*/
void reset();
/**
* Query the device and store the latest values. You must call this
* function before querying the temperature or the humidity.
*/
void update();
/**
* Query the temperature in degrees Celsius. update() must have
* been called prior to calling this function.
*
* @return The temperature in Celsius
*/
float getTemperature();
/**
* Query the relative humidity. update() must have been called
* prior to calling this function.
*
* @return The relative humidity.
*/
float getHumidity();
/**
* Read the status register.
*
* @return The contents of the status register.
*/
uint8_t readStatus();
/**
* Write a value to the status register.
*
* @param status The uint8_t to write to the register.
* @return UPM result
*/
upm_result_t writeStatus(uint8_t status);
/**
* The Vdd voltage the sensor is being driven at can affect the
* temperature measurements. This function allows you to specify a
* voltage as close as you are using to power the sensor, so that
* the appropriate compensation can be made. By default, the
* coefficients are set for 5v operation.
*
* @param volts One of the SHT1X_VOLTS_T values.
*/
void setVolts(SHT1X_VOLTS_T volts);
protected:
// device context
sht1x_context m_sht1x;
/**
* Send a command to the device. This is a low level command that
* should not be used directly unless you know exactly what you are
* doing.
*
* @param cmd One of the SHT1X_CMD_T values.
* @return UPM result
*/
upm_result_t sendCommand(SHT1X_CMD_T cmd);
/**
* Wait for the appropriate response when starting a temperature or
* humidity measurement. This is a low level command that should
* not be used directly unless you know exactly what you are doing.
*
* @return UPM result
*/
upm_result_t waitForResponse();
/**
* Issue the start transmission sequence. This is a low level
* command that should not be used directly unless you know exactly
* what you are doing.
*
* @return UPM result
*/
void startXmit();
/**
* Read 8 bits (a byte) from the device. This is a low level
* command that should not be used directly unless you know exactly
* what you are doing.
*
* @param value Pointer to a uint8_t that will hold the received byte.
* @return UPM result
*/
uint8_t read8Bits();
/**
* Write 8 bits (a byte) to the device. This is a low level command
* that should not be used directly unless you know exactly what you
* are doing.
*
* @param value A uint8_t that will be sent to the device.
* @return UPM result
*/
upm_result_t write8Bits(uint8_t byte);
private:
};
}

125
src/sht1x/sht1x_fti.c Normal file
View File

@ -0,0 +1,125 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "sht1x.h"
#include "upm_fti.h"
/**
* This file implements the Function Table Interface (FTI) for this sensor
*/
const char upm_sht1x_name[] = "SHT1X";
const char upm_sht1x_description[] = "SHT1X Temperature and Humidity Sensor";
const upm_protocol_t upm_sht1x_protocol[] = {UPM_GPIO, UPM_GPIO};
const upm_sensor_t upm_sht1x_category[] = {UPM_TEMPERATURE, UPM_HUMIDITY};
// forward declarations
const void* upm_sht1x_get_ft(upm_sensor_t sensor_type);
void* upm_sht1x_init_name();
void upm_sht1x_close(void *dev);
upm_result_t upm_sht1x_get_humidity(void *dev, float *value);
upm_result_t upm_sht1x_get_temperature(void *dev, float *value,
upm_temperature_u unit);
static const upm_sensor_ft ft =
{
.upm_sensor_init_name = upm_sht1x_init_name,
.upm_sensor_close = upm_sht1x_close,
};
static const upm_temperature_ft tft =
{
.upm_temperature_get_value = upm_sht1x_get_temperature,
};
static const upm_humidity_ft hft =
{
.upm_humidity_get_value = upm_sht1x_get_humidity,
};
const void* upm_sht1x_get_ft(upm_sensor_t sensor_type)
{
switch(sensor_type)
{
case UPM_SENSOR:
return &ft;
case UPM_HUMIDITY:
return &hft;
case UPM_TEMPERATURE:
return &tft;
default:
return NULL;
}
}
void* upm_sht1x_init_name()
{
return NULL;
}
void upm_sht1x_close(void *dev)
{
sht1x_close((sht1x_context)dev);
}
upm_result_t upm_sht1x_get_humidity(void *dev, float *value)
{
upm_result_t rv;
if ((rv = sht1x_update((sht1x_context)dev)))
return rv;
*value = sht1x_get_humidity((sht1x_context)dev);
return UPM_SUCCESS;
}
upm_result_t upm_sht1x_get_temperature(void *dev, float *value,
upm_temperature_u unit)
{
upm_result_t rv;
if ((rv = sht1x_update((sht1x_context)dev)))
return rv;
// always in C
float temp = sht1x_get_temperature((sht1x_context)dev);
switch (unit)
{
case CELSIUS:
*value = temp;
return UPM_SUCCESS;
case KELVIN:
*value = temp + 273.15;
return UPM_SUCCESS;
case FAHRENHEIT:
*value = temp * (9.0/5.0) + 32.0;
return UPM_SUCCESS;
}
return UPM_SUCCESS;
}