Addressing two DS18x20 Temperature Sensor's on LoPy4

Guys Im in over my head and need some assistance please!!

Following on from my LoPy4 adventures I now want to address two DS18x20 temperature sensors (air & soil temperatures), connected to the same GPIO.

I have done my best to follow the Pycom documentation and looking into the onewire.py library. The best I have got so far is this:


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

ow = OneWire(Pin(‘P10’))
temp = DS18X20(ow)

while True:
print(onewire.OneWire.scan(ow))
print(temp.read_temp_async())
time.sleep(1)
temp.start_conversion()
time.sleep(1)


Which gives the results:


[bytearray(b’(\xaa#\xf07\x14\x01g’), bytearray(b’(\x18/\x8e\t\x00\x001’)]
18.3125


So now I have the bytearray of the two ROMs but how do I get that last step completed such that I can update ow = OneWire(Pin(‘P10’)) to include the ROM address.

Or, as an alternative, how would I get both temperatures and be able to identify which temp came from which sensor??

Thanks
Jon

Hi Jon,

I’ve tagged @clinton to see if he can help with this problem. Surely you can just connect to another GPIO though right?

Thanks Stephen, appreciate the help.

I certainly could use another GPIO for the second sensor to get me out of a bind, I just figured that I could fairly easily daisy chain the second one of the one onewire, seemingly not!

Hopefully @Clinton can advise, I cant be the only one to have encountered the issue.

Thx
Jon

Hi Jon,

I looked it up for you. You can find an example here:
http://docs.micropython.org/en/v1.8.2/esp8266/esp8266/tutorial/onewire.html

Just take the ROM address that you know and do two separate reads.

Thanks Stephen,
Interestingly enough I was looking at this page last night:
http://docs.micropython.org/en/v1.9.3/esp8266/esp8266/tutorial/onewire.html

Its the same page except for the fact that its a later version (v1.9.3 and not v1.8.2 as per your link). On the LoPy4, the v1.9.3 code did not work in Atom. The only difference that I can see is that the v1.9.3 code imports ds18x20 from / and onewire and the older version does not.

I will try this tonight and see what happens.

Thx
J

Further to above and below, how do I incorporate my byte array Roms into the code? Should I convert them into hex first?

Quick update, the code from the python pages (v1.8.2) give an error:

File “”, line 7, in
ValueError: invalid argumet(s) value

Here’s a screenshot of my Atom after I try to run the code. The only thing I did was change from Pin12 to Pin10.

R
Jon

I think you could just replace “rom” with the rom value that you recorded.

As far as why that code fails on line 7, something is wrong with how you are calling that pin, but I’m not sure what.

Best of luck!

You may need to specify the pin as a string as the name P10 may not be the same as the hardware pin 10.
dat = machine.Pin('P10')

I believe you are right Clinton.

See https://docs.pycom.io/firmwareapi/pycom/machine/pin.html

How does it go after that line is fixed are you able to select multiple sensors?

Well, kind of success…

After reading a whole load of code from various sources I got myself all muddled up with ‘onewire’, ‘OneWire’, ‘ds18x20’. ‘DS18X20’, ‘ds18b20’ and ‘DS18B20’!!

This is how I finally got to detecting both ROMs. I havent tidied the code up at all, I know there are a lot of variables I can add in to make it more readable, but at least it works… sort of.

The code identifies both ROMs and proceeds to read them both. The only problem is that one of them always reads 85^C (regardless of which order I have the sensors - I have 3 and have swapped out the 85^C one to eliminate possibility of a dead sensor.) I am using a 47k pull-up resistor across the yellow sense-wire and the +3V.

Any ideas on the 85^C issue? Until I get this sorted I havent specifically tried to read a particular ROM address.

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

# the device is on GPIO12
dat = machine.Pin('P10')

# create the onewire object
ds = onewire.DS18X20(onewire.OneWire(dat))

# scan for devices on the bus
# roms = ds.scan()
roms = onewire.OneWire.scan(OneWire(Pin('P10')))
print('found devices:', roms)

# loop 10 times and print all temperatures
DS18X20(OneWire(Pin('P10'))).start_conversion()

for i in range(100):
#    print('temperatures:', end=' ')
#    DS18X20(OneWire(Pin('P10'))).convert_temp()
#    time.sleep(1)
#    print(DS18X20(OneWire(Pin('P10'))).read_temp_async())
#    time.sleep(1)
for rom in roms:
    time.sleep(1)
    print(rom)
#  print(DS18X20(OneWire(Pin('P10'))).read_temp_async(rom), end=' ')
    print(DS18X20(OneWire(Pin('P10'))).read_temp_async(rom))
    time.sleep(1)
print()

Thanks heaps, all advice & pointers are really appreciated.
Jon

Update…

I went back the basics… Read 1 sensor, read two sensors on different pins. Initially I got the 85^C reading on the second pin - turns out I needed to ‘start_conversation()’ on the second pin.

This is the codes that successfully reads two sensors on two pins:

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

#DS18B20 data line connected to pin P10 & P11
ow = OneWire(Pin('P10'))
temp_10 = DS18X20(ow)
ow11 = OneWire(Pin('P11'))
temp_11 = DS18X20(ow11)

while True:
    temp_10.start_conversion()
    temp_11.start_conversion()
    time.sleep(1)
    print("Pint 10 Temp: ", temp_10.read_temp_async())
    print("Pint 11 Temp: ", temp_11.read_temp_async())
    time.sleep(1)

Noting the issue about the need to start_conversation() on both pins, Im assuming that I probably need to do the same but by ROM address when using multiple sensors on the one pin.

I’ll have another look later today.

R
Jon

1 Like

Update…
Its working:) Two OneWire sensors connected on the same pin, easily identifiable and individually callable.

After getting to the stage noted in my thread above I re-read through the onewire.py library and made some amendments to my code.

Ive put comments in it and listed it here to try to help other non-coder’s like me.

Hope it helps someone.

# Using two DS18x20 (Dallas OneWire) sensors connected to the same pin and via onewire
# 4k7 pull-up resistor, identify the ROM addresses of each sensors and then call each
# sensor to read and present the temperatures.
# LoPy4 pinout details here: https://docs.pycom.io/datasheets/development/lopy4.html
#
# J. Kelly, June 2019
#

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

# DS18B20 data line connected to pin P10
ow = OneWire(Pin('P10'))
temp=DS18X20(ow)

# b = bytearray to hold ROM addresses from OneWire address scan
time.sleep(1)
b = (onewire.OneWire.scan(ow))
# Below prints the array, b
#print("b = ", b)
soil_temp_rom = b[0]
#print("Soil Temp ROM = ", b[0])
air_temp_rom = b[1]
#print("Air Temp ROM = ", b[1])

while True:
    Current_Air_Temp = 0.0
    Current_Soil_Temp = 0.0
    time.sleep(1)
    temp.start_conversion(soil_temp_rom)
    temp.start_conversion(air_temp_rom)
    time.sleep(1)
    Current_Soil_Temp = temp.read_temp_async(soil_temp_rom)
    Current_Air_Temp = temp.read_temp_async(air_temp_rom)
    print("Current Soil Temp = ", Current_Soil_Temp)
    print("Current Air Temp = ", Current_Air_Temp)

Now to take these learnings and implement in my TTN & Node-Red project:)

Jon

1 Like

Looks great Jon! I’m glad you worked it out!