Internal timing

So, I’ve been working on running a sequencer in my Yaeltex firmware, by tapping into the main loop and counting micros. It works pretty well, but I can hear a bit of clock jitter. Once I get save-to-EEPROM working, I noticed the clock slowed down for a second while writing. So I rewrote it to do a better job of catching up if it gets behind.

However, I finally noticed that my clock is just slow. It’s fairly consistent, with a little jitter, but something like 10% slow. I did some reading and I guess the micros() function is not based on a realtime clock but processor cycles? So if the arduino gets busy, it may lose track. Is that right?

So my question for you is: is there any way for me to build an internal clock that keeps reasonably accurate tempo? In timer.ino, the comments say it’s tied to an interrupt at a certain sample rate – can I tap into that? can I calculate the clock rate and count timer loops to know how much actual time has passed or something?

Hello @mike!

The timing in a controller like this (which was not thought from the start to have precise timing) can be tricky.

The priority of the timer interrupt is the highest possible (see timer.ino line 76)

The timer that checks the MIDI buffer should be working every 1/7000 seconds.
This is set by the sampleRate variable you find in setup.ino.

If you set it for example to 5000 to have an interrupt every 0.2 ms for example.
You can check this having a counter increase inside this interrupt and then on the loop print every second with the micros() function.

 static uint32_t antMicrosTest = micros();  

  if(micros()-antMicrosTest > 1000000){
    SERIALPRINTLN(countTimer)
    countTimer = 0;
    antMicrosTest = micros();
  }

Using a similar hardware configuration to HACHI, I get 5000, 5001, 5003, 5000, 5004, 5001… Not perfect, but this depends on the exact moment the loop runs and does this check.
You could check this variable inside the timer function to have different timing events, but be careful to not place any heavy code inside the interrupt.
You should only set flags to be checked by the loop code (or functions).

With a jitter of 0-4 counts you get 0-0.8 ms error in timing, which is not perfect but it’s something to start with.

Maybe try that and from your results we can keep working to improve it!

thanks for the tips. I’ll experiment with that when I try to get internal clock working.

but for the moment I shifted to external sync, figuring I can always feed hachi a clock from somewhere else. but I implemented that and it’s really jittery. I’ve just been finding though that if I turn off all feedback, it’s reasonably solid, but as soon as I try to light up LEDs, it gets jittery again.

What I’m doing right now is:

  • in handleClockUSB in comms.ino, I increment a pulse counter
  • in the hachi loop (which is called from the main loop), I check if the pulseCount > 0 and, if so, do my clock pulse stuff (i.e. send midi notes, light up LEDs etc) and decrement the pulseCount

If I take all the LED updates out of my code, the timing is ok. but otherwise, nope. I was thinking about saving the LED updates for the next clock cycle. so when I get a pulse, I do all my timing critical stuff like sending out midi notes, and then I set some flags for what needs to be updated and on the next loop I check the flags and do the updates.

but it seems to me like your code is already essentially doing that – in feedback.ino you buffer up changes and then send them when you have enough or 5ms passes. so I’m not sure waiting for the next cycle would do much.

maybe I’m just trying to update too many buttons? I’m a little dumb about the updates, basically just cycling through certain rows and setting the colors without checking to see if the color is already set. I’m not sure if your code knows when something has changed.

1 Like

One question: if I send two updates for the same button to SetChangeDigitalFeedback(), will it know it’s a duplicate? it looks to me like it just adds the change to the end of the update buffer (though I don’t see how feedbackUpdateWriteIdx gets incremented)

should I be keeping track of my own button states so I know which ones actually need to change and which are fine, and just send one message to feedback?

Update: I modified my LED-lighting-up code to keep track of the current state of all 188 buttons and only call SetChangeDigitalFeedback if it’s changed. That’s really helped solidify the timing, which is good.

I’m having some other issues, but nothing I can’t figure out… eventually.

2 Likes