Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of SHT_v1 by
SHT.cpp@1:0dbbb4802508, 2016-02-23 (annotated)
- Committer:
- fblanc
- Date:
- Tue Feb 23 08:10:54 2016 +0000
- Revision:
- 1:0dbbb4802508
- Parent:
- 0:df1c8f2961a1
SHT V4 5V;
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| roselea | 0:df1c8f2961a1 | 1 | /* mbed module to use a Sensirion SHT1x /SHT7x sensor |
| roselea | 0:df1c8f2961a1 | 2 | * Copyright (c) 2007-2009 Stephen McGarry |
| roselea | 0:df1c8f2961a1 | 3 | * Released under the MIT License: http://mbed.org/license/mit |
| roselea | 0:df1c8f2961a1 | 4 | */ |
| roselea | 0:df1c8f2961a1 | 5 | |
| roselea | 0:df1c8f2961a1 | 6 | #include "SHT.h" |
| roselea | 0:df1c8f2961a1 | 7 | |
| roselea | 0:df1c8f2961a1 | 8 | #include "mbed.h" |
| fblanc | 1:0dbbb4802508 | 9 | #define MICROSECONDE 10//1 |
| roselea | 0:df1c8f2961a1 | 10 | |
| roselea | 0:df1c8f2961a1 | 11 | SHT::SHT(PinName p_sclk, PinName p_data, SHT_acc p_accuracy) : sclk(p_sclk), data(p_data), accuracy(p_accuracy) { |
| roselea | 0:df1c8f2961a1 | 12 | sclk=0; |
| roselea | 0:df1c8f2961a1 | 13 | data=0; // data pin will be used as open collector pin |
| roselea | 0:df1c8f2961a1 | 14 | data.mode(PullUp); // with the pull up internally active |
| roselea | 0:df1c8f2961a1 | 15 | data.input(); // with line released to go high |
| roselea | 0:df1c8f2961a1 | 16 | temperature = humidity = dewpoint=0.0f; |
| fblanc | 1:0dbbb4802508 | 17 | |
| roselea | 0:df1c8f2961a1 | 18 | } |
| roselea | 0:df1c8f2961a1 | 19 | |
| roselea | 0:df1c8f2961a1 | 20 | char SHT::write_byte(byte value) |
| roselea | 0:df1c8f2961a1 | 21 | //---------------------------------------------------------------------------------- |
| roselea | 0:df1c8f2961a1 | 22 | // writes a byte on the Sensibus and checks the acknowledge |
| roselea | 0:df1c8f2961a1 | 23 | { |
| roselea | 0:df1c8f2961a1 | 24 | int i; |
| roselea | 0:df1c8f2961a1 | 25 | char error=0; |
| roselea | 0:df1c8f2961a1 | 26 | |
| roselea | 0:df1c8f2961a1 | 27 | for (i=0x80;i>0;i/=2) { //shift bit for masking |
| roselea | 0:df1c8f2961a1 | 28 | if (i & value) data.input(); //masking value with i , write to SENSI-BUS |
| roselea | 0:df1c8f2961a1 | 29 | else data.output(); |
| fblanc | 1:0dbbb4802508 | 30 | wait_us(MICROSECONDE); //ensure sclk is low for min time |
| fblanc | 1:0dbbb4802508 | 31 | |
| roselea | 0:df1c8f2961a1 | 32 | sclk=1; //clk for SENSI-BUS |
| fblanc | 1:0dbbb4802508 | 33 | wait_us(MICROSECONDE); //pulsewith approx. 2 us |
| roselea | 0:df1c8f2961a1 | 34 | sclk=0; |
| roselea | 0:df1c8f2961a1 | 35 | } |
| roselea | 0:df1c8f2961a1 | 36 | data.input(); //release DATA-line |
| fblanc | 1:0dbbb4802508 | 37 | wait_us(MICROSECONDE); //ensure sclk is low for min time |
| roselea | 0:df1c8f2961a1 | 38 | sclk=1; //clk #9 for ack |
| roselea | 0:df1c8f2961a1 | 39 | error=data; //check ack (DATA will be pulled down by SHT11) |
| fblanc | 1:0dbbb4802508 | 40 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 41 | sclk=0; |
| roselea | 0:df1c8f2961a1 | 42 | return error; //error=1 in case of no acknowledge |
| roselea | 0:df1c8f2961a1 | 43 | } |
| roselea | 0:df1c8f2961a1 | 44 | |
| roselea | 0:df1c8f2961a1 | 45 | byte SHT::read_byte(bool send_ack) |
| roselea | 0:df1c8f2961a1 | 46 | //---------------------------------------------------------------------------------- |
| roselea | 0:df1c8f2961a1 | 47 | // reads a byte form the Sensibus and gives an acknowledge in case of "ack=1" |
| roselea | 0:df1c8f2961a1 | 48 | { |
| roselea | 0:df1c8f2961a1 | 49 | byte i,val=0; |
| roselea | 0:df1c8f2961a1 | 50 | data.input(); //release DATA-line |
| roselea | 0:df1c8f2961a1 | 51 | for (i=0x80;i>0;i/=2) { //shift bit for masking |
| fblanc | 1:0dbbb4802508 | 52 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 53 | sclk=1; //clk for SENSI-BUS |
| roselea | 0:df1c8f2961a1 | 54 | if (data) val=(val | i); //read bit |
| fblanc | 1:0dbbb4802508 | 55 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 56 | sclk=0; |
| roselea | 0:df1c8f2961a1 | 57 | } |
| fblanc | 1:0dbbb4802508 | 58 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 59 | if (send_ack) data.output(); // if ack needed then drive data low |
| roselea | 0:df1c8f2961a1 | 60 | sclk=1; //clk #9 for ack |
| fblanc | 1:0dbbb4802508 | 61 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 62 | sclk=0; |
| roselea | 0:df1c8f2961a1 | 63 | data.input(); //release DATA-line |
| roselea | 0:df1c8f2961a1 | 64 | return val; |
| roselea | 0:df1c8f2961a1 | 65 | } |
| roselea | 0:df1c8f2961a1 | 66 | |
| roselea | 0:df1c8f2961a1 | 67 | void SHT::trans_start(void) |
| roselea | 0:df1c8f2961a1 | 68 | //---------------------------------------------------------------------------------- |
| roselea | 0:df1c8f2961a1 | 69 | // generates a transmission start |
| roselea | 0:df1c8f2961a1 | 70 | // _____ ________ |
| roselea | 0:df1c8f2961a1 | 71 | // DATA: |_______| |
| roselea | 0:df1c8f2961a1 | 72 | // ___ ___ |
| roselea | 0:df1c8f2961a1 | 73 | // SCK : ___| |___| |______ |
| roselea | 0:df1c8f2961a1 | 74 | { |
| roselea | 0:df1c8f2961a1 | 75 | data.input(); |
| roselea | 0:df1c8f2961a1 | 76 | sclk=0; //Initial state |
| fblanc | 1:0dbbb4802508 | 77 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 78 | sclk=1; |
| fblanc | 1:0dbbb4802508 | 79 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 80 | data.output(); // data low |
| fblanc | 1:0dbbb4802508 | 81 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 82 | sclk=0; |
| fblanc | 1:0dbbb4802508 | 83 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 84 | sclk=1; |
| fblanc | 1:0dbbb4802508 | 85 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 86 | data.input(); // allow data to high |
| fblanc | 1:0dbbb4802508 | 87 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 88 | sclk=0; |
| fblanc | 1:0dbbb4802508 | 89 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 90 | } |
| roselea | 0:df1c8f2961a1 | 91 | |
| roselea | 0:df1c8f2961a1 | 92 | void SHT::connection_reset(void) |
| roselea | 0:df1c8f2961a1 | 93 | //---------------------------------------------------------------------------------- |
| roselea | 0:df1c8f2961a1 | 94 | // communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart |
| roselea | 0:df1c8f2961a1 | 95 | // _____________________________________________________ ________ |
| roselea | 0:df1c8f2961a1 | 96 | // DATA: |_______| |
| roselea | 0:df1c8f2961a1 | 97 | // _ _ _ _ _ _ _ _ _ ___ ___ |
| roselea | 0:df1c8f2961a1 | 98 | // SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |______ |
| roselea | 0:df1c8f2961a1 | 99 | { |
| roselea | 0:df1c8f2961a1 | 100 | int i; |
| roselea | 0:df1c8f2961a1 | 101 | data.input(); // allow data high |
| roselea | 0:df1c8f2961a1 | 102 | sclk=0; // and clk low |
| roselea | 0:df1c8f2961a1 | 103 | for (i=0;i<9;i++) { // 9 SCK cycles |
| fblanc | 1:0dbbb4802508 | 104 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 105 | sclk=1; |
| fblanc | 1:0dbbb4802508 | 106 | wait_us(MICROSECONDE); |
| roselea | 0:df1c8f2961a1 | 107 | sclk=0; |
| roselea | 0:df1c8f2961a1 | 108 | } |
| roselea | 0:df1c8f2961a1 | 109 | } |
| fblanc | 1:0dbbb4802508 | 110 | |
| roselea | 0:df1c8f2961a1 | 111 | char SHT::soft_reset(void) |
| roselea | 0:df1c8f2961a1 | 112 | //---------------------------------------------------------------------------------- |
| roselea | 0:df1c8f2961a1 | 113 | // resets the sensor by a softreset |
| roselea | 0:df1c8f2961a1 | 114 | { |
| roselea | 0:df1c8f2961a1 | 115 | char error=0; |
| roselea | 0:df1c8f2961a1 | 116 | SHT::connection_reset(); //reset communication |
| roselea | 0:df1c8f2961a1 | 117 | trans_start(); |
| roselea | 0:df1c8f2961a1 | 118 | error+=write_byte(com_reset); //send RESET-command to sensor |
| roselea | 0:df1c8f2961a1 | 119 | return error; //error=1 in case of no response form the sensor |
| roselea | 0:df1c8f2961a1 | 120 | } |
| roselea | 0:df1c8f2961a1 | 121 | |
| roselea | 0:df1c8f2961a1 | 122 | char SHT::read_status(byte &value) |
| roselea | 0:df1c8f2961a1 | 123 | //---------------------------------------------------------------------------------- |
| roselea | 0:df1c8f2961a1 | 124 | // reads the status register with checksum (8-bit) |
| roselea | 0:df1c8f2961a1 | 125 | { |
| roselea | 0:df1c8f2961a1 | 126 | //byte checksum; |
| roselea | 0:df1c8f2961a1 | 127 | |
| roselea | 0:df1c8f2961a1 | 128 | char error=0; |
| roselea | 0:df1c8f2961a1 | 129 | trans_start(); //transmission start |
| roselea | 0:df1c8f2961a1 | 130 | error=write_byte(com_read_status_reg); //send command to sensor |
| roselea | 0:df1c8f2961a1 | 131 | value=read_byte(send_ack); //read status register (8-bit) |
| roselea | 0:df1c8f2961a1 | 132 | /* checksum= */ |
| roselea | 0:df1c8f2961a1 | 133 | (void)read_byte(no_ack); //read checksum (8-bit) |
| roselea | 0:df1c8f2961a1 | 134 | // check the checksum ?? |
| roselea | 0:df1c8f2961a1 | 135 | return error; //error=1 in case of no response form the sensor |
| roselea | 0:df1c8f2961a1 | 136 | } |
| roselea | 0:df1c8f2961a1 | 137 | |
| roselea | 0:df1c8f2961a1 | 138 | char SHT::write_status(byte value) |
| roselea | 0:df1c8f2961a1 | 139 | //---------------------------------------------------------------------------------- |
| roselea | 0:df1c8f2961a1 | 140 | // writes the status register (8-bit) |
| roselea | 0:df1c8f2961a1 | 141 | { |
| roselea | 0:df1c8f2961a1 | 142 | char error=0; |
| roselea | 0:df1c8f2961a1 | 143 | trans_start(); //transmission start |
| roselea | 0:df1c8f2961a1 | 144 | error+=write_byte(com_write_status_reg); //send command to sensor |
| roselea | 0:df1c8f2961a1 | 145 | error+=write_byte(value); //send value of status register |
| roselea | 0:df1c8f2961a1 | 146 | return error; //error>=1 in case of no response form the sensor |
| roselea | 0:df1c8f2961a1 | 147 | } |
| roselea | 0:df1c8f2961a1 | 148 | |
| roselea | 0:df1c8f2961a1 | 149 | char SHT::measure(int &value, byte command) |
| roselea | 0:df1c8f2961a1 | 150 | //---------------------------------------------------------------------------------- |
| roselea | 0:df1c8f2961a1 | 151 | // makes a measurement (humidity/temperature) with checksum |
| roselea | 0:df1c8f2961a1 | 152 | { |
| roselea | 0:df1c8f2961a1 | 153 | unsigned int i; |
| roselea | 0:df1c8f2961a1 | 154 | byte msb; |
| roselea | 0:df1c8f2961a1 | 155 | // byte checksum; |
| roselea | 0:df1c8f2961a1 | 156 | |
| roselea | 0:df1c8f2961a1 | 157 | trans_start(); //transmission start |
| roselea | 0:df1c8f2961a1 | 158 | if (write_byte(command)) return 1; // if command fails return |
| roselea | 0:df1c8f2961a1 | 159 | |
| roselea | 0:df1c8f2961a1 | 160 | for (i=10000;i;i--) { //wait until sensor has finished the measurement |
| roselea | 0:df1c8f2961a1 | 161 | wait_us(100); |
| roselea | 0:df1c8f2961a1 | 162 | if (data==0) break; |
| roselea | 0:df1c8f2961a1 | 163 | } |
| roselea | 0:df1c8f2961a1 | 164 | if (data) return 1; // or timeout (~1 sec.) is reached !! |
| roselea | 0:df1c8f2961a1 | 165 | msb = read_byte(send_ack); //read the first byte (MSB) |
| roselea | 0:df1c8f2961a1 | 166 | value = msb*256 + read_byte(send_ack); //read the second byte (LSB) |
| roselea | 0:df1c8f2961a1 | 167 | /* checksum= */ |
| roselea | 0:df1c8f2961a1 | 168 | (void)read_byte(no_ack); //read checksum |
| roselea | 0:df1c8f2961a1 | 169 | return 0; |
| roselea | 0:df1c8f2961a1 | 170 | } |
| roselea | 0:df1c8f2961a1 | 171 | |
| roselea | 0:df1c8f2961a1 | 172 | void SHT::calculate() |
| roselea | 0:df1c8f2961a1 | 173 | //---------------------------------------------------------------------------------------- |
| fblanc | 1:0dbbb4802508 | 174 | // calculates temperature [�C] and humidity [%RH] |
| roselea | 0:df1c8f2961a1 | 175 | // input : hum [Ticks] (12 bit) |
| roselea | 0:df1c8f2961a1 | 176 | // temp [Ticks] (14 bit) |
| roselea | 0:df1c8f2961a1 | 177 | // output: humidity [%RH] |
| fblanc | 1:0dbbb4802508 | 178 | // temperature [�C] |
| roselea | 0:df1c8f2961a1 | 179 | { |
| fblanc | 1:0dbbb4802508 | 180 | //Optimized V4 humidity conversion coefficients |
| fblanc | 1:0dbbb4802508 | 181 | const float C1=-2.0468; // for 12 Bit |
| fblanc | 1:0dbbb4802508 | 182 | const float C2=0.0367; // for 12 Bit |
| fblanc | 1:0dbbb4802508 | 183 | const float C3=-1.5955E-6; // for 12 Bit |
| fblanc | 1:0dbbb4802508 | 184 | const float T1=0.01; // for 12 |
| fblanc | 1:0dbbb4802508 | 185 | const float T2=0.00008; // for 12 Bit |
| fblanc | 1:0dbbb4802508 | 186 | const float D1= -40.1; //for °C 5V |
| fblanc | 1:0dbbb4802508 | 187 | const float D2= 0.01 ; //for °C for 14 |
| roselea | 0:df1c8f2961a1 | 188 | float rh; // rh: Humidity [Ticks] 12 Bit |
| roselea | 0:df1c8f2961a1 | 189 | float t; // t: Temperature [Ticks] 14 Bit |
| fblanc | 1:0dbbb4802508 | 190 | float rh_lin; // rh_lin: Humidity linear |
| roselea | 0:df1c8f2961a1 | 191 | if (accuracy==SHT_low) { |
| roselea | 0:df1c8f2961a1 | 192 | rh=hum*16; // rescale to high accuracy values - 8 to 12 bits |
| roselea | 0:df1c8f2961a1 | 193 | t=temp*4; // and 12 to 14 bits |
| roselea | 0:df1c8f2961a1 | 194 | } else { |
| roselea | 0:df1c8f2961a1 | 195 | rh=hum; |
| roselea | 0:df1c8f2961a1 | 196 | t=temp; |
| roselea | 0:df1c8f2961a1 | 197 | } |
| roselea | 0:df1c8f2961a1 | 198 | |
| fblanc | 1:0dbbb4802508 | 199 | temperature=D1 + D2*t ; //calc. temperature from ticks to [�C] |
| fblanc | 1:0dbbb4802508 | 200 | rh_lin=C3*rh*rh + C2*rh + C1; //calc. humidity from ticks to [%RH] |
| fblanc | 1:0dbbb4802508 | 201 | humidity =(temperature-25)*(T1+T2*rh)+rh_lin; //calc. temperature compensated humidity [%RH] (ignore as never >0.25%) |
| roselea | 0:df1c8f2961a1 | 202 | if (humidity>100)humidity=100; //cut if the value is outside of |
| roselea | 0:df1c8f2961a1 | 203 | if (humidity<0.1)humidity=0.1; //the physical possible range |
| roselea | 0:df1c8f2961a1 | 204 | } |
| roselea | 0:df1c8f2961a1 | 205 | |
| roselea | 0:df1c8f2961a1 | 206 | float SHT::get_temperature() { // get the most recent temp reading |
| roselea | 0:df1c8f2961a1 | 207 | return temperature; |
| roselea | 0:df1c8f2961a1 | 208 | } |
| roselea | 0:df1c8f2961a1 | 209 | |
| roselea | 0:df1c8f2961a1 | 210 | float SHT::get_humidity() { // get the most recent humidity reading |
| roselea | 0:df1c8f2961a1 | 211 | return humidity; |
| roselea | 0:df1c8f2961a1 | 212 | } |
| roselea | 0:df1c8f2961a1 | 213 | |
| roselea | 0:df1c8f2961a1 | 214 | float SHT::get_dewpoint() { // get the most recent dewpoint value |
| roselea | 0:df1c8f2961a1 | 215 | return dewpoint; |
| roselea | 0:df1c8f2961a1 | 216 | } |
| roselea | 0:df1c8f2961a1 | 217 | |
| fblanc | 1:0dbbb4802508 | 218 | int SHT::update(SHT_acc acc) { // update stored values from sensor |
| roselea | 0:df1c8f2961a1 | 219 | int error=0; |
| fblanc | 1:0dbbb4802508 | 220 | soft_reset(); |
| fblanc | 1:0dbbb4802508 | 221 | //connection_reset(); |
| roselea | 0:df1c8f2961a1 | 222 | if (acc!=accuracy) { |
| roselea | 0:df1c8f2961a1 | 223 | accuracy=acc; |
| roselea | 0:df1c8f2961a1 | 224 | error+=write_status((acc==SHT_low)?0x01:0x00); //set the status reg to high or low accuarcy |
| roselea | 0:df1c8f2961a1 | 225 | } |
| roselea | 0:df1c8f2961a1 | 226 | error+=measure(temp,com_measure_temp); |
| roselea | 0:df1c8f2961a1 | 227 | error+=measure(hum,com_measure_humid); |
| roselea | 0:df1c8f2961a1 | 228 | if (!error) calculate(); |
| fblanc | 1:0dbbb4802508 | 229 | return error; |
| roselea | 0:df1c8f2961a1 | 230 | } |
