I've been developing some codes that drive a 433MHz transmitter, and I ran into an issue with the Arduino Uno R3 with regard to either "delayMicroseconds()" or "writeDigital()" or the two working in combination.
I generate a pulse train by using writeDigital() to turn on, then off, the voltage for on-off keying (OOK) transmissions by a 433MHz transmitter. For certain timing patterns, the pulse timings generated by the Uno are incorrect.
The problem occurs when I want to hold the output voltage HIGH for more than about 500 microseconds. When I attempt that, the HIGH is held for only about 524us maximum, and the LOW is extended by 100's of microseconds.
I generated some code (below) to isolate the problem from the larger program. The code runs on both the Uno and the Pico2, and the Pico2 does not exhibit this problem. So I think the issue is with my misunderstanding of either the Uno architecture, the Arduino IDE's compiled code, or the library code for either "delayMicroseconds()", "writeDigital()", or some interaction between the two that I don't understand.
The tables below show the results of running the code on both the Uno and the Pico2. The code times the actual loop durations with "micros()" and reports them. rtl_433 monitors the RTL-SDR dongle and records the signals received. The tables show the internally recorded times for the Uno and for the Pico2, and then the results for both as seen by rtl_433. The original code (emulating a Lacrosse TX141 remote sensor) worked fine on the Pico2 (rtl_433 recognized the device with no issues), but transmissions from the Uno weren't recognized at all.
Variations of 10-20 microseconds are acceptable, so my concern is not that a pulse that should be 400us is actually 412us. My concern is that a pulse of 500 high/500 low works fine (512/504 is OK), but that a pulse of 700/700 gets changed into 528/892 !.
I'm running
Arudino IDE Version: 2.3.6,
Date: 2025-04-09T11:22:51.016Z
CLI Version: 1.2.0
on Mac Mini M2, Sequoia 15.5.
Have I stumbled into a known issue? Is there a workaround?
Or is there a flaw in my code or my thinking?
Times as reported by Arduino Uno
15:17:46.240 -> For delay = 100us, actual time was 105.96us
15:17:47.260 -> For delay = 200us, actual time was 206.40us
15:17:48.284 -> For delay = 300us, actual time was 307.16us
15:17:49.340 -> For delay = 400us, actual time was 407.76us
15:17:50.363 -> For delay = 500us, actual time was 508.28us
15:17:51.448 -> For delay = 600us, actual time was 608.84us
15:17:52.505 -> For delay = 700us, actual time was 709.52us
15:17:53.589 -> For delay = 800us, actual time was 810.24us
15:17:54.675 -> For delay = 900us, actual time was 910.76us
Times as reported by Raspberry Pi Pico2
15:54:00.558 -> For delay = 100us, actual time was 100.49us
15:54:01.576 -> For delay = 200us, actual time was 200.49us
15:54:02.630 -> For delay = 300us, actual time was 300.48us
15:54:03.649 -> For delay = 400us, actual time was 400.48us
15:54:04.705 -> For delay = 500us, actual time was 500.48us
15:54:05.761 -> For delay = 600us, actual time was 600.49us
15:54:06.849 -> For delay = 700us, actual time was 700.50us
15:54:07.937 -> For delay = 800us, actual time was 800.48us
15:54:09.026 -> For delay = 900us, actual time was 900.52us
Times as reported by RTL_433 ("Recv'd")
Note Uno results at markers :51, :52, and :53
ARDUINO UNO RPi Pico2
Time Recv'd Recv'd Recv'd Recv'd
Time Req'd by High Low High Low
Marker Program Pulse Pulse Pulse Pulse
:46 100us 120us 92us 112us 84us
:47 200us 212us 200us 200us 196us
:48 300us 316us 300us 300us 300us
:49 400us 416us 400us 400us 400us
:50 500us 512us 504us 496us 500us
:51 600us 524us 692us [garbled]
:52 700us 528us 892us 696us 700us
:53 800us 528us 1092us [garbled]
:54 900us [garbled] 900us 896us
[garbled] means the message wasn't received because of
other simultaneous broadcasts in the neighborhood.
The code:
# Arduino Uno R3 or RPi Pico2
#define TX 3
void setup(void) {
Serial.begin(9600);
pinMode(TX, OUTPUT);
delay(1000);
digitalWrite(TX, LOW);
delay(1000);
Serial.println("Testing delayMicroseconds");
};
void loop(void) {
unsigned int times[] = {100,200,300,400,500,600,700,800,900};
int i, j;
unsigned long before, after;
int pulses = 50;
for (i=0; i<9; i++) {
after = 0;
for (j=0; j<pulses; j++) {
before = micros();
digitalWrite(TX, HIGH);
delayMicroseconds(times[i]);
digitalWrite(TX, LOW);
delayMicroseconds(times[i]);
after += (micros() - before);
};
Serial.print("For delay = ");
Serial.print(times[i]);
Serial.print("us, actual time was ");
Serial.print(after/(2.0*pulses));
Serial.println("us");
delay(1000);
};
delay(30000);
};


