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