Code example in One-Wire library for DS18b20 to display temperature less than zero

I have make an outdoor thermometer using the DS18b20. I used the one-wire library device code example for a single device and it has been working good. As the outdoor temperature has gone down this winter I have noticed a problem with the data the device code is sending. The temperature reading is good until it goes down past zero C. I have found some code on a different site that looks to address this problem, but it is code for the arduino. I am having a hard time rewriting the code so it will work with the existing library code.
You can see in the photo below the output I get when the temperature does down past zero. The MSB jumps to 255 and the LSB jumps to 255 just past zero c. As the temperature goes lower the LSB starts to decrease.
I am a newbie when it comes to coding and math was not a strong subject for me in school. If anyone could help me with the code change to the example I would very much appreciate it.
Bill

You need to “sign extend” this to a 32 bit value. The value is two’s complement encoded as a 16 bit signed value when you read it from the chip.

The easy way to do this in squirrel, as integers are signed, is to shift the value up towards the top of the 32 bit signed integer, then back down again. This will fill in “FFFF” at the top, and make everything magically work.

ie:

local raw = (tempMSB << 8) + tempLSB; local temperature = ((raw << 16) >> 16)*0.0625; server.log("Temperature is "+temperature+"degC");

So integers are signed in squirrel, didn’t know that. So much to learn. Thanks

I ended up with below for my device code. It works.

`// Thermometer electric imp - DS18B20

function onewireReset() {
// Configure UART for 1-Wire RESET timing
ow.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS);
ow.write(0xF0);
ow.flush();
local read = ow.read();
if (read == -1) {
// No UART data at all
server.log(“No circuit connected to UART.”);
return false;
} else if (read == 0xF0) {
// UART RX will read TX if there’s no device connected
server.log(“No 1-Wire devices are present.”);
return false;
} else {
// Switch UART to 1-Wire data speed timing
ow.configure(115200, 8, PARITY_NONE, 1, NO_CTSRTS);
return true;
}
}

function onewireWriteByte(byte) {
for (local i = 0 ; i < 8 ; i++, byte = byte >> 1) {
// Run through the bits in the byte, extracting the
// LSB (bit 0) and sending it to the bus
onewireBit(byte & 0x01);
}
}

function onewireReadByte() {
local byte = 0;
for (local i = 0 ; i < 8 ; i++) {
// Build up byte bit by bit, LSB first
byte = (byte >> 1) + 0x80 * onewireBit(1);
}
return byte;
}

function onewireBit(bit) {
bit = bit ? 0xFF : 0x00;
ow.write(bit);
ow.flush();
local returnVal = ow.read() == 0xFF ? 1 : 0;
return returnVal;
}

// Wake up every 15 minutes and write to the server

function awakeAndGetTemp() {
local tempLSB = 0;
local tempMSB = 0;

// Run loop again in 15 minutes
imp.wakeup(900.0, awakeAndGetTemp);

if (onewireReset()) {
    onewireWriteByte(0xCC);
    onewireWriteByte(0x44);

    // Wait for at least 750ms for data to be collated
    imp.sleep(0.8);

    // Get the data
    onewireReset();
    onewireWriteByte(0xCC);
    onewireWriteByte(0xBE);

    tempLSB = onewireReadByte();
    tempMSB = onewireReadByte();

    // Reset bus to stop sensor sending unwanted data
    onewireReset();

    // Log the Celsius temperature
    local raw = (tempMSB << 8) + tempLSB;
    local temperature = ((raw << 16) >> 16)*0.0625;
    local tempFahrenheit = (temperature * 9 / 5 + 32)
    server.log(format("Temperature is : %3.2f Degrees F "tempFahrenheit));
}

}

// PROGRAM STARTS HERE

ow <- hardware.uart12;
awakeAndGetTemp();

`

1 Like

Glad it’s working, and thanks for posting your code - I’m sure it’ll help others!

1 Like

And I’ve updated the sample code in the 1-Wire Developer Guide

It made me feel good that I was able to write some code again. The last time was when I was in a college class. IBM System/360, I may have a stack of punch cards up in the attic. :slight_smile: