Non-constant delayMicroSeconds timing issues

Hi,

I was trying to run a simple code to test the accuracy of delayMicroseconds on the Argon and it seems like the delay is not very consistent.

Here is the code that was used to test this:

SYSTEM_MODE(SEMI_AUTOMATIC);
int COM = D4;

// setup() runs once, when the device is first turned on.
void setup() {
  // Put initialization like pinMode and begin functions here.
  noInterrupts();
}

// loop() runs over and over again, as quickly as it can execute.
void loop() {
  // The core of your code will likely live here.
  int time_start = micros();
  //digitalWriteFast(COM, HIGH);
  delayMicroseconds(500);
  int time_finish = micros();
  int time_taken = time_finish - time_start;
  Serial.println(time_taken);
}

The result of this test is:

Is there any setting that I must configure the photon to make delayMicrosecond work more consistently?

Turning off interrupts in setup() won’t work. Either the system will come to a complete halt, which does not appear to have happened, or something turned them back on again. You should only turn off interrupts for brief periods. In your test, surrounding the precision timing code from before time_start to after time_end only. You code is almost certainly running with interrupts enabled.

Part of the timing error is caused by micros() not being completely stable, and also the latency to execute it. The best solution for that is to use the GPIO and monitor the timing externally using a logic analyzer or oscilloscope.

However, the underlying problem is that it’s impossible to do precision timing on the nRF52, because interrupt latency is very unpredictable. Various parts of the system in particular the BLE radio run at high interrupt priority.

If you need precision timing of input or output waveforms you need to use the nRF52 hardware directly. For example, reading DHT22 sensors without timing loops.

Thank you for your reply! I find micros being unstable quite odd because I was trying out the same code on an Arduino and it wasn’t an issue there. Hence, I figured that the argon has potentially other things running in the background that is causing these problems.

That said, do you have any good recommendations on any reading materials that would allow me to disable all other parts of the Argon system to make it mimic an Arduino?

Is it also possible to permanently disable bluetooth as well?

The Argon has a very large number of things running in the background. Disabling them would also disable the cloud connection, Wi-Fi networking, BLE, some USB host functions, basically everything that makes the Argon have more functionality than an Arduino.

If you use MANUAL system mode and do not enable Wi-Fi or the cloud connection, that will help. Also call BLE.off() to make sure BLE is off.

However it’s better to either design the timing-sensitive code to use the nRF52 hardware directly when possible, or offload it to a separate coprocessor for timing-sensitive code. I usually use a Microchip PIC as a coprocessor because they’re inexpensive and I happen to be familiar with them.

2 Likes