DS18B20 / OneWire not detected on Arduino UNO Q — Zephyr timing / GPIO / RPC issue?

The example program of the library works well for UNO R3 IDE 1.8.19. The prit shows the device address and the content of scratchpad memory.

For UNO Q , it requires IDE 2.3.7 for the UNO Q board to get installed. However, the example sketch of the library gives the following compilation error,. I can't proceed,

WARNING: library OneWireNg claims to run on avr, megaavr, esp8266, esp32, rp2040, sam, samd, samd_beta, stm32, mbed, mbed_edge, mbed_giga, mbed_nano, mbed_nicla, mbed_portenta, mbed_rp2040 architecture(s) and may be incompatible with your current board which runs on zephyr architecture(s).
In file included from C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:20:
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/OneWireNg_CurrentPlatform.h:59:3: warning: #warning "Can't detect platform. Use proper class for the platform you are compiling for!" [-Wcpp]
   59 | # warning "Can't detect platform. Use proper class for the platform you are compiling for!"
      |   ^~~~~~~
In file included from c:\Users\GolamMostafa\Documents\Arduino\libraries\DebugLog/DebugLogRestoreState.h:4,
                 from c:\Users\GolamMostafa\Documents\Arduino\libraries\DebugLog/DebugLog.h:54,
                 from c:\Users\GolamMostafa\Documents\Arduino\libraries\MsgPack/MsgPack.h:5,
                 from C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RPClite\src/error.h:17,
                 from C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RPClite\src/client.h:14,
                 from C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RPClite\src/Arduino_RPClite.h:22,
                 from C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RouterBridge\src/bridge.h:27,
                 from C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RouterBridge\src/Arduino_RouterBridge.h:16,
                 from C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:23:
c:\Users\GolamMostafa\Documents\Arduino\libraries\DebugLog/DebugLogEnable.h:50:4: warning: #warning "Defaulting to a log level of: DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE" [-Wcpp]
   50 |   #warning "Defaulting to a log level of: DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE"
      |    ^~~~~~~
In file included from c:\Users\GolamMostafa\Documents\Arduino\libraries\DebugLog/DebugLogRestoreState.h:4,
                 from c:\Users\GolamMostafa\Documents\Arduino\libraries\MsgPack/MsgPack.h:19:
c:\Users\GolamMostafa\Documents\Arduino\libraries\DebugLog/DebugLogEnable.h:50:4: warning: #warning "Defaulting to a log level of: DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE" [-Wcpp]
   50 |   #warning "Defaulting to a log level of: DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE"
      |    ^~~~~~~
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:77:45: error: wrong number of template arguments (0, should be 1)
   77 | static Placeholder<OneWireNg_CurrentPlatform> ow;
      |                                             ^
In file included from C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:22:
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/utils/Placeholder.h:71:8: note: provided for 'template<class T> struct Placeholder'
   71 | struct Placeholder: ::detail::Placeholder<T> {};
      |        ^~~~~~~~~~~
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino: In function 'void printScratchpad(const DSTherm::Scratchpad&)':
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:114:5: error: 'Monior' was not declared in this scope; did you mean 'Monitor'?
  114 |     Monior.print("; Resolution:");
      |     ^~~~~~
      |     Monitor
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino: In function 'void setup()':
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:28:25: error: expected type-specifier before numeric constant
   28 | # define OW_PIN         13
      |                         ^~
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:28:25: note: in definition of macro 'OW_PIN'
   28 | # define OW_PIN         13
      |                         ^~
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:130:41: error: expected ')' before numeric constant
  130 |     new (&ow) OneWireNg_CurrentPlatform(OW_PIN, false);
      |                                        ~^
      |                                         )
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:132:19: error: no matching function for call to 'DSTherm::DSTherm(int&)'
  132 |     DSTherm drv(ow);
      |                   ^
In file included from C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:21:
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/drivers/DSTherm.h:245:5: note: candidate: 'DSTherm::DSTherm(OneWireNg&)'
  245 |     DSTherm(OneWireNg& ow): _ow(ow) {}
      |     ^~~~~~~
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/drivers/DSTherm.h:245:24: note:   no known conversion for argument 1 from 'int' to 'OneWireNg&'
  245 |     DSTherm(OneWireNg& ow): _ow(ow) {}
      |             ~~~~~~~~~~~^~
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/drivers/DSTherm.h:25:7: note: candidate: 'constexpr DSTherm::DSTherm(const DSTherm&)'
   25 | class DSTherm
      |       ^~~~~~~
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/drivers/DSTherm.h:25:7: note:   no known conversion for argument 1 from 'int' to 'const DSTherm&'
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/drivers/DSTherm.h:25:7: note: candidate: 'constexpr DSTherm::DSTherm(DSTherm&&)'
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/drivers/DSTherm.h:25:7: note:   no known conversion for argument 1 from 'int' to 'DSTherm&&'
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino: In function 'void loop()':
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:159:19: error: no matching function for call to 'DSTherm::DSTherm(int&)'
  159 |     DSTherm drv(ow);
      |                   ^
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/drivers/DSTherm.h:245:5: note: candidate: 'DSTherm::DSTherm(OneWireNg&)'
  245 |     DSTherm(OneWireNg& ow): _ow(ow) {}
      |     ^~~~~~~
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/drivers/DSTherm.h:245:24: note:   no known conversion for argument 1 from 'int' to 'OneWireNg&'
  245 |     DSTherm(OneWireNg& ow): _ow(ow) {}
      |             ~~~~~~~~~~~^~
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/drivers/DSTherm.h:25:7: note: candidate: 'constexpr DSTherm::DSTherm(const DSTherm&)'
   25 | class DSTherm
      |       ^~~~~~~
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/drivers/DSTherm.h:25:7: note:   no known conversion for argument 1 from 'int' to 'const DSTherm&'
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/drivers/DSTherm.h:25:7: note: candidate: 'constexpr DSTherm::DSTherm(DSTherm&&)'
c:\Users\GolamMostafa\Documents\Arduino\libraries\OneWireNg\src/drivers/DSTherm.h:25:7: note:   no known conversion for argument 1 from 'int' to 'DSTherm&&'
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:183:26: error: invalid type argument of unary '*' (have 'int')
  183 |     for (const auto& id: *ow) {
      |                          ^~~
In file included from C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RouterBridge\src/Arduino_RouterBridge.h:17:
C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RouterBridge\src/monitor.h: In instantiation of 'bool BridgeMonitor<BufferSize>::begin(long unsigned int, uint16_t) [with unsigned int BufferSize = 512; uint16_t = short unsigned int]':
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:134:14:   required from here
C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RouterBridge\src/monitor.h:40:30: warning: unused parameter '_legacy_baud' [-Wunused-parameter]
   40 |     bool begin(unsigned long _legacy_baud=0, uint16_t _legacy_config=0) {
      |                ~~~~~~~~~~~~~~^~~~~~~~~~~~~~
C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RouterBridge\src/monitor.h:40:55: warning: unused parameter '_legacy_config' [-Wunused-parameter]
   40 |     bool begin(unsigned long _legacy_baud=0, uint16_t _legacy_config=0) {
      |                                              ~~~~~~~~~^~~~~~~~~~~~~~~~
C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RouterBridge\src/monitor.h: In instantiation of 'int BridgeMonitor<BufferSize>::read(uint8_t*, size_t) [with unsigned int BufferSize = 512; uint8_t = unsigned char; size_t = unsigned int]':
C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RouterBridge\src/monitor.h:56:13:   required from 'int BridgeMonitor<BufferSize>::read() [with unsigned int BufferSize = 512]'
C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RouterBridge\src/monitor.h:54:9:   required from here
C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.52.0\libraries\Arduino_RouterBridge\src/monitor.h:63:45: warning: comparison of integer expressions of different signedness: 'int' and 'size_t' {aka 'unsigned int'} [-Wsign-compare]
   63 |         while (temp_buffer.available() && i < size) {
      |                                           ~~^~~~~~
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino: At global scope:
C:\Users\GolamMostafa\AppData\Local\Temp\.arduinoIDE-unsaved202618-8764-1r37z9n.ouov\DallasTemperature\DallasTemperature.ino:80:13: warning: 'bool printId(const uint8_t (&)[8])' defined but not used [-Wunused-function]
   80 | static bool printId(const OneWireNg::Id& id)
      |             ^~~~~~~
exit status 1

Compilation error: wrong number of template arguments (0, should be 1)

Uno Q , with Q for Questions with capital Q.

Mmm, more complex than thought. Not planned to buy an UNO Q soon as my backlog has prio. On the other hand having working libs on the Q is valuable.

Need to think what is a good strategy here.

A:

What about going through the datasheet of DS18B20 and convert the timing diagrams into bitbang codes keeping close attention to what Zephyr RTOS does/will do in this business? It is possible, as I hope, to do something in this case for a person like @robtillaart having excellent expertise in creating libraries for 3rd party devices.

  • Generating RESET command (Fig-1) to the sensor is easy.


    Figure-1:

  • Issue ROM-read command and collecting the 64-bit data, formatting them, and then presenting them on Serial Monitor Console (Fig-2).

  • etc.

B:


Figure-2:

1. In Arduino UNO R3, the Serial Monitor under IDE 1.8.18/2.3.7 has the following physica/virual connection (at my level of understanding):

From hardware UART Port of ATmega328P MCU (async TTL) -----> UART signal/USB signal Converter chip on UNO R3 Board -----> USB-B connector of UNO R3 -----> USB-A connector of PC -----> USB signal/virtual UART signal converter -----> soft decoder/formatter ----> OutputBox of Serial Monitor

2. The Serial Monitor in Step-1 is seen as Serial object by the driver software. So, we have this sketch to show "Hello!" on the Serial Monitor.

void setup
{
    Serial.begin(9600);
    delay(1000);  //wait for the hardware of Serial object to get initialized
    Serial.println("Hello!");
}

void loop(){}

3. In Arduino UNO Q, the Serial Monitor (bettr to call Serial Console) under IDE 2.3.7 has the following physica/virtual connection (Fig-2, at my level of understanding):

From hardware LUART1 Port of STM32U585 MCU (async TTL) -----> QRB2210 MPU via Router Bridge (hardware communication path) -----> UART signal/USB signal converter -----> USB-C connector of UNO Q -----> USB-A connector of PC -----> USB signal /virtual UART signal converter -----> soft decoder/formatter ----> OutputBox of Serial Console

4. The Serial Console in Step-3 is seen as Monitor object by the driver software. So, we have this sketch to show "Hello!" on the Serial Console.

#include<Arduino_RouterBrige.h>  //owning comm path between MCU/MPU

void setup
{
    Bridge.begin();
    Monitor.begin(9600);
    delay(1000);  //wait for the hardware of Bridge/Monitor objects to get initialized
    Monitor.println("Hello!");
}

void loop(){}

@GolamMostafa

Just a thought,

Can you disable interrupts before reading the ds18b20, and enable them afterwards? (Every call must be with interrupt disabled)

My DHTNEW library for DHT22 has this option to prevent RTOS et al to disrupt the time sensitive bit banging.

I have tried the following sketch on UNO Q with interrupts disabled globally (noInterrupts()) in the setup() function, and still no reading from the sensor. however, the same sketch works well with UNO R3 IDE 2.3.7.

#include <OneWire.h>
//#include <Arduino_RouterBridge.h>

OneWire ds(2);  //DPin-2 with 4.7k pull-up

byte data[12];
byte addr[8];
float celsius;

void setup() {
  //Bridge.begin();
  //Monitor
  Serial.begin(9600);
  noInterrupts();
  //-------------
  //Monitor
  Serial.println("Acquiring 64-bit ROM Code: ");
  ds.reset();
  ds.search(addr);
  //Monitor
  /*Serail.print("ROM =");
  for (int i = 0; i < 8; i++) {
    byte y = addr[i];
    if (y < 0x10) {
      //Monitor
      Serial.print('0');  //leading 0
    }
    Monitor.print(addr[i], HEX);
    Monitor.print(' ');
  }
  Monitor.println();*/
}

void loop() {
  ds.reset();
  ds.select(addr);
  ds.write(0x44);  // start conversion, with parasite power on at the end

  delay(1000);  // maybe 750ms is enough, maybe not

  ds.reset();
  ds.select(addr);
  ds.write(0xBE);                // Read Scratchpad
  for (int i = 0; i < 9; i++) {  // we need 9 bytes
    data[i] = ds.read();
    //Monitor
    Serial.print(data[i], HEX);
    //Monitor
    Serial.print(" ");
  }
  //Monitor
  Serial.println();

  int16_t raw = (data[1] << 8) | data[0];
  celsius = (float)raw / 16.0;
  //Monitor
  Serial.print("  Temperature = ");
  //Monitor
  Serial.print(celsius);
  //Monitor
  Serial.println(" Celsius, ");
}

When running on UNO Q, the Serial object is to be replaced by Monitor object and the bridge on and the bridge library included.

Output with UNO R3

A8 1 1E F6 1F FF 8 10 C4 
  Temperature = 26.50 Celsius, 
A8 1 1E F6 1F FF 8 10 C4 
  Temperature = 26.50 Celsius, 

Is there anyway to shut-off the scheduler of Zephyr so that it will not supervise the loop() thread? This is to discover that it is Zephyr that interferes with DS18B20's timing functions of OneWire.h Library.

Thanks for doing the experiment, however it is not what I proposed, the disabling has to be done for every DS18B20 call.

The reason for this - per call disabling - is that one of the other calls in the code, e.g. Serial.print might enable the interrupts without being noticed.

If this works I will add disabling into my DS18B20 library internally so the user has not all the hassle. Just like DHTNEW.

(back to my own projects)

Then at which point of the loop() function to place the noInterrupt(); code?

noInterrupts();
issue write/conversion command
issue read command
read scratchpad memory
interrupts();

Patched your code at all places where a call to the oneWire object is made.

#include <OneWire.h>
//#include <Arduino_RouterBridge.h>

OneWire ds(2);  //DPin-2 with 4.7k pull-up

byte data[12];
byte addr[8];
float celsius;

void setup() {
  //Bridge.begin();
  //Monitor
  Serial.begin(9600);
  //-------------
  //Monitor
  Serial.println("Acquiring 64-bit ROM Code: ");
  
  noInterrupts();
  ds.reset();
  ds.search(addr);
  interrupts();

  //Monitor
  /*Serail.print("ROM =");
  for (int i = 0; i < 8; i++) {
    byte y = addr[i];
    if (y < 0x10) {
      //Monitor
      Serial.print('0');  //leading 0
    }
    Monitor.print(addr[i], HEX);
    Monitor.print(' ');
  }
  Monitor.println();*/
}

void loop() {
  noInterrupts();
  ds.reset();
  ds.select(addr);
  ds.write(0x44);  // start conversion, with parasite power on at the end
  interrupts();

  delay(1000);  // maybe 750ms is enough, maybe not

  noInterrupts();
  ds.reset();
  ds.select(addr);
  ds.write(0xBE);                // Read Scratchpad
  interrupts();

  for (int i = 0; i < 9; i++) {  // we need 9 bytes
    noInterrupts();
    data[i] = ds.read();
    interrupts();
    
    //Monitor
    Serial.print(data[i], HEX);
    //Monitor
    Serial.print(" ");
  }
  //Monitor
  Serial.println();

  int16_t raw = (data[1] << 8) | data[0];
  celsius = (float)raw / 16.0;
  //Monitor
  Serial.print("  Temperature = ");
  //Monitor
  Serial.print(celsius);
  //Monitor
  Serial.println(" Celsius, ");
}


I have run the sketch of #29; there is no signal from the sensor.

Again thanks for testing,
So the problem seems not to be in the interrupts.

To dig deeper one has to go to lowest layer of the communication stack. (the wires)
Attach a logic analyzer (or scope) to the pin connecting the UNO-Q to the DS18B20.
Then we can see

  • if the UNO Q sends
  • what the UNO Q sends
  • if the DS18B20 returns the call
  • what is returned.

Do you have a logic analyzer (and time) to do these tests?

@robtillaart

The following AI-assisted bit-banged sketch successfully acquires the full 8-byte ROM code of my DS18B20 sensor for UNO R3. However, the same sketch does not work on the UNO Q platform; even the presence pulse is not detected, which is the very first step in the 1-Wire communication process.

At present, I am experimenting with the reset-pulse timing (Fig-1, #24) as specified in the datasheet. I also tried inserting noInterrupts(), but this appears to worsen the situation rather than improve it.

I would greatly appreciate any advice or insights on this bit-banged issue.

/* =====================================================
   DS18B20 READ_ROM (0x33) using raw 1-Wire protocol
   No libraries
   Single device on bus
   ===================================================== */

#define DQ 2  // 1-Wire data pin

/* ---------- 1-Wire Reset ---------- */
uint8_t onewire_reset(void) {
  uint8_t presence;

  pinMode(DQ, OUTPUT);
  digitalWrite(DQ, LOW);
  delayMicroseconds(500);  // ≥480 µs reset pulse

  pinMode(DQ, INPUT);     // release bus
  delayMicroseconds(70);  // wait before sampling

  presence = !digitalRead(DQ);  // LOW = presence pulse

  delayMicroseconds(410);  // finish timeslot
  return presence;
}

/* ---------- Write single bit ---------- */
void onewire_write_bit(uint8_t bit) {
  pinMode(DQ, OUTPUT);
  digitalWrite(DQ, LOW);

  if (bit)
    delayMicroseconds(6);  // write '1'
  else
    delayMicroseconds(60);  // write '0'

  pinMode(DQ, INPUT);  // release bus
  delayMicroseconds(64);
}

/* ---------- Read single bit ---------- */
uint8_t onewire_read_bit(void) {
  uint8_t bit;

  pinMode(DQ, OUTPUT);
  digitalWrite(DQ, LOW);
  delayMicroseconds(6);

  pinMode(DQ, INPUT);  // release bus
  delayMicroseconds(9);

  bit = digitalRead(DQ);  // sample
  delayMicroseconds(55);

  return bit;
}

/* ---------- Write byte (LSB first) ---------- */
void onewire_write_byte(uint8_t data) {
  for (uint8_t i = 0; i < 8; i++) {
    onewire_write_bit(data & 0x01);
    data >>= 1;
  }
}

/* ---------- Read byte (LSB first) ---------- */
uint8_t onewire_read_byte(void) {
  uint8_t data = 0;

  for (uint8_t i = 0; i < 8; i++) {
    data >>= 1;
    if (onewire_read_bit())
      data |= 0x80;
  }
  return data;
}

/* ---------- Arduino setup ---------- */
void setup() {
  uint8_t rom[8];

  Serial.begin(9600);
  Serial.println("DS18B20 READ_ROM (No Library)");
  Serial.println("--------------------------------");

  if (!onewire_reset()) {
    Serial.println("No DS18B20 detected!");
    return;
  }

  onewire_write_byte(0x33);  // READ_ROM command

  for (uint8_t i = 0; i < 8; i++)
    rom[i] = onewire_read_byte();

  Serial.print("ROM Code: ");
  for (uint8_t i = 0; i < 8; i++) {
    if (rom[i] < 0x10) Serial.print("0");
    Serial.print(rom[i], HEX);
    Serial.print(" ");
  }
  Serial.println();

  Serial.print("Family Code: 0x");
  Serial.println(rom[0], HEX);
}

/* ---------- Arduino loop ---------- */
void loop() {
  // Nothing to do
}

@GolamMostafa

Lets start to verify something small and basic.

void setup()
{
  Serial.begin(115200);
  while (!Serial);

  uint32_t start = micros();
  delayMicroseconds(10);
  uint32_t stop = micros();
  Serial.println(stop - start);
  delay(100);

  start = micros();
  delayMicroseconds(100);
  stop = micros();
  Serial.println(stop - start);
  delay(100);

  start = micros();
  delayMicroseconds(1000);
  stop = micros();
  Serial.println(stop - start);
  delay(100);

  start = micros();
  delayMicroseconds(2000);
  stop = micros();
  Serial.println(stop - start);
  delay(100);
}

void loop()
{
}


Of course this is not a good test, as the delayMicros might use the same clock.
But it is a quick one.

Better would be to measure the delayMicroSeconds with a pin HIGH LOW and let an UNO R3 interrupt measure the time.

Hello

I am also intrested to use DS18B20 with Arduino UNO Q and stumbled into this thead. I used Arduino Pro mini clone and got temperature readings from DB18B20. So I tryed the same code with Arduino UNO Q. I used Arduino IDE 2.3.7 to compile and upload the code. I got no temperature measurements.

I wired a clone of Saleae logic analyser to the dataline of DS18B20 and managed to get the same init line pattern as in post #24 with UNO Q. After that I didn't see any traffic at all in DS18B20 data line.

I tested robtillaarts code in post #33. First the original code and then noInterrupts/interrups added around delayMicroseconds().

  • stop - start time as microseconds:
    delayMicroseconds Original with noInterrupts/interrups
    10 116 165
    100 200 200
    1000 1100 1100
    2000 2100 2100

It looks like the real microseconds = 100 us + delayMicroseconds().

I made pulses to pin 10.

digitalWrite(10,HIGH);
delay(10);
digitalWrite(10,LOW);
delayMicroseconds(10);
digitalWrite(10,HIGH)

I managed to measure almost the same delays with Saleae logic analyzer as in table above. So I suspect that Zephyr delayMicroseconds() timing is broken.

@hannupul

Thanks for doing the tests. It seems to prove my theory that the low level timing is not OK..

First I thought timing was disrupted by interrupts, and as disabling those did not help I suspected the timing itself. Therefor I proposed to measure the delays.

So the next step is to get the source code of the delayMicroseconds() to see if there are “gremlins at work”.

Again thanks for testing,

@GolamMostafa

Can you confirm the test of delayMicroseconds?

As the oneWire lib uses delayMicrosenods too, this 100us extra disrupts the protocols.

@hannupul

Could you do a similar test for delay() to see if it looses ~100 micros in different calls?

this code here I believe is what you seek..
looks like it calls a zephyr function, maybe some wrong config somewhere??
~q

Thanks for the code link

Both delay and delayMicroseconds call a sleep function. This makes me think that it actually does a context switch, causing the extra 100 us.

Next step could be an implementation based on micros()

uint32_t start = micros();
while (micros() - start < param);  //  empty loop

In short active polling of micros until ready.

(updated the code block to something more readable ;)

1.

I am trying to generate the following RESET signal (Fig-1) for the DS18B20 sensor from Zephyr's kernel clock using the k_timer class. I asked for 500 us, the k_time has retrned 496 us. (Pls, see Section-2).


Fgure-1:

2.
OUTPUT:

Pin went HIGH at (start): 71845707 us
Pin went HIGH again at (end): 71846203 us
LOW duration (measured): 496 us
-----------------------------
Pin went HIGH at (start): 72937707 us
Pin went HIGH again at (end): 72938203 us
LOW duration (measured): 496 us
-----------------------------

3.
Sketch: (run under IDE 2.3.7)

#include <Arduino.h>
#include <zephyr/kernel.h>
#include<Arduino_RouterBridge.h>

#define PULSE_PIN 2   // DPIN-2 (UNO Q)

static struct k_timer pulse_timer;
volatile bool pulse_done = false;

/* Timestamp storage */
volatile uint32_t t_high_start_us = 0;
volatile uint32_t t_high_end_us   = 0;

/* ---------------- Timer callback ---------------- */
void pulse_timer_handler(struct k_timer *timer)
{
    digitalWrite(PULSE_PIN, HIGH);          // Return HIGH
    t_high_end_us = micros();               // Time when pin goes HIGH again
    pulse_done = true;
}

/* ---------------- Generate pulse ---------------- */
void generate_500us_low_pulse(void)
{
    digitalWrite(PULSE_PIN, HIGH);
    t_high_start_us = micros();              // Pin went HIGH (initial)

    digitalWrite(PULSE_PIN, LOW);            // Pull LOW
    k_timer_start(&pulse_timer,
                  K_USEC(500),               // LOW for 500 µs
                  K_NO_WAIT);                // one-shot
}

/* ---------------- Arduino setup ---------------- */
void setup()
{
    Bridge.begin();
    Monitor.begin();
    delay(5000);
    
    pinMode(PULSE_PIN, OUTPUT);
    digitalWrite(PULSE_PIN, HIGH);

    k_timer_init(&pulse_timer, pulse_timer_handler, NULL);

    Monitor.println("UNO Q: 500us LOW pulse test");

    generate_500us_low_pulse();
}

/* ---------------- Arduino loop ---------------- */
void loop()
{
    if (pulse_done)
    {
        pulse_done = false;

        Monitor.print("Pin went HIGH at (start): ");
        Monitor.print(t_high_start_us);
        Monitor.println(" us");

        Monitor.print("Pin went HIGH again at (end): ");
        Monitor.print(t_high_end_us);
        Monitor.println(" us");

        Monitor.print("LOW duration (measured): ");
        Monitor.print(t_high_end_us - t_high_start_us);
        Monitor.println(" us");

        Monitor.println("-----------------------------");

        delay(1000);     // repeat every 1 second
        generate_500us_low_pulse();
    }
}

4.
Someone may try to read DS18B20 through this I2C to 1-Wire converter (Fig-2). This is to ensure that there is timing problem in the context of UNO Q.


Figure-2:

Output (run on UNO Q IDE 2.3.7)

126    expected: 10
199    expected: 100
1100   expected: 1000
2100   expected: 2000

My results agree with the results of #34.

However, k_timer based timing (#39) is much better only with - 4 us offset.

insightfull.

(to be continued)
Thanks for testing!


@GolamMostafa

Can you test the delay() functions if it also has an offset of ~100 us?

Just as you confirmed the delayMicroseconds ?


@ptillisch

Please note that the failing delayMicroseconds() on the UNO Q is confirmed.
So the hypothesis is now the following chain

delayMicroseconds fails => oneWire timing fails => DS18B20 fails.


@GolamMostafa @qubits-us

Can you replace the delayMicroseconds() in your local copy of zephyrCommon.cpp?

(do not forget to comment the old code as backup)

This is a first try to see if and by how much the function can be improved.

void delay(unsigned long ms) {
	k_sleep(K_MSEC(ms));
}

// void delayMicroseconds(unsigned int us) {
// 	k_sleep(K_USEC(us));
// }


void delayMicroseconds(unsigned int us) {
  //  ignore small values 
  if (us <= 1) return;

  //  optional adjust loop here

  // start the clock
  uint32_t start = micros();
  while (micros() - start < us)
  {
    //  empty loop
  }
  return;
}

Please notice delay(unsigned long) versus delayMicroseconds(unsigned int)

Don’t know the size of int and long on the UNO Q,

I propose to make both parameters uint32_t as that is defined in size.