DS18B20 error

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
greentree
Posts: 12
Joined: Wed Dec 16, 2015 3:16 am

DS18B20 error

Post by greentree » Wed Oct 26, 2016 4:35 pm

As far as I can tell there is an issue reading DS18B20 sensors with recent firmware, where the normal usage fails during the DS18X20.scan() call. That seems to be because the filter for DS18X20 types onewire devices rejects ROMs that it should accept (or else the ROMs are being read incorrectly). Removing this filter with

Code: Select all

class DS18X20:
    def __init__(self, onewire):
        self.ow = onewire
        self.buf = bytearray(9)

    def scan(self):
        return [rom for rom in self.ow.scan()]
        #return [rom for rom in self.ow.scan() if rom[0] == 0x10 or rom[0] == 0x28]
seems to execute without error and give sensible temperature readings, if only DS18X20 sensors are present.

Has anyone else run into this issue and come up with a more confidence-inspiring fix?

greentree
Posts: 12
Joined: Wed Dec 16, 2015 3:16 am

Re: DS18B20 error

Post by greentree » Wed Oct 26, 2016 4:43 pm

Some more specifics for an array of six DS18B20 sensors.

With DS18X20 from frozen bytecode:

Code: Select all

from machine import Pin
from onewire import OneWire
from time import sleep_ms
from ds18x20 import DS18X20

p12 = Pin(12, Pin.OUT)
p12.high()
p14 = Pin(14, Pin.OUT)
p14.low()
ow = OneWire(Pin(13))
print(ow.scan())
ds = DS18X20(ow)
print(ds)
roms = ds.scan()
ds.convert_temp()
sleep_ms(750)
for rom in roms:
    print(ds.read_temp(rom))
gives
[bytearray(b'(\xff\x80V\x06\x00\x00\x83'), bytearray(b'(\xa7eE\x06\x00\x00\xb4'), bytearray(b'(\xeb\x15V\x06\x00\x00a'), bytearray(b'(\x83\xb7E\x06\x00\x00\x03'), bytearray(b'(\x9e\xc8W\x06\x00\x00/'), bytearray(b'(\xcedV\x06\x00\x00\x9c')]
<DS18X20 object at 3fff12f0>
Traceback (most recent call last):
File "<stdin>", line 14, in <module>
File "ds18x20.py", line 14, in scan
File "ds18x20.py", line 1, in <listcomp>
TypeError: 'int' object is not an iterator
With the filter replaced, the same code gives
[bytearray(b'(\xff\x80V\x06\x00\x00\x83'), bytearray(b'(\xa7eE\x06\x00\x00\xb4'), bytearray(b'(\xeb\x15V\x06\x00\x00a'), bytearray(b'(\x83\xb7E\x06\x00\x00\x03'), bytearray(b'(\x9e\xc8W\x06\x00\x00/'), bytearray(b'(\xcedV\x06\x00\x00\x9c')]
<DS18X20 object at 3fff1380>
19.625
19.625
19.5625
19.5
19.625
19.625

Damien
Site Admin
Posts: 640
Joined: Mon Dec 09, 2013 5:02 pm

Re: DS18B20 error

Post by Damien » Thu Oct 27, 2016 5:15 am

Try recompiling mpy-cross and rebuilding the esp8266 firmware. There were some recent changes to the VM bytecodes which can lead to such a TypeError.

Miguel
Posts: 20
Joined: Fri Sep 09, 2016 7:53 am

Re: DS18B20 error

Post by Miguel » Thu Oct 27, 2016 10:56 am

Hello!

I have the same problem on Wipy except that modifying scan method doesn't help. Using Robert's firmware 1.8.4-16 with disabled multithreading helps:

https://github.com/robert-hh/Shared-Stu ... mcuimg.bin

Michal

User avatar
ernitron
Posts: 84
Joined: Fri Jun 03, 2016 5:53 pm
Location: The Netherlands

Re: DS18B20 error

Post by ernitron » Fri Oct 28, 2016 7:19 pm

Ehm... sorry guys but I have just obtained an outstanding temperature with my software and DS18x20 driver:
Freezer: 4079.313 °C
Yes, it reads FOUR THOUSAND seventynine and something degrees Celsius in my fridge!

Actually temperature sensor is set in my freezer which usually goes from -18 to -30 centigrades negative!
Is there any issue with NEGATIVE temperatures in new firmware?
Thanks if anybody can check.

Snippet from my code is simply:

Code: Select all

ow = onewire.OneWire(Pin(pin))
ds = ds18x20.DS18X20(ow)
roms = ds.scan()
ds.convert_temp()
time.sleep_ms(750)
temp = ds.read_temp(roms[0])
as I have only one ds18b20 attached.

Consider that with positive temperature it just works fine!

Firmware is: 1.8.5 fresh build of today... and software (installed in tenths of termometers can be found here https://github.com/ernitron/uPython-esp8266-httpserver
Hardware is WeMos D1 w 4MB flash


EDIT:

I had a look into the 1.8.5 code. For 0x28 sensors (which is my case) looks no negative numbers are returned. Am I wrong?

Code: Select all

def convert_temp(self, rom0, data):
        """
        Convert the raw temperature data into degrees celsius and return as a float.
        """
        temp_lsb = data[0]
        temp_msb = data[1]
        if rom0 == 0x10:
            if temp_msb != 0:
                # convert negative number
                temp_read = temp_lsb >> 1 | 0x80  # truncate bit 0 by shifting, fill high bit with 1.
                temp_read = -((~temp_read + 1) & 0xff) # now convert from two's complement
            else:
                temp_read = temp_lsb >> 1  # truncate bit 0 by shifting
            count_remain = data[6]
            count_per_c = data[7]
            temp = temp_read - 0.25 + (count_per_c - count_remain) / count_per_c
            return temp
        elif rom0 == 0x28:
            return (temp_msb << 8 | temp_lsb) / 16
        else:
            assert False

User avatar
pythoncoder
Posts: 4940
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: DS18B20 error

Post by pythoncoder » Sat Oct 29, 2016 7:21 am

You would seem to be right. According to the datasheet " The temperature data is stored as a 16-bit sign-extended two’s complement number ... The sign bits (S) indicate if the temperature is positive or negative: for positive numbers S = 0 and for negative numbers S = 1."

The existing code yields a 16 bit result. On 32 bit machines the sign should be extended to the upper two bytes:

Code: Select all

elif rom0 == 0x28:
	temp32 = (temp_msb << 8 | temp_lsb)  # lower 16 bits valid
	if temp32 & 0x8000: # sign bit set
	    temp32 |= 0xffff0000 # sign extend to 32 bits
	return temp32 / 16 # Scale and convert to float
Doubtless the rom10 code is similarly afflicted.
Peter Hinch

User avatar
ernitron
Posts: 84
Joined: Fri Jun 03, 2016 5:53 pm
Location: The Netherlands

Re: DS18B20 error

Post by ernitron » Sat Oct 29, 2016 9:52 am

Yes Pythoncoder. I guess nobody puts a temperature sensor in a fridge ;)

I just fixed with this into the driver on original branch. Seems to work for 0x28 sensors.
micropython/esp8266/modules/ds18xb20.py

Code: Select all


    def read_temp(self, rom):
        buf = self.read_scratch(rom)
        if rom[0] == 0x10:
            if buf[1]:
                t = buf[0] >> 1 | 0x80
                t = -((~t + 1) & 0xff)
            else:
                t = buf[0] >> 1
            return t - 0.25 + (buf[7] - buf[6]) / buf[7]
        else:
            #return (buf[1] << 8 | buf[0]) / 16 # Doesn't work for negative temps
            t = buf[1] << 8 | buf[0]
            if t & 0x8000:  # bit sign
                t = (t ^ 0xffff) + 1 # 2's complement
                return -(t / 16.0)
            return t / 16.0
Should someone issue a pull request?

User avatar
pythoncoder
Posts: 4940
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: DS18B20 error

Post by pythoncoder » Sun Oct 30, 2016 6:32 am

Yes, that looks a fine way to do it. I suppose someone with suitable hardware should look at the other ROM version. As for a PR, I guess you're the man ;)
Peter Hinch

User avatar
ernitron
Posts: 84
Joined: Fri Jun 03, 2016 5:53 pm
Location: The Netherlands

Re: DS18B20 error

Post by ernitron » Mon Oct 31, 2016 10:10 am

OK I did a pull request, but also asked Damien to fix this directly into the code that I presume he is managing directly.

For 0x10 I don-t assume any risk as I have no sensor of 0x10 class to test :)

bayardi
Posts: 1
Joined: Tue Dec 29, 2020 4:06 pm

Re: DS18B20 error

Post by bayardi » Fri Jan 15, 2021 8:34 pm

Hello everyone! I'm new here on the forum, I have a problem and would like everyone's help.

I have a project composed of:
1_esp32
4_ds18b20
using the thonny compiler.
with micropython.

my goal is to read the temperature of the sensors, and be able to add or remove the sensors at any time.
I'm using the following code:

* ------------------------------------------------- ------------------------------------

Code: Select all

import time
import machine
from machine import Pin, PWM
import onewire, ds18x20

dat = machine.Pin (4)
ds = ds18x20.DS18X20 (onewire.OneWire (dat))

while True:
    time.sleep_ms (750)
    roms = ds.scan ()
    print ()
# ds.convert_temp ()
    print ('temperatures:', end = '')
    for rom in roms:
        print (ds.read_temp (rom), end = '|')
* ------------------------------------------------- ------------------------------------

makes reading perfect.

when doing a defect simulation of the ds18s20 sensor, the following error occurs:

the error happens when my sensor disconnects from the board.

temperatures: 28.8125 | 29.25 | 29.0625 | 29.25 |
temperatures: 28.8125 | 29.25 |
temperatures: 28.8125 | Traceback (most recent call last):
File "<stdin>", line 27, in <module>
File "ds18x20.py", line 40, in read_temp
File "ds18x20.py", line 30, in read_scratch
Exception: CRC error

I would like you to help me with this error.
thanks!

Post Reply