Still, I have checked the whole code and I still don't understand why it would crash anything just by messing out with one variable that only micros() uses.
The one multibyte variable is shared with an interrupt service routine. To obtain the micros value, the variable is combined with a hardware register. Your reset code ignores both of those very important elements.
Even if you do correctly reset the value, if you ever add a library that uses millis or micros the library will behave erratically when the value is reset.
Guys, I'm learning, and yes, this is not commercial, just trying to learn something new. So, please, don't be so hard on me.
It isn't about being hard, it's just that you change things on your system that are internal to the library and not expected to be modified. Sometimes such things are needed, but usually you should do these kind of things if the benefits outweigh the risks by a large margin and you understand the ramifications. The second is definitely not the case and I have my doubts about the first one.
Bad ideas won't get any better by pampering egos. Better learn to do things correctly, even if you don't have to.
Now, before you go out and get more lipstick to paint on your sow, you should take a step back and refocus on the problem you're trying to solve, what are the current problems and the expected improvements and how to measure or verify it. Then you can check if the current way passes those tests or if not, what are better alternative solutions. That would be a more professional way of doing it, where you gather facts on how well your solution works and you don't have to rely on hopes, wishes, religious beliefs or voodoo.
Got it, thanks guys, yesterday I was in a bit of a bad mood. :-[
I will check the 16 bit timer and see if maybe that would solve my problem. In any event, the MyTimer lib I created also works out. I just need to check if its good enough for a MIDI Clock PPQ at 96 PPQ...
If one might ask, what is this problem that leads you mess around so much with timers? For music, useful beats usually don't exceed 300 bpm which are rather puny 5Hz. You can usually deal with those without the need to resort to all those rigmaroles.
Ok, new idea, to create the Timer1, which is 16 bits, and have it deal with PPQ. Outside the timer I check which will be the next data to be sent out, and put in a small buffer. When the Timer1 happens, it checks the small buffer and sends midi-out. I just hope it doesn't block the previous PPQ. So I guess I need to time how many midi-notes I can send per PPQ before the next Timer1 call happens. Maybe for now I will leave as one note only, or something like that. Them I start messing around with the buffer size.
120 BPM means 120 Beats, each Beat has 96 pulses.
120 x 96 = 720 events per minute = 12 hz. (if my math is right)
In any event, thanks guys, I learned A LOT from all this talk.
Sorry to bother so much this forum. When I first started working with C++ and Assembly, I also had the same crazy ideas and people made fun of me. It was over 10 years ago, and look where I am now. www.Wusik.com
So I guess I just need a few more years ahead of me in all this Arduino talk. :-[ :-X
Still, we're not even close to problematic timings. If you'd be talking about 12000Hz that would be a problem, but anything below 1000Hz is well in the comfort-zone of your Arduino where you don't have to worry much. So again, what is failing at 12Hz?
Good question. To be honest, all was working the way I did, it was just the problem with micros() overflowing. But after I learned about Timers, I had this idea of using a timer and not having to worry about things anymore. As there is a problem I have to check, as my project uses a lot of other things that takes time to process. So the PPQ clock could get late and make the midi sequence drift in time, which is bad.
For instance, the SD Card reading and writing takes time to process, and its done a lot, as all the MIDI data is stored in the SD Card.
But anyway, I will do more tests and see what happens now.
Thanks again for all the great help. I'm sure I will do stupid things in the way, and maybe a year from now I will fix those stupid things... But at least it will work! ;D
So the PPQ clock could get late and make the midi sequence drift in time, ...
Could or Does? Also, if you don't accumulate errors but always resync on the beat, some PPQ might be slightly off due to rounding, but the error will even out. No matter what you do, those errors will be present, the interesting part is to make them not matter. As an advanced topic, you could make sure the rounding errors get spread in a most even and balanced manner over the PPQ intervals so they're least perceptible. For this one can apply the algorithms designed by Bresenham in the 1960ies for line drawing on raster displays.
Ok, I took some time to figure out how exactly timers work out and how to use them for my project. It does look much better now, I used portions of the Tone code.
Now a question. What happens if my code takes too long inside an interrupt? How can I check if that happened?
As in ...
ISR(TIMER2_COMPA_vect)
{
// CRAZY long code //
unsigned long iou = 0;
for (unsigned long pp=0; pp<99999999; pp++) { iou += pp+12; }
}
I know the code should be short. But I need to know how can I check if I made something too complex for the HZ calls I'm doing.
I'm pretty sure this is yet another stupid thing I'm doing, so, please, bear with me while I learn this up.... and thanks again for helping me out.
AHHHHH!!! I just finished up my new MyTimer Library plus 2 Examples. One is a Midi Clock at 960 PPQ, and it works great! Doesn't miss a pulse at all. I played it into my notebook and its perfect. The clock is like 0.1% slower than what other clocks I tested, but that's why they created MIDI-Sync messages for. In any event, this is a MASTER clock, so I don't really care if its 0.1% slower than other devices BPM clocks.
I uploaded a new ZIP file and will also post the new examples here.
Even in cases of overflows, endtime-startime will always be the correct elapsed duration, as long as the types of endtime and starttime match the the type returned by your counter, which means unsigned long for millis() and micros().
If you start adding durations to timestamps or comparing timestamps with each other, your program will fail because of the overflow.
The sane conclusion to this is to only use code such as:
Even in cases of overflows, endtime-startime will always be the correct elapsed duration, as long as the types of endtime and starttime match the the type returned by your counter, which means unsigned long for millis() and micros().
A correction... The variable types do not have to match the type returned by the function. Any variables used must be unsigned and should all be the same type.
For example, this works for ranges up to 255 milliseconds...
unsigned char Previous;
unsigned char Current;
void setup( void )
{
Previous = millis();
}
void loop( void )
{
Current = millis();
if ( Current - Previous >= 100 )
{
// This runs every 100 milliseconds
Previous = Current;
}
}