DS18B20 temperature sensor - One wire interface - a start

I started coding a one wire communication interface for communicating with the DS18B20 temperature sensor directly instead of reading the one wire bus bus. I managed to directly read the temperature using the below tutorial:

Reading bus

  Method dTemperature (sSensorID as string) as double
  dim ftemp as new FolderItem
  Dim t As TextInputStream
  dim sHulp as string
   
  try
    ftemp = new FolderItem("/sys/bus/w1/devices/" + sSensorID + "/w1_slave", FolderItem.PathTypeAbsolute)
    t = TextInputStream.Open(ftemp)
    sHulp = t.ReadLine
    if sHulp.Right(3)= "YES" then
      'read 2nd line
      sHulp = t.ReadLine
      return sHulp.Mid(sHulp.InStrB("t=")+2).Val/1000
  else
      return 99999
    end if
End Method

Now i try to directly communicate with the sensor using GPIO. I followed the following tuturial but with no luck so far (and I don’t have a oscilloscope). Maybe some people have some ideas what should be changed in the code. The code consists of a class called Onewire. The class has the following methods so far:

  • Initiate
  • Readbit
  • Readdata
  • WriteByte
  • WriteOne
  • WriteZero

Initiate - return boolean:

//Steps to reset one wire bus
  //* Pull bus low
  //* hold condition for 480us
  //* release bus
  //* wait for 60us
  //* read bus
  //* if bus low then device present set / return var accordingly
  //* wait for balance period (480-60)
  
  Dim value, iBit as Integer
 
  'start
  ' minimal 480 Microseconds low
  GPIO.PinMode(pin, GPIO.OUTPUT)
  GPIO.DigitalWrite(pin, GPIO.LOW)
  GPIO.DelayMicroseconds(480)
  
  'go high and wait for 60 Microseconds
  GPIO.DigitalWrite(pin, GPIO.HIGH)
  GPIO.DelayMicroseconds(60)
  GPIO.PinMode(pin, GPIO.INPUT)
  
  value = GPIO.DigitalRead( pin )
  
  GPIO.DelayMicroseconds(480)
  
  if value = 0 then
    Return True
  else 
    Return false
  end if

Readbit - return integer

  //*Steps for master to issue a read request to slave device on bus aka milk slave device
  //* pull bus low
  //* hold for 5us
  //* release bus
  //* wait for 45us for recovery (46us+5us=61us)
  Dim value, iBit as Integer
  iBit =0
  
  GPIO.PinMode(pin, GPIO.OUTPUT)
  GPIO.DigitalWrite(pin, GPIO.LOW)
  GPIO.DelayMicroseconds(5)
  GPIO.PinMode(pin, GPIO.INPUT)
  GPIO.DelayMicroseconds(15)
  value = GPIO.DigitalRead( pin )
  
  if value = 1 then
    iBit = 1
    
  end if
  
  GPIO.DelayMicroseconds(46)
   
  return iBit

Readdata (bits as integer) - returns string

  dim sHulp as string
  dim r as Integer
  sHulp = ""
   
  for r = 1 to bits
    if Readbit = 1 then
      sHulp = sHulp +"1"
    else
      sHulp = sHulp + "0"
    end if
  next r
   
  return shulp

WriteOne

  //*Steps for master to transmit logical one to slave device on bus
  //* pull bus low
  //* hold for 5us
  //* release bus
  //* wait for 1us for recovery
  
  GPIO.DigitalWrite(pin, GPIO.LOW)
  GPIO.DelayMicroseconds(5)
  
  GPIO.DigitalWrite(pin, GPIO.HIGH)
  GPIO.DelayMicroseconds(1)

WriteZero

  //Steps for master to transmit logical zero to slave device on bus
  //*pull bus low
  //* hold for 60us
  //* release bus
  //* wait for 1us for recovery
    
  GPIO.DigitalWrite(pin, GPIO.LOW)
  GPIO.DelayMicroseconds(60)
  
  GPIO.DigitalWrite(pin, GPIO.HIGH)
  GPIO.DelayMicroseconds(1)

WriteByte (Byte as integer, Power as Boolean)

  dim sHulp as string
  dim r, ilen as Integer
  
  sHulp = Bin(Byte)
  
  GPIO.PinMode(pin, GPIO.OUTPUT)
  ilen = sHulp.Len
  
  for r = 1 to ilen
    if sHulp.Mid(ilen-r+1,1) = "1" then
      WriteZero
    else
      WriteOne
    end if
  next r
  
  for r = 1 to 8-ilen
    WriteZero
  next r
    
  if Power then
    //GPIO.PinMode(pin, GPIO.OUTPUT)
    GPIO.DigitalWrite(pin, GPIO.HIGH)
    GPIO.Delay(10)
  end if

To read the temperature you need the following code:

  dim temp as new Onewire
  
  //#define DS1820_SKIP_ROM             0xCC
  //#define DS1820_READ_SCRATCHPAD      0xBE
  //#define DS1820_CONVERT_T            0x44
  
  temp.pin = 4
  
  if temp.Initiate = true then
    sHulp = "connected "
    
    temp.WriteByte(&h0CC,false)
    temp.WriteByte(&h044,true)
    
    GPIO.Delay(755)
    
    ''if temp.Initiate = true then
    ''temp.WriteByte(&h0CC,false)
    temp.WriteByte(&h0BE,false)
    
    sHulp = sHulp + temp.Readdata(16)
    
    ''end if
  else
    sHulp = "error "
    
  end if
  
  TextArea1.Text = sHulp

In the tutorial is also mentioned that “Since earlier I mentioned about that releasing bus is not as same as pushing the bus high”. But how can you release then using GPIO?

The link to the full code I have here.

Hi Coen,

I am working on your question about directly communicating with the DS18B20 with an SPI bus. It is taking me some time to go through the datasheet and the longest part is waiting for my Raspberry Pi 3B to update :slight_smile:

If someone else is able to develop a solution before I do, then great. I am also going to be out in the field during my day-job for the next couple of days. If I don’t get back to you right away then I’ll develop a solution when I am back at home.

Just a friendly reply to let you know that at least one person is working on your question :slight_smile:

I’ve done this with Arduino.
Maybe this can help you: https://github.com/milesburton/Arduino-Temperature-Control-Library

I’ve done this with an esp8266 module. then your temperature is available like on a web server via httpsocket.
a raspberry is way overkill to read temperature… (even the esp8266 is !)

you could also use an i2c to 1wire interface chip like the DS2482
https://www.maximintegrated.com/en/products/interface/controllers-expanders/DS2482-100.html
then the i2c on the raspberry is more easy to handle.

Hello Coen,

I have updated the program and I found that some of the code from http://karve.in/?p=1408 was using parameters that were not used, and some of the code may not be correct. Bit-banging a solution does take quite a while. Here is an update with the project you started. Its not working yet, and it is getting closer.

Updated - but not working yet

The most helpful information would be either: a) code that works or, b) really good instructions on the 18B20 chip. Some datasheets are better than others. I’ll ask you to keep working on it, and so will I. If we are both able to create a solution together, then it would be good!

I didn’t read your full code (definitely not the GPIO bit banging parts), but at a cursory glance I see some steps missing in the Read Temperature function below. In particular, you’ll find that 1-Wire devices tend to rely on a bus reset as a sort of command delimiter, and of course after every bus reset you have to address the sensor you want to talk to next, even it’s the same sensor you were just talking to (or you can skip-rom in lieu of addressing if it’s the only device attached)… this will make more sense after you read the following…

Generally speaking, the high-level steps to perform a temperature conversion on a DS18B20 and read the results are:

  1. Optional: Configure the sensor’s conversion resolution which ranges from 9 to 12 bits. I believe it defaults to 9 bits at power up.
  2. Initiate the temperature conversion
  3. Wait for some period of time. Amount of time depends on the conversion resolution, worst case is 750mS at 12 bit resolution. If the sensor is being parasitically powered, then no other communication can happen on the 1Wire bus during this period. If it’s externally powered, then other things can happen while you wait. Un-intuitively, if the sensor is parasitically powered, make certain to tie the sensor’s VDD pin to GND, otherwise sporadic 85 degree C readings will occur.
  4. Read results and parse.

Breaking these down further:
[h]1) Optional, configure the conversion resolution:[/h]
a) Reset the 1-Wire Bus
b) Address the sensor (or skip-rom, 0xCC)
c) Read existing scratchpad data (9 bytes, command code 0xBE)
d) Calculate new scratchpad contents to set the desired resolution
e) Reset the 1-Wire Bus
f) Address the sensor (or skip-rom, 0xCC)
g) Write new scratchpad data to the sensor (3 bytes, command code 0x4E)
h) Reset the 1-Wire Bus

[h]2) Initiate temperature conversion:[/h]
a) Reset the 1-Wire Bus
b) Address the sensor (or skip-rom, 0xCC)
c) Send Convert command (command code 0x44)

[h]3) Wait…[/h]
750mS worst case. Alternately poll the bus for conversion completion status, but only if the sensor is externally powered.

[h]4) Read the results:[/h]
a) Reset the 1-Wire Bus
b) Address the sensor (or skip-rom, 0xCC).
c) Read the scratchpad data (9 bytes, command code 0xBE).
d) Reset the 1-Wire bus.
e) Parse scratchpad and display results

Chay Wesley
Embedded Data Systems

[quote=298226:@Coen Martinus]

To read the temperature you need the following code:

  dim temp as new Onewire
  
  //#define DS1820_SKIP_ROM             0xCC
  //#define DS1820_READ_SCRATCHPAD      0xBE
  //#define DS1820_CONVERT_T            0x44
  
  temp.pin = 4
  
  if temp.Initiate = true then
    sHulp = "connected "
    
    temp.WriteByte(&h0CC,false)
    temp.WriteByte(&h044,true)
    
    GPIO.Delay(755)
    
    ''if temp.Initiate = true then
    ''temp.WriteByte(&h0CC,false)
    temp.WriteByte(&h0BE,false)
    
    sHulp = sHulp + temp.Readdata(16)
    
    ''end if
  else
    sHulp = "error "
    
  end if
  
  TextArea1.Text = sHulp

Hello Eugene,

Thanks for the update. Most of my programming is in the weekends, so somethings It takes some more time to do test with the raspberry. I will come back to this ASAP or at least next weekend.

@chay: thanks for this information.

This is very helpful Chay. Similar to Coen, I will work on this during my spare time, which is usually on the weekend.

:slight_smile:

I worked on this project a little more tonight, and the code at http://karve.in/?p=1408 does not work. I’ll keep looking for some good explanations on the DS18B20 and/or some working code.

Good news, I compiled the following github code with gcc and it works:

Big Banging DS18B20

Now its a matter of converting it to Xojo :slight_smile:

@Eugene thanks, I will look to the gcc code on thuesday to convert this to xojo.

new version

I tried to convert the ‘big banging’ code to Xojo (for single sensor). But for now no success. A new version added above.

Hi Coen,

Good news, I have the reset portion of the code working. When the one-wire is unplugged from pin #4 then the program is able to say ‘unconnected’, and when pin #4 is reconnected then it shows ‘connected’ with some bytes. The next step is to read the data. Here is the latest version to download: Reset Works

Besides connected I only get ones. The 750 microsecondes should be 750 milliseconde after the conversion. Next weekend I will continue.