I am working on an embedded system whose microcontroller is an Arduino chip (Arduino Nano ATmega328P).
I can connect to it with a FTDI cable to read its outputs using a serial terminal. Now I want to communicate with it the other way around, that is, sending it messages or codes in order to change its global parameters.
I know it is possible to do so if I write some code where the Arduino is doing nothing but listening to the serial port. But I would like to be able to send it message at any time, even when it is doing something else. Sending it a message could trigger an interrupt, then the Arduino would execute a parallel script where it listens to the serial port for some time...
Can I do that, or is it not possible with an Arduino ?
Thanks :)
As far as I know (could be wrong), you can not "multi-thread" an arduino (don't know of any microcontrollers that support this). Inherently microcontrollers should be coded in a different style from computers. You can not assume infinite resources and infinite threads. Instead it is all about your main loop speed and how to distribute your resources. The arduino example (blink without delay) is an example of how this is done with timers. Basically, you put all of your processes inside their own timers so that they execute once per timer interval and are skipped at all other times. Assuming none of your processes are in the main loop, this will allow context switching after each and every process, as the program will cycle back through the main loop looking for the next task timer to come up. If you put all of your cyclical processes on timers like this, then put your serial availability check in another (pretty high frequency) timer, and grab serial any time you see it, it will I believe give you the results that you are after. Keep in mind though that serial read and write is a relatively slow process and so after reading or writing you may need to be careful about other processes that depend on a tight frequency call (like reading a mic to determine sound frequency for instance would need to be reset every time you read serial).
--edit I was literally working on this today anyways, so here you go:
*note that i had no need to read incoming serial, so left that bit to you to figure out. (but showed where it would be done)
boolean resetMicRecording = true;
unsigned long microphoneTimer = 0;
unsigned long microphonePeriod = 100; //us
unsigned long serialTimer = 0;
unsigned long serialPeriod = 500; //ms
void setup() {
Serial.begin(9600);
}
void loop() {
if (micros() - microphoneTimer >= microphonePeriod)
{
microphoneTimer = micros();
//do microphone task
if(resetMicRecording)//first time flag
{
//set inital recording stuff
resetMicRecording = false;
}
else//consistent frequency sampling
{
//precision analog reading, logging, and processing if nec
}
}
if (millis() - serialTimer >= serialPeriod)
{
serialTimer = millis();
if(Serial.available()>0)
{
//read your incoming serial here
//reset sensitive device timers to startup
resetMicRecording = true;
}
}
}