timing glitch - real or instrument?

I may have to borrow my girlfriend’s oscilloscope unless any one can explain…

This MRE should produce a constant frequency output. It is ripped from a larger project and while it does not seems to be the problem in the “real” project (dim last column of a matrix of LEDs), it does exhibit some odd behavior.

What I see: every 10 seconds or so, rather than 166.0 Hz on my cheapy freq meter I see a few readings go by that are a few Hertz greater, like

166.0 168.8 167.3 168.8 166.0

then back to 166.0. The meter publishes a new value about I am guessing 3-5 per second.

You can see by the commented out lines what I thought of. It doesn’t look like

  1. Serial output
  2. anything about 13 LED_BUILTIN
  3. nothing in main(), as I capture attention in loop and never return.

If it was one odd reading every so often I would think it was some kind of phase issue between my meter’s period of measurement and exactly where the synthesized wave was, but the several odd readings in a row are baffling me.

Maybe you have a better meter you could throw on there, or get out a damp trout and explain the error in my logic.

//# define IDLETIME 13  /* lamp on during leftover time */

# define IDLETIME 3  /* lamp on during leftover time */
# define MRATE  6     /* run loop code every MRATE mS */

unsigned long lastTick;
void setup()
//  Serial.begin(115200);
//  Serial.println("Jello Whirled!");


  lastTick = millis();

void loop()
  for (; ; ) myLoop();

void myLoop()
  unsigned long tempTick;

  if ((tempTick = millis()) - lastTick < MRATE) {
     digitalWrite(IDLETIME, HIGH);

  lastTick = lastTick + MRATE;

//  lastTick = tempTick;

  digitalWrite(IDLETIME, LOW);


void task()
//  Serial.println(lastTick);



i ran your code and put a scope on the output.

i saw the pulse width alternate between 5 and 6 msec.

i saw a steady waveform when I set MRATE to 6000 and used micros()

I have repeated your experiment.

I am guessing that this makes the "problem" 1000 times harder to see, perhaps as a practical matter invisible.

With the millis() version posted above, adding reporting to task() shows a pattern of 7 or 8 pulses that are around 6140 micros leading edge to leading edge, followed by just one that is around 5120.

Over the long term, it averages 6000 uS as it must.

I will go to the trouble of looking at it ('scope) when I get a chance. Meanwhile there are a few places where I will switch to micros with 1000x values.

I wonder if I even knew about micros() before, I am certain I would not have thought to try it.

Alligator down. Learnt something. I only wish it had had anything to do with the damn swamp.

Thank you!