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.