Although this code is highly intertwined with the other aspects of my project, let me dig up excerpts of the core functionality. BTW, this works as it is but may not work reliably if you poll the sensor too quickly (>10x a second).
I put this together from parallax' sample code, datasheet, and oscilliscope.
In the end, I just had to add a small delay before the "Wait" function, as the SHT11 / pullup resistor has some delay going high.
// SHT11 interface code
// copyleft 2k7, hacked together by Derek Yerger
int adcCount;
int shtData = 2;
int shtClk = 3;
const int shtTemp = 3;
const int shtHumi = 5;
const int shtStatW = 6;
const int shtStatR = 7;
const int shtReset = 30;
int ioByte;
int ackBit;
long unsigned retVal;
uint8_t bitmask;
void SHT_Write_Byte(void) {
pinMode(shtData, OUTPUT);
shiftOut(shtData, shtClk, MSBFIRST, ioByte);
pinMode(shtData, INPUT);
digitalWrite(shtData, LOW);
digitalWrite(shtClk, LOW);
digitalWrite(shtClk, HIGH);
ackBit = digitalRead(shtData);
digitalWrite(shtClk, LOW);
}
int shiftIn() {
int cwt;
cwt=0;
bitmask=128;
while (bitmask >= 1) {
digitalWrite(shtClk, HIGH);
cwt = cwt + bitmask * digitalRead(shtData);
digitalWrite(shtClk, LOW);
bitmask=bitmask/2;
}
return(cwt);
}
void SHT_Read_Byte(void) {
ioByte = shiftIn();
digitalWrite(shtData, ackBit);
pinMode(shtData, OUTPUT);
digitalWrite(shtClk, HIGH);
digitalWrite(shtClk, LOW);
pinMode(shtData, INPUT);
digitalWrite(shtData, LOW);
}
void SHT_Connection_Reset(void) {
shiftOut(shtData, shtClk, LSBFIRST, 255);
shiftOut(shtData, shtClk, LSBFIRST, 255);
}
void SHT_Soft_Reset(void) {
SHT_Connection_Reset();
ioByte = shtReset;
ackBit = 1;
SHT_Write_Byte();
delay(15);
}
void SHT_Wait(void) {
delay(5); // this is where I ran into trouble. Ok now.
dly = 0;
while (dly < 400) {
if (digitalRead(shtData) == 0) dly=2600;
delay(1);
dly=dly+1;
}
}
void SHT_Start(void) {
digitalWrite(shtData, HIGH);
pinMode(shtData, OUTPUT);
digitalWrite(shtClk, HIGH);
digitalWrite(shtData, LOW);
digitalWrite(shtClk, LOW);
digitalWrite(shtClk, HIGH);
digitalWrite(shtData, HIGH);
digitalWrite(shtClk, LOW);
}
void SHT_Measure(int vSvc) {
SHT_Soft_Reset();
SHT_Start();
ioByte = vSvc;
// digitalWrite(dbp, HIGH); // this is for triggering a scope
// digitalWrite(dbp, LOW);
SHT_Write_Byte();
SHT_Wait();
ackBit = 0;
// digitalWrite(dbp2, HIGH); // again, for triggering a sweep
// digitalWrite(dbp2, LOW); // this time, right before reading data
SHT_Read_Byte();
int msby;
msby = ioByte;
ackBit = 1;
SHT_Read_Byte();
retVal = msby;
retVal = retVal * 0x100;
retVal=retVal+ioByte;
if (retVal<=0) retVal = 1;
}
int SHT_Get_Status(void) {
SHT_Soft_Reset();
SHT_Start();
ioByte = shtStatR;
SHT_Write_Byte();
SHT_Wait();
ackBit = 1;
SHT_Read_Byte();
return(ioByte);
}
There are separate routines for measurement and status due to differing amounts of data returned.
For completeness' sake, heres a routine to set the status register:
int SHT_WriteStat(void) {
SHT_Soft_Reset();
SHT_Start();
ioByte = shtStatW;
SHT_Write_Byte();
int tmp;
ioByte = 4; // turn heater on. 0 would be "off"
SHT_Write_Byte();
ackBit = 1;
SHT_Read_Byte();
return(ioByte);
}
Maybe some day I'll library-ize this, but I've demonstrated how inept I am at seeing these through, as I still haven't completed the bit under the playground for Dallas One-Wire stuff.
Good luck! If you use this and improve it, please share your results with us. That code above was ~3 days or total 8 hours of "wtf?" until I figured out the timing.
Once the project this is part of is completed, I'll certainly volunteer to do a write-up in the playground. Till then... hope this helps.
Derek