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

Committer:
okini3939
Date:
Fri Jun 03 15:38:22 2011 +0000
Revision:
19:69b77f9e0446
Parent:
0:4265d973a98f

        

Who changed what in which revision?

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