SHT V4 5V UART

Dependencies:   mbed

Fork of SHT_v1 by Stephen McGarry

Committer:
roselea
Date:
Sun Jan 24 22:00:35 2010 +0000
Revision:
0:df1c8f2961a1
Child:
1:0dbbb4802508

        

Who changed what in which revision?

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