I have a main loop that uses the SoftwareSerial library. In each loop, it sends a command over the SW serial channel, then it blocks for about 1-2 seconds until a response arrives, and then does something else depending on the response.
Pseudocode of the main loop:
//SEND COMMAND
//RECEIVE
//BUSY WAIT WHILE NOTHING AVAILABLE AND NOT TIMED OUT
//PROCESS RECEIVED DATA IF ANY
An ISR might kick in at any point in the main loop. It might interrupt the delays, or it might interrupt a send or receive operation.
At the same time, inside the ISR, I'd like to cancel whatever the main loop is doing, read an analog pin, and quickly send a character over the software serial.
So my questions:
Is reading an analog pin allowed inside ISRs?
Is using the SW serial library possible inside the ISR, or is it too long an operation? Can the ISR mess with the serial communications if it interrupts a pending send or receive instruction in the main loop?
Is using the SW serial library possible inside the ISR
No. The SoftwareSerial library relies on interrupts being enabled. While your ISR is running, other interrupts do not happen.
Can the ISR mess with the serial communications if it interrupts a pending send or receive instruction in the main loop?
Interrupts can happen only when it is safe to do so. But, if the timing of something, like SoftwareSerial's reception of a byte, is critical, and that timing is upset by an interrupt happening, then it can "mess with the serial communications".
Any other way of doing what I want?
Yes. You can recognize that serial communications is, by design, asynchronous, and not try to force it into a synchronous pattern.
buffer_overfly:
At the same time, inside the ISR, I'd like to cancel whatever the main loop is doing, read an analog pin, and quickly send a character over the software serial.
Don't do those things inside the ISR.
Get the ISR to set a variable to record that it has happened and then use the code in loop() to do the reading and sending if the variable shows that the ISR has happened.
void myISR() {
isrTriggered = true;
}
void loop() {
// other stuff
if (isrTriggered == true) { // I do it like this because I like it. @PaulS does not
isrTriggered = false;
val = analogRead(A0);
Serial.println(val);
}
}
buffer_overfly:
I have a main loop that uses the SoftwareSerial library. In each loop, it sends a command over the SW serial channel, then it blocks for about 1-2 seconds until a response arrives, and then does something else depending on the response.
Pseudocode of the main loop:
//SEND COMMAND
//RECEIVE
//BUSY WAIT WHILE NOTHING AVAILABLE AND NOT TIMED OUT
//PROCESS RECEIVED DATA IF ANY
An ISR might kick in at any point in the main loop. It might interrupt the delays, or it might interrupt a send or receive operation.
At the same time, inside the ISR, I'd like to cancel whatever the main loop is doing, read an analog pin, and quickly send a character over the software serial.
So my questions:
- Is reading an analog pin allowed inside ISRs?
- Is using the SW serial library possible inside the ISR, or is it too long an operation? Can the ISR mess with the serial communications if it interrupts a pending send or receive instruction in the main loop?
- Any other way of doing what I want?
Revise your design - basically make the ISR to BE THE MAIN function (controller) and you be better of.
You have event driven application so monitor those events using interrupts.
Vaclav:
Revise your design - basically make the ISR to BE THE MAIN function (controller) and you be better of.
You have event driven application so monitor those events using interrupts.
Passing data from ISR to "main" is silly.
I don't understand.
For a long time I have been under the impression that loop() is the principal function in the Arduino world.
And "main" is a poor choice of word when talking about C/C++ code where it has a special significance.
All of the ISRs I have written "pass" their data to loop(). Or more accurately, loop() reads the data that the ISR is creating.
For a long time I have been under the impression that loop() is the principal function in the Arduino world.
And "main" is a poor choice of word when talking about C/C++ code where it has a special significance.
All of the ISRs I have written "pass" their data to loop(). Or more accurately, loop() reads the data that the ISR is creating.
...R
In "one word" -Arduino fathers build hardware and "developers" made software to blink LED.
Since first REAL program was written it has been established that "main" is the link between OS and application.
Now you are saying it is a poor choice? ( Arduino IDE has main() )
As far as passing data from ISR to "loop()" see my first comment above.
Any application interfacing with real word, even just pushing a button, by letting loop() to process / take control cannot be taken seriously, see my first comment above.
But if you use "blink without delay" you are the champ.
pYro_65:
Its also a good reason why there is 5000 topics asking what language the Arduino is programmed in.
...and you are going to be asked to prove the numbers...
As I said it before - Arduino WAS invented for kindergarteners and with "hide everything TOO complicated for children " attitude it will forever stay that way.
If "they" want to cater to majority who have no ambition to learn software AND hardware that is their business.
Maybe the secret goal is to keep this forum humming. I figure there must be some money in it.
...and I am off my soapbox before I get banned for speaking up , again.
Vaclav:
As I said it before - Arduino WAS invented for kindergarteners and with "hide everything TOO complicated for children " attitude it will forever stay that way.
I will resist the almost overwhelming temptation to respond to that.
If the Arduino environment is as awful as he constantly complains, why does he continue to use it?? I find it works just fine, despite its idiosyncracies, and I've been doing C programming for over 35 years.
Vaclav:
As I said it before - Arduino WAS invented for kindergarteners and with "hide everything TOO complicated for children " attitude it will forever stay that way.
If "they" want to cater to majority who have no ambition to learn software AND hardware that is their business.
Maybe the secret goal is to keep this forum humming. I figure there must be some money in it.
...and I am off my soapbox before I get banned for speaking up , again.
Ah! Vaclav, our resident whine connoisseur.
Arduino WAS invented for kindergarteners
Really? You've got PROOF of that?
Or are you just out to insult a couple of hundred thousand forum members, Vaclav?
Vaclav:
As I said it before - Arduino WAS invented for kindergarteners and with "hide everything TOO complicated for children " attitude it will forever stay that way.
I quite like the Arduino IDE. Nice and easy to use. And - you know what? - I managed to wrap my head around the fact that there is a hidden "main" file that does this, in effect:
int main ()
{
init ();
setup ();
while (true)
loop ();
}
Virtually everything in the computer world "hides" things from you. You don't want to write a disk device driver? Fine, the supplied device driver interfaces with the disks for you. How about a 3D graphics card driver? The supplied driver hides the details for you.
It must be time to wheel "Toorum's Quest" out again. This was done using the Arduino IDE:
Ah yes, Microsoft are particularly good bad at that.
In their defence, I think they define things like CHAR (to be char), and if you happen to make a Unicode app it turns into wide char. But still, it is hard to read.
And I think they introduced a few other "conventions" it is hard to train people out of. One of them, as I recall, is using leading underscores in variable names.
PaulS:
Microsoft is a master at that. What the fk is an LPTSTR? That type is used all over the fking place, when a nice simple char * would usually suffice.
They do that for exactly the same reason Arduino has int*_t, uint*_t, and all the other non-platform-dependant types. LPSTR is NOT necessarily the same as char *. It is, by definition, a Pointer to a String, and it is platform independant. Whereas char * can be very much platform-dependant, and, in the x86 world, even memory-model dependant.