As soon as you move your sequencing code out of the main loop and trigger it via the timerinterrupt, the speed of the main loop does not interfere with the sequencing code.
I had the multiplexer read every single loop. If I remember correctly, there were some very short delays in there to slow it down to work correctly. I just looked at the Control_Surface Library, how he did access the multiplexer.
If you want to work with timings, that you calculate yourself, elapsedMillis and elapsedMicros is a very good solution, so you dont have to do all that millis() and micos() calculation yourself all the time.
Code:
elapsedMillis em;
void loop() {
if( em >= 1000) {
// Do what every you want to do every 1000 milli seconds
em = 0;
}
}
I just read your other thread and it's pretty impressive that your clock is more tight than the ones from your other machines!
Yeah, I wondered myself too. I think one of the reasons is, that most of the other devices do way more than "just" sequencing, and a lot of them use way slower MCUs as the Teensy4.1 has.
But that IntervalTimer seems to be very accurate. I am missing devices to see, if a microsecond there is really a microsecond, but non of the tools I had (Hardware and DAWs) or was able to lend was showing any jitter.
And it is so easy:
Calculate the microseconds between every pulse. (BPM is quarter notes per minute, a Minute as 60 million microseconds, so a quarter note takes 60.000.000 / BPM microseconds. Devide that by your resolution (PulsesPerQuarterNote, in my case 192) and you have the amount of microseconds you need to wait between every pulse.
So there is a IntervalTimer somewhere. Than you have a callback function, that is called, when the interrupt occurs. And than you start it with the microseconds you calculate and update it, when you change the BPM.
Code:
// used variables
IntervalTimer pulseTimer;
uint16_t microSecondsPerPulse =MICROSECONDS_PER_SECONDS / bpm / PPQN;
// callback method
void onPulseTimer() {
Sequencer::pulse();
}
// start the timer
pulseTimer.begin(onPulseTimer, microSecondsPerPulse);
// update the timer if the bpm changes
// first recalculate the microSeconds
microSecondsPerPulse = MICROSECONDS_PER_SECONDS / bpm / PPQN;
pulseTimer.update(micoSecondsPerPulse);
This is pseudo code, I wrote down here to explanation. You should check for datatypes etc. Defines are missing, etc.
I use the Raspberry Pi Pico for everything, that I don't need that much power, because its 3.99€ shipped from a shop a few cities away. No need to spare a few bucks for a Arduinoclone that is slower and might not work correctly from china there