I'm using the DS2438 library from Guilherme Barros at Google Code Archive - Long-term storage for Google Code Project Hosting. along with the 1-wire library. I am reading temp and humidity using the example that came with the DS2438 library. Everything is fine until the temp drops below 32.00 degrees F. At that point both temp and humidity jump to over 200 degrees and 150% rh. Is anyone using this library and have you had problems. BTW, I have tried 2 different 1-wire sensor boards with the same problem. As soon as the temp rises to 32 again everything is good.
32.00 degrees F is zero Celsius, so maybe there is an overflow or divide by zero or such condition. zero's are nasty numbers in programming as they are the lowest unsigned number. Strange things happened before.
Have to dive into the lib. may take a while .....
update 1: checking the datasheet http://pdfserv.maxim-ic.com/en/ds/DS2438.pdf
DS2438 is a smart Battery Monitor, with a 13 bit temperature sensor, 8 bit before digital point and 5 thereafter, giving a precision of 1/32 degree. (nice IC). Temperature is in Celsius. So it is not a restriction of the sensor, it must be in the lib.
Q: Can you share your code in which it happens?
update 2: Just looking at the lib shows that readHum() uses readTempC() so if the latter is wrong the first one will be too.
update 3: readTempC()
float ds2438::readTempC()
{
//override for now, [glow][b]plsfixkthx[/b][/glow]
_parasite = 1;
//request temp conversion
_wire->reset();
_wire->select(_deviceAddress);
_wire->write(CONVERTT, _parasite);
delay(20);
//copy data from eeprom to scratchpad & read scratchpad
ScratchPad _scratchPad;
_readMem(_scratchPad);
//return tempC (ignore 3 lsb as they are always 0);
int16_t rawTemp = ( ((int16_t)_scratchPad[TEMP_MSB]) << 5) | (_scratchPad[TEMP_LSB] >> 3);
return (float)rawTemp * 0.03125;
}
Could the highlighted "Please Fix This" related to your problem? Do you use parasite power?
PARASITE POWER
The block diagram (Figure 1) shows the parasite-powered circuitry. This circuitry “steals” power whenever the DQ pin is high. DQ will provide sufficient power as long as the specified timing and voltage requirements are met (see the section titled “1-Wire Bus System”). The advantage of parasite power is that the ROM may be read in absence of normal power, i.e., if the battery pack is completely
discharged.
Hi robtillaart
First, thanks for looking at this.
Look at the example code with the library. I ran that last night and as soon as the outdoor temp went below 32f or 0c it gave me the strange results. Like you I suspect the calculation used to convert the temperature is at fault but I'm not well versed in C or library building to figure it out.
Convert T [44h]
This command begins a temperature conversion. No further data is required. The temperature conversion will be performed, setting the TB flag in the Status/Configuration register to a “1” during conversion. When the temperature conversion is done, the TB flag will clear to a “0”. If the bus master issues read time slots following this command, the DS2438 will output “0” on the bus as long as it is busy making a temperature conversion; it will return a “1” when the temperature conversion is complete.
When I look at the code of the library it just does a delay(20); after the call for convert. As I am familiar with the DS18B20 temp sensor, that takes 750 msec for 12 bit, so 13 bit may even take longer (OK Assumption with big A) but it seems to me that the library just waits to short for conversion.
Could you please try to replace readTempC in the library with this one. It waits until the TB flag (Temperature Busy) is cleared. Code is not compiled or tested
Rob
float ds2438::readTempC()
{
//override for now, plsfixkthx
_parasite = 1;
//request temp conversion
_wire->reset();
_wire->select(_deviceAddress);
_wire->write(CONVERTT, _parasite);
// delay(20);
ScratchPad _scratchPad;
// wait until TB register clears, see page 15/29 datasheet
// iso delay(20);
boolean ready = false;
while (!ready)
{
//copy data from eeprom to scratchpad & read scratchpad
_readMem(_scratchPad);
ready = ( _scratchPad[STATUS] & 0x10) == 0x00;
delay(10); // wait before reread of the scratchpad
}
// TB is cleared so conversion is ready
//return tempC (ignore 3 lsb as they are always 0);
int16_t rawTemp = ( ((int16_t)_scratchPad[TEMP_MSB]) << 5) | (_scratchPad[TEMP_LSB] >> 3);
return (float)rawTemp * 0.03125;
}
If you just want to tweak the delay I would propose to start with 2000 millisec iso 750. that's quite long but if the IC behaves similar to the DS18B20 2000 is a reasonable value. The DS18B20 doubles the delay time for every extra bit ( it can be configured from 9-12 bits with a max of 750 msec)
If 2000 works you might go down in steps of 100 msec until it fails.
I had a similar problem on the TC74 temp sensors, it overflows back to 255 when the temp drops below 0. Pretty simple to solve in code though as the max temp is 125C (I think) so anything above that is mapped to minus values in code.
Technically, I can imagine that with lower temperatures the ADC goes slower but never that much slower. So that's not the cause.
My current line of thought is that as long as the TB flag is not cleared the scratchpad reads an undefined value ... (based upon datasheet)
Found cause for the bug, please confirm as I have no sensor to test with.
The scratchpad is defined as array of unsigned int 8 (see ds2438.h)
typedef uint8_t ScratchPad[9];
in readTempC(); the temperature reading is done and two shifts are used to merge the value of the MSB and LSB register. As the value of MSB is an unsigned int, the value casting it to an int_16_t does not do a sign extension. Therefor as the value becomes (should be) negative, it is interpreted as 255 instead of -1.
float ds2438::readTempC()
{
//override for now, plsfixkthx
_parasite = 1;
//request temp conversion
_wire->reset();
_wire->select(_deviceAddress);
_wire->write(CONVERTT, _parasite);
delay(20);
//copy data from eeprom to scratchpad & read scratchpad
ScratchPad _scratchPad;
_readMem(_scratchPad);
//return tempC (ignore 3 lsb as they are always 0);
uint8_t x = _scratchPad[TEMP_MSB];
int rawTemp = (x & 0x80)?(-256+x): x; // uint8_t => int
float f = rawTemp + (_scratchPad[TEMP_LSB] >> 3) * 0.03125;
return f;
}
Rob
Note: Other solution could be the changing the type of the scratchpad to signed but I did not investigate the impact of that change to the rest of the DS2438 class.
Thanks Rob! Didn't mean for u to spend a lot of time on this but it is appreciated. Only one more simple question. What program do I use to edit this with? Notepad won't work. It adds stray chars. Get all kinds of errors.
Thanks,
Bill
BTW... I have several DS2438s. If you want a couple send me a personal message with you address.
It was fun to investigate, I hope the proposed changes work for you.
For coding libraries is use notepad++, it is lightweigth and does syntax highlighting, can open multiple files (tabs). It is not the greatest but very fast also for large logfiles (100.000++ lines) You can find it at http://notepad-plus-plus.org/
wrt the 2438's I appreciate the gesture but I think you have to pay more on postage than the costs of the sensors
@Bill
Could you confirm that the the first patch works?
Strange that the second patch, which stays more to the original code, doesn't work. My testcode with same datatypes did. Could you test a rewrite of the last patch as proposed below? I have moved the rightshift 3 to a division in the return statement, to be sure the signbit is kept...