frederic blanc
/
SHTxx2013
SHT V4 5V UART
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 | } |