B4R Code Snippet Reading temperature sensor DS18B20 via inline C/C++, again

Peter Simpson

Expert
Licensed User
SubName: Using inline C/C++ to read temperature module DS18B20.
Description: You can use this basic code to read the temperature readings from a DS18B20 temperature module, this can easily be done using inline C/C++. I'm reading °C but you can easily change it to °C by replacing 'sensors.getTempCByIndex(0)' with 'sensors.getTempFByIndex(0)'.

AppStart
Temperature is: 23.2500°C
Temperature is: 23.2500°C
Temperature is: 23.2500°C
Temperature is: 23.2500°C
Temperature is: 23.2500°C
Temperature is: 23.3125°C
Temperature is: 23.2500°C
Temperature is: 23.3125°C
Temperature is: 23.3125°C
Temperature is: 23.2500°C
Temperature is: 23.2500°C
Temperature is: 23.3125°C
Temperature is: 23.2500°C
Temperature is: 23.2500°C
Temperature is: 23.2500°C
Temperature is: 23.3125°C
Temperature is: 23.2500°C
Temperature is: 23.2500°C
Temperature is: 23.2500°C

Yes there's already code and also a library on this forum to do this, but I personally use this solution.
B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.

    Public Serial1 As Serial
    Public Temperature As Float
    Public TempTimer As Timer
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")

    RunNative("loop", Null)  'NOT REALLY NEEDED, BUT I USE IT TO IGNORE THE VERY FIRST TEMP READING THAT IS SOMETIME INCORRECT

    TempTimer.Initialize("TempUpdate_Tick", 2500)
    TempTimer.Enabled = True
End Sub

Sub TempUpdate_Tick
    RunNative("loop", Null)
    Log("Temperature is: ", Temperature, "°C")
End Sub

#if C
// Include the libraries
#include <OneWire.h>
#include <DallasTemperature.h>

// DS18B20 temperature sensor data wire is plugged into pin 2
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices
    OneWire oneWire(ONE_WIRE_BUS);

// Pass oneWire reference to Dallas Temperature.
    DallasTemperature sensors(&oneWire);

void setup (B4R::Object* unused) {
  // Start up the library.
  sensors.begin(); //B4R USERS, YOU CAN TAKE THIS LINE OUT AS IT STILL WORKS WITHOUT IT
}

void loop (B4R::Object* unused) {
//    Request temperature readings from ALL devices on the bus
    sensors.requestTemperatures();

//    You can have more than one DS18B20 on the same bus. 0 refers to the first IC on the wire. sensors.getTempCByIndex(0) = °C, sensors.getTempFByIndex(0) = °F
     b4r_main::_temperature = sensors.getTempCByIndex(0);
}
#End if
Tags: Temperature, Sensor, DS18B20, Arduino, Resistor, inline, C, C++

Temperature_bb.png
 
Last edited:

derez

Expert
Licensed User
It runs well on Arduino UNO but not on WEMOS D1 R2, I get the following error:
In file included from sketch\b4r_main.cpp:11:0:
D:\Arduino\libraries\OneWire/OneWire.h:108:2: error: #error "Please define I/O register types here"
#error "Please define I/O register types here"
^
D:\Arduino\libraries\OneWire/OneWire.h:115:5: error: 'IO_REG_TYPE' does not name a type
IO_REG_TYPE bitmask;
^
D:\Arduino\libraries\OneWire/OneWire.h:116:14: error: 'IO_REG_TYPE' does not name a type
volatile IO_REG_TYPE *baseReg;
^
exit status 1
Does anybody know how to fix it ?
 

Erel

Administrator
Staff member
Licensed User
That example works fine here. Tested on Arduino Mega and Wemos D1.

Logs:
ROM = 28FF963820160307
Chip = DS18B20
Data = 87014B467FFF0C10B7000000
CRC = B7
Temperature = 24.44 Celsius, 75.99 Fahrenheit
No more addresses.
ROM = 28FF963820160307
Chip = DS18B20
Data = 86014B467FFF0C10F4000000
CRC = F4
Temperature = 24.37 Celsius, 75.87 Fahrenheit
No more addresses.
ROM = 28FF963820160307
Chip = DS18B20
Data = 85014B467FFF0C1031000000
CRC = 31
Temperature = 24.31 Celsius, 75.76 Fahrenheit
No more addresses.
ROM = 28FF963820160307
Chip = DS18B20
Data = 84014B467FFF0C1072000000
CRC = 72
Temperature = 24.25 Celsius, 75.65 Fahrenheit
No more addresses.
ROM = 28FF963820160307
Chip = DS18B20
Data = 83014B467FFF0C10A2000000
CRC = A2
Temperature = 24.19 Celsius, 75.54 Fahrenheit
No more addresses.
ROM = 28FF963820160307
Chip = DS18B20
Data = 82014B467FFF0C10E1000000
CRC = E1
Temperature = 24.12 Celsius, 75.43 Fahrenheit
B4X:
Sub Process_Globals
   Public Serial1 As Serial
   Private onewire As OneWire
   Private timer1 As Timer
   Private bc As ByteConverter
   Private address(8) As Byte
   Private type_s As Boolean
   Private d1 As D1Pins
End Sub

Private Sub AppStart
   Serial1.Initialize(115200)
   Log("AppStart")
   onewire.Initialize(d1.D5)
   timer1.Initialize("timer1_Tick", 2000)
   timer1.Enabled = True
End Sub

Sub Timer1_Tick
   If onewire.Search(address) = False Then
     onewire.ResetSearch
     Log("No more addresses.")
     Return
   End If
   Log("ROM = ", bc.HexFromBytes(address))
   If onewire.CRC8(address, 7) <> address(7) Then
     Log("CRC is not valid!")
     Return
   End If
   Select address(0)
     Case 0x10
       Log("Chip = DS18S20")
       type_s = True
     Case 0x28
       Log("Chip = DS18B20")
       type_s = False
     Case 0x22
       Log("Chip = DS1822")
       type_s = False
     Case Else
       Log("Device is not a DS18x20 family device.")
       Return
   End Select
   onewire.Reset
   onewire.Select(address)
   onewire.Write(0x44, True)
   'give it 1 second to read the temperature
   CallSubPlus("ReadTemparature", 1000, 0)
End Sub

Private Sub ReadTemparature (u As Byte)
   onewire.Reset
   onewire.Select(address)
   onewire.Write(0xBE, False)
   Dim data(12) As Byte
   onewire.ReadBytes(data, 9)
   Log("Data = ", bc.HexFromBytes(data))
   Log("CRC = ", bc.HexFromBytes(Array As Byte(onewire.CRC8(data, 8))))
   Dim raw As Int = Bit.Or(Bit.ShiftLeft(data(1), 8), data(0))
   If type_s Then
     raw = Bit.ShiftLeft(raw, 3)
     If data(7) = 0x10 Then
       raw = Bit.And(raw, 0xFFF0) + 12 - data(6)
     End If
   Else
     Dim cfg As Byte = Bit.And(data(4), 0x60)
     If cfg = 0 Then
       raw = Bit.And(raw, Bit.Not(7))
     Else if cfg = 0x20 Then
       raw = Bit.And(raw, Bit.Not(3))
     Else if cfg = 0x40 Then
       Bit.And(raw, Bit.Not(1))
     End If
   End If
   Dim celsius As Double = raw / 16
   Dim fahrenheit As Double = celsius * 1.8 + 32
   Log("Temperature = ", NumberFormat(celsius, 0, 2), " Celsius, " _
  , NumberFormat(fahrenheit, 0, 2), " Fahrenheit")
End Sub
 

derez

Expert
Licensed User
My sensor looks like a transistor, not an IC like yours, may be it is not recognized, I get the "Device is not a DS18x20 family device" message. I have tried to comment all the first part until the reset but I get all the readings zero.
With that sensor I got correct readings with arduino sketch and with Peter Simson's code above - but only on UNO.
The arduino sketch fails with WEMOS with the same error as above about IO_REG_TYPE.
I'll continue playing tomorrow, its my grandchildren time now...
 

Peter Simpson

Expert
Licensed User
Darn it, I too have the same issue using a D1 @derez :mad:, I only tested it on an UNO.
I also tried the C++ code in the Arduino IDE and the same thing happened again with D1, Uno worked perfect.

Erel is just holding a board with a DS18B20 temperature sensor on it, I'm going to presume that the board has a SMD capacitor and a SMD resistor on it, but I could be wrong. Anyway It's not an IC, it exactly what you are using, the package is called a 'TO-92 Case', it just looks like an IC in Erels photo, but it's not.
 

derez

Expert
Licensed User
Darn it, I too have the same issue using a D1 @derez :mad:, I only tested it on an UNO.
I also tried the C++ code in the Arduino IDE and the same thing happened again with D1, Uno worked perfect.

Erel is just holding a board with a DS18B20 temperature sensor on it, I'm going to presume that the board has a SMD capacitor and a SMD resistor on it, but I could be wrong. Anyway It's not an IC, it exactly what you are using, the package is called a 'TO-92 Case', it just looks like an IC in Erels photo, but it's not.
Have you tried Erel's code ? does it work for you on Uno ?
 

derez

Expert
Licensed User
Erel, when checking the source of your code (from the onewire library examples) in Wemos I also get the same error message "Please define I/O register types here" from line 108 in the onewire.h file.
I know that our Wemos mc are different, I already posted about the different pins names.
Found this link http://www.esp8266.com/viewtopic.php?f=32&t=6775 , someone changed the library and made it work but I can't understand the change.
 
Last edited:

derez

Expert
Licensed User
Got the arduino example from onewire working, after downloading the last onewire library and after changing this : OneWire ds(4); (it was 10) .
Erel's code still does not work whatever pin I use.
With Peter's code I get -127 C which is wrong. Maybe it is a pin's number problem.
 
Last edited:

derez

Expert
Licensed User
Erel's code works also with wire connected to D4 (named with my WEMOS as D1.D2...) and although the voltage for the sensor is 5V I take the sense wire directly to the pin, no level down conversion.
Peter's code works also, changing the pin number to 4 : #define ONE_WIRE_BUS 4
:):):):):):):):):):):):):):):)
 
Top