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