So I was just playing around with timer driven interupts and a basic error handler. Everything behaved as expected untill I added a while loop. So the program that behaved included a timer driven interupt calling a function for three seconds when the function would run the errorhandler that stopped it. The code is bellow:
thanks for the input. I am still learning and self teaching so I think there are a lot of standard practices that I am missing out on having not learnt in uni.
AWOL:
This interupt was not intended to do serial output in the end. It's intended to to servo position updating for path following. I was just doing serial output to test out that the interrupt was working as I expected. However, no, i didn't know that it's a bad idea. What is the reason behind it?
PaulS
I was wanting to infinatly print the msg for when I eventually disable the auto reset due to serial connections. I was wanting to just connect the Serial in the event of an error (see the light flashing) to find out the exacts. Can you suggest a better way?
However, whether it is the better way or not, I was still curious as to why the while loop was unable to blink the LED or print the error msg as expected. I kinda felt it was a gap in my knowledge, one which I was unable o figure out by googling. Any ideas?
Thanks a heap for your input btw, i am trying to learn fast and these forums and all the people on them have been great.
My project is to develope a walker. This walker will eventually consist of four legs, each controlled by three servo’s. Currently I am just working on one leg in 2D (just two of three servo’s). I will make it more complex slowly as I get each step working properly as I expect.
I do use the servo library to do the controlling of the servo’s. Example bellow, this is a function I wrote to just throw a bit of sa:
I then progressed this and created a function that took intended coordinates,figured out the required servo positions and set them.
I am now working on a set of functions that will take a linear path from A to B over an aloted time and guide the foot along that path. To do this I not only need the servo’s signal repeating via the servo library but I also need the servo position to be repeatedly recalculated by a repeating function.
My thinking for doing this was to have a recalulating function called at roughly 20hz by a software interupt.
Does this make sence? Does it seem like the best way of doing this?
My end effector code is bellow:
void TwoDLeg::setEEPos(int y, int z)
{
double cSQRE = square(y) + square(z);
double cosC = (aSQRE + bSQRE - cSQRE)/(2d2d3);
double C = acos(cosC);
double theta = atan2(y,z);
double c = sqrt(cSQRE);
double cosB = (cSQRE + aSQRE - bSQRE)/(2cd2);
double B = acos(cosB);
theta = theta * (360/(2M_PI));
B = B * (360/(2M_PI));
C = C * (360/(2*3.14));
int uncheckedS1 = round(theta + B);
int uncheckedS2 = round(C-90);
// Need a safety check in here to check position is obtainabl
Never have more than a couple of lines of code in any interrupt handler because another interrupt can always interrupt your interrupt handler and while loops here hijack the processor
eg.micros() depends on a timer0 interrupt with a resolution of 4us - so it is running 250000 times a second . Your serial communication function is much slower... and you are adding another loop you get the idea what is happening .
the right way to handle an interrupt is to set some global flag like variable in the interrupt handler and exit immediately
in your main loop, examine the value of the variable every cycle and do your serial.whatever() from here. In this case , the processor will keep track of your code even when timer0 occurs and your code will execute properly
Ah... you're right... my bad...the millis() and micros() depends on an interrupt handler that catches timer0 overflow and it IS much slower... only about 976 times a second with 64 prescalar.
Most of the other observations are still valid though
srinathdevelopment
Ok, so I was going to use an interrupt to change the variables every 50 ms. However, what your saying is that every interrupt I add increases the chance that another interrupt will fail to execute. That is correct?
So, you were saying that I should update the variables in the loop function and just set a global flag variable that the seperate interrupt should then update them for the Servo function to use?
If that is so, would it be a better option yet to just run the position update every loop and update the servo positions directly from there? Reasons being:
it is one less interrupt running
I will get a more accurate update of the Servo positions as there will always be a lag between when the positions are recalculated and when they are updated by the timer interupt for use by the Servo library.
Does this sound right?
Cheers,
David
P.S. I am still not sure why my original while loop did not work (see first post in this topic)?
The Serial.print commands just queue up the messages, and they're printed via ISR. The easy not-actually-fixing-the-problem solution is to call the interrupts() (or sei()) function right before going into the infinite loop. Having an infinite loop in an ISR doesn't hurt the processor or anything if it's going to be reset anyway.
Regarding your bigger question on do you need to use interrupts at all, i've found that it's usually necessary to use interrupts only in these circumstances -
1. You have a highly time critical response need (within microseconds)
In this case, you mentioned somewhere you're looking at 50ms or so timing - so this may not be critical
2. Your loop function spends much time doing something else & cannot monitor whatever you want with adequate frequency
Recall that the Arduino Uno processor is running at 16 Million processor instructions per second - so even if 10 lines of C code translate into 500 processor instructions on compilation (loops add more of course :)), this has still taken only 32 microseconds
3. You are depending on some micro-processor peripheral which works on interrupts
In my experience on ATMEGA peripherals like TWI & Timers, there are usually options to avoid interrupts which product blocking but simpler code.
If you don't have these needs, it's likely that simply doing what you want in the loop function is sufficient and will simplify your code.
PS - would be great if others can provide more areas in which using interrupts has benefits, since i have relatively limited experience on interrupt programming, it's likely i'm missing some circumstances
I understand that the while loop prevents the continuation of the usual programming loop. However I would have thought that interupts would still be enabled during the while loop and hence they would be able to run. Why does a while loop disable the trigering of ISR's? Sorry, so many questions.
Srinathdevelopment
Thank you, that is very helpful. I am fairly satisfied that an interupt is not the best way to go about my program. It is good to hear your criteria.
srinathdevelopment:
Never have more than a couple of lines of code in any interrupt handler because another interrupt can always interrupt your interrupt handler ...
No it can't. Interrupt handlers turn interrupts off. Otherwise that would happen. For example, the timer interrupts that increments millis() might happen to be interrupted by incoming serial data.
However you are right that interrupt handlers should be short, because the next interrupt is now pending until the first one is finished. If it is pending too long subsequent ones may be missed (eg. incoming serial bytes).
Why does a while loop disable the trigering of ISR's?
It doesn't. However you are calling a function from an ISR, and as I said above, interrupts are disabled inside ISRs.
Serial comms on version 1.0 of the IDE is (are?) done by an interrupt handler, and these are disabled during your while loop (purely because it is called from an interrupt handler).