Friday, July 6, 2012

pyMCU and DS18B20 temperature sensors

As part of my Garage Monitor project I am using a Maxim DS18B20 digital temperature sensor with a pyMCU microcontroller. I found lots of pages and sample code for using the DS18B20 with Arduino boards and various other microcontrollers but nothing for the pyMCU. The pyMCU uses a Python library published by the board manufacturer to control it. The DS18B20 uses the 1-Wire communication bus and the pyMCU Python library includes functions for 1-Wire communication called owWrite and owRead. The tricky part is figuring out the command sequence to coax a temperature reading out of the sensor. The communication with the sensor involves writing several hex values to it and then reading a hex temperature value. That hex value is then converted to a decimal value.

It took me the better part of three evenings to figure out the sequence of writes and reads. The other thing that was a bit difficult was figuring when to send reset pulses.

The pyMCU 1-Wire function uses this format:

owWrite(pinNum, mode, writeData)

The mode value determines if a reset pulse is sent before or after the data. Here is how I wired it:


And is the code that I wrote:

#!/usr/bin/python
#
# Written by Matthew McMillan
# matthew.mcmillan at gmail dot com
#
# This code reads a temperature value from
# a DS18B20 sensor using a pyMCU board. It only
# reads from a single sensor.
#
import pymcu           # Import the pymcu module

# Function to read value from DS18B20 temperature sensor
# Need to pass digital pin number and flag for F or C units
#
# 0x33  READ ROM. Read single device address.
# 0xCC  SKIP ROM. Address all devices on the bus
# 0x44  CONVERT T. Initiate temperature conversion
# 0xBE  READ SCRATCHPAD. Initiate read temp stored in the scratchpad.

def readtemp(pin,ForC):
    mb.owWrite(pin,1,0x33)
    ReadVal = mb.owRead(pin,0,8)
    mb.owWrite(pin,1,0xCC)
    mb.owWrite(pin,0,0x44)
    mb.owWrite(pin,1,0xCC)
    mb.owWrite(pin,0,0xBE)
    ReadVal = mb.owRead(pin,0,12)
    HexVal1 = hex(ReadVal[1])
    HexVal2 = hex(ReadVal[0])
    HexVal1 = HexVal1[2:4]
    HexVal2 = HexVal2[2:4]
    HexVal = '0x'+HexVal1+HexVal2
    DecVal = int(HexVal, 0)
    TempC = (DecVal * 0.0625)
    if ForC:
        TempF = ((TempC*9)/5)+32
        TempFR = round(TempF, 1)
        return TempFR
    else:
        TempCR = round(TempC, 1)
        return TempCR

################
# Main program
################

# Initialize mb (My Board) with mcuModule Class Object
mb = pymcu.mcuModule() 

#  Need to pass digital pin number and flag for ForC
tempout = readtemp(7,1)

print 'Temp: ' + str(tempout)


Please leave a comment if you found this helpful. I found this page on hackaday.com very helpful in figuring this out.

3 comments:

  1. Hi Matt,

    Thanks for the hack as I have also a project using pymcu and the DS18B20.

    For the convertion you can simplify everything just doing a :

    TempC = ((ReadVal[1] << 8) + ReadVal[0]) * 0.0625

    Did you made a try using the "Parasite-Powered" mode ?

    Sam-

    ReplyDelete
    Replies
    1. Thanks for the simplification. I'll have to try that out. I'm not a programmer by trade so my code is usually a bit ugly. I have not tried the parasite powered mode.

      Delete
  2. I've write the same about 1821 on PyMCU - http://highleaf.free.fr/capteur-de-temperature-dallas-1821.html

    ReplyDelete

Please note all comments are moderated by me before they appear on the site. It may take a day or so for me to get to them. Thanks for your feedback.