Site and Contents © 2020

Don’t do delay…

 
26 Oct

I’ve been working with Arduinos and AVR chips for a few years now in my projects, and one thing I’ve found with all of them if using the ADC for continual reading in conjunction with some form of output switching on a pin (say driving an LED or an opto-isolator) is that I’m not too keen on how by using a delay call whilst triggering something makes a mess of the ADC readings after the delay is called.

Most of the time, it’s not a lot of an issue, but the whole process of restarting the ADC, the power fluctuations and then the garbage in the ADC frustrates me a little when it comes to building high speed triggers like I use for my stuff. Probably wouldn’t affect a lot of other people, perhaps most don’t notice it, but occasionally other folk have mentioned it to me.

In simplistic terms a triggering routine on an AVR (I say simplistic, this is basic Playground level) would look something like this.

void trigger(int _triggerPin, int _inPin){
  digitalWrite(_triggerPin, HIGH);
  delay(100);
  digitalWrite(_triggerPin, LOW);
  delay(50);
  analogRead(_inPin)
}

Sure, it works, it’s a bit slow calling the digitalWrite, but I’m not looking at the digitalWrite here, I’m more concerned with the analogRead and what data I’m getting off there. In the end I sat around and thought about this for a while, and came to the conclusion that the ADC didn’t need to be stopped, nor restarted, and that it could stabilise whilst taking the place of the delay() function.

Sure that’s not going to put a man on the moon, but in something like a thunderstorm where it’s possible to get a couple of strikes with only part of a second difference, shaving a few millis off here and there is a big difference!

Here’s what I came up with.

The trigger() function I’ve got here is pretty much the same as above, but notice that the delay() has been removed and replaced with a function called pauseAdc(), the millisecond timings are a tad shorter (reason for that is depending on how the ADC is set, the reads could take it over the wait limit; nothing is perfect, always a compromise).

void trigger(int _triggerPin, int _inPin){
  digitalWrite(_triggerPin, HIGH);
  pauseAdc(_inPin, 50);
  digitalWrite(_triggerPin, LOW);
  pauseAdc(_inPin, 25);
}

And the pauseAdc() looks like this… If you notice I’ve called a long _now with the current millis() call in that, as well as recalling it in the while() statement as some functions will make a mess if called within another function or conditional.

void pauseAdc(int _inPin=A0, int _mSec=100){
  //Attempts to keep the ADC running and clean, replacing the delay() function.
  unsigned long _now = millis();
  unsigned long _end = abs(_now+_mSec);
  while(_now < _end){
    _now = millis();
    analogRead(_inPin);
  }
}

Share This Post :