B4R Question Dallas 18b20

Mania

Member
Licensed User
Longtime User
Hey! My configuration is B4R 4.0, Arduino 2.3.3. ESP32 Wroom. The program for handling OneWire doesn't detect any DS18b20 sensor. In Arduino and the old B4R, the same PCB works fine, so the hardware is correct. What am I doing wrong
B4X:
[CODE=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

End Sub

Private Sub AppStart
   Serial1.Initialize(115200)
   Log("AppStart")
 
 
 
   onewire.Initialize(27)
   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
 

Laurent95

Active Member
Licensed User
Longtime User
Hello,

The suggestion is maybe also to test on another GPIO, to see if it's not burned.
But if you are sure of everything, why are you asking?
The first thing is to say "Thank you" and then ask if you don't understand the answer given :).

I am sure of several things:
Dallas has not changed anything for a very long time on their ds18b20.
B4R can change version, it never means that any library has changed.
The Chinese make very bad copies of Dallas or Siemens sensors or whatever you want. The cheap quality is not real, it is just a dream, or a Chinese fake ;).

You say "the hardware is correct", maybe yes, but you talk also about a PCB. You didn't soldering the components on a PCB ? If yes like I'm sure, it's not the same components and not even a PCB i think, instead it's a breadboard with new components and cables. That already introduce many possibility of failure...
And to conclude your code is not really an example of that "is correct"...

Why an interrupt:
your code:
Sub Timer1_Tick
..../...
-> Too much done here for an interrupt, see my comment below
And :
onewire.Reset
onewire.Select(address)
onewire.Write(0x44, True)
'give it 1 second to read the temperature <- oh OK, but it's not done afterwards in the function, while the same commands are used again...
CallSubPlus("ReadTemparature", 1000, 0)
End
Then :
Your function called 1 second later:
Private Sub ReadTemparature (u As Byte)
onewire.Reset
onewire.Select(address)
etc.
Another reset, another sensor selection??? why, and this time without any pause... it's a bit weird I'm not sure the Dallas sensor really appreciates that. But i didn't work with it since a while and not with this library.

IMPORTANT, on all µCs, interrupts are made to:
- Wake up the µC when it is in sleep mode;
- Keep information of a button pressed, or whatever you want.
So keep information to do things in the infinite loop after, even if this loop blocks everything!
Because it is a hardware interrupt before all. So it is strongly recommended to make the code as short as possible, i.e. set a boolean to true etc.
And especially not to write a book... which leads you to an erroneous code, which never works absolutely well!

So the first question is why an interrupt? A simple timer in the infinite loop does exactly the same thing.
interrupt every 2 seconds... during my working time I was also an expert in heating and cooling regulation, I have never used a poll as short as that, do you think you are alone on an ESP, WIFI does not exist?

There is a lot of work to be done before solving anything. So Derez is right to bring you first on a link to learn one of the good ways to achieve it ;)

Have a good day everyone.
 
Upvote 0

Mania

Member
Licensed User
Longtime User

Hi! I mentioned that the hardware is fine because I tested the same configuration on Arduino and an older version of B4R. The code I posted and tested is Erel's example code, not mine. This code works correctly on B4R 3.9, but after updating everything to the latest version, it doesn’t work on the ESP32 Wroom-32D processor. On the ESP8266 12f processor, it works fine. I resolved the issue by embedding the code from Arduino into B4R inline. It may not look aesthetically pleasing, but it works properly.
B4X:
#Region Project Attributes
    #AutoFlushLogs: True
    #CheckArrayBounds: True
    #StackBufferSize: 600
#End Region
'Ctrl+Click to open the C code folder: ide://run?File=%WINDIR%\System32\explorer.exe&Args=%PROJECT%\Objects\Src

Sub Process_Globals
    Public Serial1 As Serial
    Private wifi As ESP8266WiFi
    Private timer1 As Timer
    Dim odlicz As Byte
    Public tempds As Float = 0
    Private czujnik As Byte
    
    
    Private bc As ByteConverter
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    'example of connecting to a local network
'    If wifi.Connect2("SSID", "PASSWORD") Then
'        Log("Connected to network")
'    Else
'        Log("Failed to connect to network")
'    End If
    
    timer1.Initialize("timer1_Tick", 2000)
    timer1.Enabled = True
    
    RunNative("initialize",Null)
    
    
End Sub


Sub timer1_tick
    
    odlicz= odlicz +1
    Select Case odlicz
        
        Case 1
            RunNative("white",Null)
            Case 2
            RunNative("dallas",Null)
            odlicz= 0
            Log("Ds18b20: ",tempds," -  ", czujnik)
                
    End Select
    
    
'    Dim addr2 As String = bc.HexFromBytes(c)
'    Log("c =",addr2)

    
End Sub


#if c
#include <OneWire.h>
OneWire  ds(16);

  byte i;
  byte present = 0;
  byte type_s = 0;
  byte data[9];
  byte addr[8];

  float celsius, fahrenheit;
  String address1;
  int czujnik1 = -1;
 
void initialize(B4R::Object* o) {
Serial.begin(115200);



 Serial.println("jestem.");


}   // koniec initialize

//*******************************************************************
void white(B4R::Object* o) {
 

 
  if ( !ds.search(addr)) {
  //  Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
 
 
//  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
//    Serial.write(' ');
 //   Serial.print(addr[i], HEX);
    
  }
    
      
      
  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
 // Serial.println();
 
     ds.write(0x4E);               // Komenda do zapisu do rejestru Scratchpad
     ds.write(0);                  // TH - wartość progu wysokiego (dowolna, np. 0)
     ds.write(0);                  // TL - wartość progu niskiego (dowolna, np. 0)
     ds.write(0x7F);
 
  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
 
 

                                 // Ustawienie rozdzielczości na 12 bitów
 
 
}   // koniec white

//*************************************************8

void dallas(B4R::Object* o) {
byte present = 0;
 
 

 present = ds.reset();
  ds.select(addr);
 // ds.write(0x7F);   
    ds.write(0xBE);         // Read Scratchpad

//  Serial.print("  Data = ");
 // Serial.print(present, HEX);
  //Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    
  //  Serial.print(" ");
  }
 
 

  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
 
 // Serial.print("  Temperature = ");
  //Serial.print(celsius);
 
  //Serial.println(" ");
  bit6=addr[6];
  bit7=addr[7];

  address1 = String(addr[6], HEX) + String(addr[7], HEX);

  // Wyświetlenie wyniku
 // Serial.println("Adres: " + address1);
 
   if (address1 == "33b") {
    czujnik1 = 1;
  } else if (address1 == "34") {
    czujnik1 = 0;
  } else {
    czujnik1 = -1; // domyślna wartość, jeśli adres nie pasuje
  }




 
 
   //Serial.print(" bit  ");
   //Serial.print(bit6);
   // Serial.print(" ");
   //Serial.print(bit7);
     b4r_main::_czujnik = czujnik1;
     b4r_main::_tempds =  celsius;
  
}   // koniec dallas
#End If
I don’t use the rOneWire library. Sorry for my English.
 
Upvote 0

Laurent95

Active Member
Licensed User
Longtime User
Hello,

OK, I wasn't sure if you had done these tests, especially because you were talking about a PCB. If it's a PCB it can't be a test it's soldered, or you're very rich :D. We use a breadboard instead.
I found Erel's example, but he wrote it in 2016, so I think that at that time the problems related to interruptions were not as well known. So, the comment I made is still relevant even if several ESP32s have 2 cores now. Erel said it himself on the example, it was presented like this to don't block the main 'thread', he was talking about the main loop.

For the new B4R version it is possible, I admit that I haven't done the updates of the B4X products for quite a long time. Two key points for that, I'm now on Linux, I've been using micopython on ESPs for a while now, my projects don't require real time.

Anyway your problem is solved, it doesn't matter if you use inline C, it's an interesting possibility, it works and I've often used that too;).
No matter for your English, it's not my native language too, I'm French.

Have fun
 
Upvote 0
Top