[PHP]
/ sensirion SHT11 humidity/temperature sensor (parallax kit)
// Todo
// heater on heater off
// clean up
// check softreset command
// check error messages
#include <avr/pgmspace.h>
//int reserved = B0000XXXX
int temperatureCommand = B00000011; // command used to read temperature
int humidityCommand = B00000101; // command used to read humidity
int readStatus = B00000111;
int writeStatus = B00000110;
int softReset = B00011110; // soft reset command wait 11 ms
int clockPin = 4; // pin used for clock
int dataPin = 5; // pin used for data
int ack; // track acknowledgment for errors
int val;
int val2;
int c;
int i = 0;
int h = 0;
int status;
float temperature;
float humidity;
float dewpoint;
boolean continuous = false;
float logEx;
const unsigned char crcTab[256] PROGMEM = {
0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219, 234, 125, 76, 31, 46, 67,
114, 33, 16, 135, 182, 229, 212, 250, 203, 152, 169, 62, 15, 92, 109, 134,
183, 228, 213, 66, 115, 32, 17, 63, 14, 93, 108, 251, 202, 153, 168, 197,
244, 167, 150, 1, 48, 99, 82, 124, 77, 30, 47, 184, 137, 218, 235, 61, 12,
95, 110, 249, 200, 155, 170, 132, 181, 230, 215, 64, 113, 34, 19, 126, 79,
28, 45, 186, 139, 216, 233, 199, 246, 165, 148, 3, 50, 97, 80, 187, 138,
217, 232, 127, 78, 29, 44, 2, 51, 96, 81, 198, 247, 164, 149, 248, 201, 154,
171, 60, 13, 94, 111, 65, 112, 35, 18, 133, 180, 231, 214, 122, 75, 24, 41,
190, 143, 220, 237, 195, 242, 161, 144, 7, 54, 101, 84, 57, 8, 91, 106, 253,
204, 159, 174, 128, 177, 226, 211, 68, 117, 38, 23, 252, 205, 158, 175, 56,
9, 90, 107, 69, 116, 39, 22, 129, 176, 227, 210, 191, 142, 221, 236, 123,
74, 25, 40, 6, 55, 100, 85, 194, 243, 160, 145, 71, 118, 37, 20, 131, 178,
225, 208, 254, 207, 156, 173, 58, 11, 88, 105, 4, 53, 102, 87, 192, 241,
162, 147, 189, 140, 223, 238, 121, 72, 27, 42, 193, 240, 163, 146, 5, 52,
103, 86, 120, 73, 26, 43, 188, 141, 222, 239, 130, 179, 224, 209, 70, 119,
36, 21, 59, 10, 89, 104, 255, 206, 157, 172
};
uint8_t crc8 = 0; // This is innitial value of crc. Should read status register and reverse ie status s7s6s5s4s3s2s1s0 --> startvalue s0s1s2s3s4s5s6s7
uint8_t check = B00000101; // This is innitial Byte A2A1A0C4C3C2C1C0 00000101 ie command 00101 = measure humidity
// generate a transmission reset
void resetSHT () {
pinMode (dataPin,OUTPUT);
pinMode (clockPin,OUTPUT);
digitalWrite(dataPin,HIGH);
digitalWrite(clockPin,LOW);
for (i=0;i<9;i++) {
digitalWrite(clockPin,HIGH);
digitalWrite(clockPin,LOW);
}
}
void setup() {
Serial.begin(9600); // open serial at 9600 bps
Serial.print("Resetting SHT11 : ");
Serial.print("\n");
continuous = false;
resetSHT();
}
void loop() {
char cmd;
while (Serial.available() >0) {
cmd=Serial.read();
switch(cmd){ // still to add softreset & read status register
case 't': case 'T': { // toggle continuous print
continuous ^=1;
break; }
case 'c': case 'C': {
SHTHeaterOff(); Serial.print (" Heater Off "); Serial.print ("\n");
break; }
case 'h': case 'H': {
SHTHeaterOn(); Serial.print(" Heater On"); Serial.print ("\n");
break; }
case 'r': case 'R': {
SHTgetTemp(); SHTgetHum(); Serial.print ("\n");
break; }
default: {
Serial.println("unrecognised command.\n");
}
}
}
if (continuous) { SHTgetTemp (); SHTgetHum (); Serial.print("\n"); delay (3000);}
}
// commands for reading/sending data to a SHTx sensor
int shiftIn(int dataPin, int clockPin, int numBits) {
int ret = 0;
for (int i=0; i<numBits; ++i) {
digitalWrite(clockPin, HIGH);
//delay(10); not needed
ret = ret*2 + digitalRead(dataPin);
digitalWrite(clockPin, LOW);
}
return(ret);
}
// send a command to the SHTx sensor
void sendCommandSHT(int command, int dataPin, int clockPin) {
int ack;
// transmission start
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
digitalWrite(dataPin, HIGH);
digitalWrite(clockPin, HIGH);
digitalWrite(dataPin, LOW);
digitalWrite(clockPin, LOW);
digitalWrite(clockPin, HIGH);
digitalWrite(dataPin, HIGH);
digitalWrite(clockPin, LOW);
// shift out the command (the 3 MSB are address and must be 000, the last 5 bits are the command)
shiftOut(dataPin, clockPin, MSBFIRST, command);
// verify we get the right ACK
pinMode(dataPin, INPUT); // prepare to read ack bit
digitalWrite(dataPin,HIGH); // engage pull-up resistors
digitalWrite(clockPin, HIGH); // send 9th clock bit for ack
ack = digitalRead(dataPin); // expect pull down by SHT11
if (ack != LOW)
Serial.println("ACK error 0");
digitalWrite(clockPin, LOW);
ack = digitalRead(dataPin);
if (ack != HIGH)
Serial.println("ACK error 1");
}
// wait for the SHTx answer
void waitForResultSHT(int dataPin) {
int ack;
pinMode(dataPin, INPUT);
for(int i=0; i<100; ++i) {
delay(10);
ack = digitalRead(dataPin);
if (ack == LOW)
break;
}
if (ack == HIGH)
Serial.println("ACK error 2 SHT11 Timeout ERROR");
}
// get data from the SHTx sensor
void getData16SHT(int dataPin, int clockPin) {
// get the MSB (most significant bits)
pinMode(dataPin, INPUT);
pinMode(clockPin, OUTPUT);
val = shiftIn(dataPin, clockPin, 8);
val *= 256; // this is equivalent to val << 8;
// send the required ACK
pinMode(dataPin, OUTPUT);
digitalWrite(dataPin, HIGH);
digitalWrite(dataPin, LOW);
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
// get the LSB (less significant bits)
pinMode(dataPin, INPUT);
val |= shiftIn(dataPin, clockPin, 8);
// send the required ACK
pinMode(dataPin, OUTPUT);
digitalWrite(dataPin, HIGH);
digitalWrite(dataPin, LOW);
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
// get 8 bits crc data from SHT11
void getcrc(int dataPin, int clockPin)
{
// get the next 8 bits
pinMode(dataPin, INPUT);
val2 |= shiftIn(dataPin, clockPin, 8);
// reverse bits in byte input val2 output h
for(h = i = 0; i < 8; i++) {
h = (h << 1) + (val2 & 1);
val2 >>= 1;
}
}
// finish routine
void finish (int dataPin, int clockPin)
{
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
digitalWrite(dataPin, HIGH);
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
void serialPrintFloat (float f) {
Serial.print((int)f);
Serial.print(".");
int temp =(f-(int)f) *100;
if (abs(temp)<10) Serial.print("0");
Serial.print(abs(temp));
}
void SHTgetTemp() {
// read the temperature and convert it to centigrades
sendCommandSHT(temperatureCommand, dataPin, clockPin);
waitForResultSHT(dataPin);
getData16SHT(dataPin, clockPin);
getcrc(dataPin,clockPin);
finish(dataPin,clockPin);
temperature = (float)val * 0.01 - 40.1; //
Serial.print("SHT11 Temperature: ");
serialPrintFloat(temperature);
Serial.print(" ");
Serial.print(176,BYTE);// degrees sign
Serial.print("C ");
crc8 = B00000000;//innitial byte comes from status register
crc8 = pgm_read_byte(crcTab + ((temperatureCommand) ^ crc8));
crc8 = pgm_read_byte(crcTab + ((val>>8) ^ crc8));
crc8 = pgm_read_byte(crcTab + ((val&0xFF) ^ crc8));
if (crc8!=h) Serial.print("crc ERROR ");
}
void SHTgetHum() {
// read the humidity
sendCommandSHT(humidityCommand, dataPin, clockPin);
waitForResultSHT(dataPin);
getData16SHT(dataPin, clockPin);
getcrc (dataPin,clockPin);
finish (dataPin,clockPin);
humidity = -2.0468 + 0.0367 * val + -0.0000015955 * val * val; // optimised V4 sensor table
humidity = (temperature -25) * (0.01 + 0.00008 * val) + humidity; // temperature correction
Serial.print("SHT11 Humidity: ");
serialPrintFloat(humidity);
Serial.print(" %RH ");
crc8 = B00000000;//innitial byte comes from status register
crc8 = pgm_read_byte(crcTab + ((humidityCommand) ^ crc8));
crc8 = pgm_read_byte(crcTab + ((val>>8) ^ crc8));
crc8 = pgm_read_byte(crcTab + ((val&0xFF) ^ crc8));
if (crc8!=h) Serial.print("crc ERROR ");
// dewpoint calculation
logEx = (0.66077 + 7.5 * temperature / (237.3 + temperature) + log10(humidity) - 2);
dewpoint = (logEx - 0.66077)*237.3/(0.66077+7.5-logEx);
Serial.print("Dewpoint: ");
serialPrintFloat(dewpoint);
Serial.print(176,BYTE);// degrees sign
Serial.print("C ");
}
void SHTHeaterOff() {
// Switch heater off
// transmission start
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
digitalWrite(dataPin, HIGH);
digitalWrite(clockPin, HIGH);
digitalWrite(dataPin, LOW);
digitalWrite(clockPin, LOW);
digitalWrite(clockPin, HIGH);
digitalWrite(dataPin, HIGH);
digitalWrite(clockPin, LOW);
// shift out the command (the 3 MSB are address and must be 000, the last 5 bits are the command)
shiftOut(dataPin, clockPin, MSBFIRST, readStatus);
getData16SHT(dataPin, clockPin);
finish (dataPin,clockPin);
Serial.print ((val/256),HEX);
}
void SHTHeaterOn() {
// Switch heater on
// transmission start
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
digitalWrite(dataPin, HIGH);
digitalWrite(clockPin, HIGH);
digitalWrite(dataPin, LOW);
digitalWrite(clockPin, LOW);
digitalWrite(clockPin, HIGH);
digitalWrite(dataPin, HIGH);
digitalWrite(clockPin, LOW);
// shift out the command (the 3 MSB are address and must be 000, the last 5 bits are the command)
shiftOut(dataPin, clockPin, MSBFIRST, readStatus);
// send ack
// shiftout(dataPin,clockPin, MSBFIRST, status);
getData16SHT(dataPin, clockPin);
finish (dataPin,clockPin);
Serial.print ((val/256),HEX);
}
[/PHP]