From e77ee06305e3252e58d9a35d0b06a99b3888c0df Mon Sep 17 00:00:00 2001 From: Frode Austvik Date: Sat, 24 Aug 2013 17:12:11 +0200 Subject: [PATCH] Added support for the 0C45:7402 TEMPerHumM12V1.0, which uses a Si7005 sensor. --- libtempered/temper_type.c | 33 +++++++++++++++ libtempered/type_hid/si7005.c | 80 +++++++++++++++++++++++++++++++++++ libtempered/type_hid/si7005.h | 20 +++++++++ 3 files changed, 133 insertions(+) create mode 100644 libtempered/type_hid/si7005.c create mode 100644 libtempered/type_hid/si7005.h diff --git a/libtempered/temper_type.c b/libtempered/temper_type.c index caf2c2f..1b00b20 100644 --- a/libtempered/temper_type.c +++ b/libtempered/temper_type.c @@ -9,6 +9,7 @@ #include "type_hid/fm75.h" #include "type_hid/sht1x.h" #include "type_hid/ntc.h" +#include "type_hid/si7005.h" // This is an array of known TEMPer types. struct temper_type known_temper_types[]={ @@ -35,6 +36,7 @@ struct temper_type known_temper_types[]={ .response_count = 2, .subtype_strings = (char *[]){ "TEMPerHumV1.0rHu", + "TEMPerHumM12V1.0", NULL } }, @@ -70,6 +72,37 @@ struct temper_type known_temper_types[]={ } } }, + (struct temper_subtype*)&(struct temper_subtype_hid){ + .base = { + .id = 1, + .name = "TEMPerHumM12V1.0", + .open = tempered_type_hid_subtype_open, + .read_sensors = tempered_type_hid_read_sensors, + .get_temperature = tempered_type_hid_get_temperature, + .get_humidity = tempered_type_hid_get_humidity + }, + .sensor_group_count = 1, + .sensor_groups = (struct tempered_type_hid_sensor_group[]){ + { + .query = { + .length = 9, + .data = (unsigned char[]){ 0, 1, 0x80, 0x33, 1, 0, 0, 0, 0 } + }, + .read_sensors = tempered_type_hid_read_sensor_group, + .sensor_count = 1, + .sensors = (struct tempered_type_hid_sensor[]){ + { + .get_temperature = tempered_type_hid_get_temperature_si7005, + .get_humidity = tempered_type_hid_get_humidity_si7005, + .temperature_high_byte_offset = 2, + .temperature_low_byte_offset = 3, + .humidity_high_byte_offset = 4, + .humidity_low_byte_offset = 5 + } + } + } + } + }, NULL // List terminator for subtypes } }, diff --git a/libtempered/type_hid/si7005.c b/libtempered/type_hid/si7005.c new file mode 100644 index 0000000..11745da --- /dev/null +++ b/libtempered/type_hid/si7005.c @@ -0,0 +1,80 @@ +#include +#include + +#include "type-info.h" +#include "../tempered-internal.h" + +bool tempered_type_hid_get_temperature_si7005( + tempered_device *device, struct tempered_type_hid_sensor *sensor, + struct tempered_type_hid_query_result *group_data, float *tempC +) { + if ( + group_data->length <= sensor->temperature_high_byte_offset || + group_data->length <= sensor->temperature_low_byte_offset + ) { + tempered_set_error( + device, strdup( "Not enough data was read from the sensor." ) + ); + return false; + } + + // Convert from two separate data bytes to a single integer. + // The result should be an unsigned int between 0x0000 and 0xFFFF. + int low_byte_offset = sensor->temperature_low_byte_offset; + int high_byte_offset = sensor->temperature_high_byte_offset; + int temp = ( group_data->data[low_byte_offset] & 0xFF ) + + ( ( group_data->data[high_byte_offset] & 0xFF ) << 8 ) + ; + + // According to the Silicon Labs Si7005 datasheet, there's 32 codes per ℃ + // with 0x0000 = -50℃. + *tempC = ((float)temp) / 32 - 50; + + return true; +} + +bool tempered_type_hid_get_humidity_si7005( + tempered_device *device, struct tempered_type_hid_sensor *sensor, + struct tempered_type_hid_query_result *group_data, float *rel_hum +) { + float tempC; + if ( + !tempered_type_hid_get_temperature_si7005( + device, sensor, group_data, &tempC + ) + ) { + return false; + } + + if ( + group_data->length <= sensor->humidity_high_byte_offset || + group_data->length <= sensor->humidity_low_byte_offset + ) + { + tempered_set_error( + device, strdup( "Not enough data was read from the sensor." ) + ); + return false; + } + + int low_byte_offset = sensor->humidity_low_byte_offset; + int high_byte_offset = sensor->humidity_high_byte_offset; + int rh = ( group_data->data[low_byte_offset] & 0xFF ) + + ( ( group_data->data[high_byte_offset] & 0xFF ) << 8 ) + ; + + // These formulas and values are based on the Silicon Labs Si7005 datasheet + + // There's 16 codes per %RH, with 0x0000 = -24%RH + float relhum = ((float)rh) / 16 - 24; + + // Linearization + relhum -= -0.00393 * relhum * relhum + 0.4008 * relhum - 4.7844; + + // Temperature compensation + relhum += ( tempC - 30 ) * ( 0.00237 * relhum + 0.1973 ); + + *rel_hum = relhum; + + return true; +} diff --git a/libtempered/type_hid/si7005.h b/libtempered/type_hid/si7005.h new file mode 100644 index 0000000..20d2756 --- /dev/null +++ b/libtempered/type_hid/si7005.h @@ -0,0 +1,20 @@ +#ifndef TEMPERED__TYPE_HID__SI7005_H +#define TEMPERED__TYPE_HID__SI7005_H + +#include + +#include "type-info.h" + +// These methods are for the Silicon Labs Si7005 chip. + +bool tempered_type_hid_get_temperature_si7005( + tempered_device *device, struct tempered_type_hid_sensor *sensor, + struct tempered_type_hid_query_result *group_data, float *tempC +); + +bool tempered_type_hid_get_humidity_si7005( + tempered_device *device, struct tempered_type_hid_sensor *sensor, + struct tempered_type_hid_query_result *group_data, float *rel_hum +); + +#endif