Offline
Newbie
Karma: 0
Posts: 36
|
 |
« on: November 27, 2012, 07:53:24 am » |
Hi everybody, After some research inside this forum and google, I've a lot of doubt about Time management with Arduino, so I've decide to ask you some help. The goal is to create a switch case loop inside "void loop()" that execute a certain subroutine for a certain time (for example 3 minutes). The pseudocode I've thought is: void setup() { Serial.begin(9600); Serial.println("Waiting for command"); } void loop() { // this is where the "polling" occurs if(Serial.available()){ char ch=Serial.read(); switch(ch) { case '1': // do something break; case '2': //do something break; case '3': void Tempfunct(); break; default: Serial.print(ch); Serial.println(" : unknown command!"); } } }
// function to be called void Tempfunct() { //do something for 3*60*60*1000 s and return to switch case selection } I consider this solution a starting point, because I think a solution involving interrupts would be a better solution. Specifically I expect something like this pseudocode: void setup() { Serial.begin(9600); Serial.println("Waiting for command"); } void loop() { // this is where the "polling" occurs if(Serial.available()){ char ch=Serial.read(); switch(ch) { case '1': // do something break; case '2': //do something break; case '3': void Tempfunct(); break; default: Serial.print(ch); Serial.println(" : unknown command!"); } } }
// function to be called void Tempfunct() { //do something until an interrupt condition is received from Serial (such a key pressed by user) and then return to switch case selection } Can someone help me? Thank you all!
|
|
|
|
|
Logged
|
|
|
|
|
Dubuque, Iowa, USA
Offline
Edison Member
Karma: 13
Posts: 1542
|
 |
« Reply #1 on: November 27, 2012, 08:25:09 am » |
Look in the example for the "TimeAlarms" addition in the [http://www.arduino.cc/playground/uploads/Code/Time.zip]Time[/url] library.
You topic subject mentions "+ using external interrupt"; I assume you meant for the timing only or is there something else you were trying to accomplish?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 36
|
 |
« Reply #2 on: November 27, 2012, 08:43:52 am » |
Hi, thank for you soon reply! I've got the library yet, but it's a little bit to understand to me how to use it to time a function. I'm trying to keep hard an eye on to understand it. The interrupt I would try to set is only for the timed function. I.e.: pushing a key on the keyboard cause the start of a measurement (for a certain and yet set sensor); pushing another button cause the stop of the measurement. During the function I would like Arduino will get values from the sensor and send value to the serial port (simply using Serial.print(....)) using a set time period (for example one serial printing every two second). After every printing Arduino should search the serial port for the "stop key", used as interrupt. I would like to use the sensor data to plot a graph on Processing. Thank you very much!
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Edison Member
Karma: 114
Posts: 2205
|
 |
« Reply #3 on: November 27, 2012, 08:47:33 am » |
Easy: void run_me(void) { static unsigned char execution_count=0; //execution counter
if (++execution_counter > MAX_RUN) return; //if total number of runs exceed, do nothing
//put your code here }
All you need to do is to specify MAX_RUN.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 36
|
 |
« Reply #4 on: November 27, 2012, 08:50:24 am » |
@dhenry: uhm... Can you explain your code??? Thank you very much!
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6388
-
|
 |
« Reply #5 on: November 27, 2012, 09:16:03 am » |
The interrupt I would try to set is only for the timed function. I.e.: pushing a key on the keyboard cause the start of a measurement (for a certain and yet set sensor); pushing another button cause the stop of the measurement. During the function I would like Arduino will get values from the sensor and send value to the serial port (simply using Serial.print(....)) using a set time period (for example one serial printing every two second). After every printing Arduino should search the serial port for the "stop key", used as interrupt. I would like to use the sensor data to plot a graph on Processing. Thank you very much!
You don't need interrupts for this. All you need is to set a flag when you detect that the measurement should start, and clear it when it should end. In loop(), use the techniques demonstrated in the 'blink without delay' example sketch to collect your sensor inputs at regular intervals while the flag is set. I guess that the keyboard you refer to is the keyboard on the host PC. You need to use some application on the host PC to send the keyboard input to the Arduino. If you plan to use the Arduino IDE's serial monitor for this, bear in mind that the serial monitor input is line buffered so you would need to enter your command character(s) followed by the return key to send that command to the Arduino. In other words, two key presses. If you were thinking about using buttons directly connected to the Arduino instead, that would work fine too but you'd need to read (and debounce) the switch states instead of reading commands from the serial port.
|
|
|
|
|
Logged
|
|
|
|
|
Dubuque, Iowa, USA
Offline
Edison Member
Karma: 13
Posts: 1542
|
 |
« Reply #6 on: November 27, 2012, 09:27:27 am » |
Just FYI: #include <Time.h> #include <TimeAlarms.h>
void setup() { Serial.begin(9600); Serial.println("Waiting for command"); } AlarmID_t temptimer; void loop() { // this is where the "polling" occurs if(Serial.available()){ char ch=Serial.read(); switch(ch) { case '1': // start recording? temptimer = Alarm.timerRepeat(1, Tempfunct); break; case '2': // stop recording? Alarm.disable(temptimer); break; default: Serial.print(ch); Serial.println(" : unknown command!"); } } }
// function to be called void Tempfunct() { // do whatever reading Serial.println(analogRead(A0)); } This is perhaps kinda heavy for what you appear to be doing (should use the "blink without delay" method), but just wanted to followup. Also, TimeAlarms.cpp needs to be updated for Arduino 1.0. Replace: #include <WProgram.h> With: #if ARDUINO >= 100 #include <Arduino.h> #else #include <WProgram.h> #endif
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 36
|
 |
« Reply #7 on: November 27, 2012, 10:23:24 am » |
You don't need interrupts for this. All you need is to set a flag when you detect that the measurement should start, and clear it when it should end. In loop(), use the techniques demonstrated in the 'blink without delay' example sketch to collect your sensor inputs at regular intervals while the flag is set.
I guess that the keyboard you refer to is the keyboard on the host PC. You need to use some application on the host PC to send the keyboard input to the Arduino. If you plan to use the Arduino IDE's serial monitor for this, bear in mind that the serial monitor input is line buffered so you would need to enter your command character(s) followed by the return key to send that command to the Arduino. In other words, two key presses. If you were thinking about using buttons directly connected to the Arduino instead, that would work fine too but you'd need to read (and debounce) the switch states instead of reading commands from the serial port.
Hi PeteH, I will use Processing to control Arduino from PC. I would like to design an interface with some button, each one used to trigger Arduino to communicate with one of the sensors (using something like a "switch case" loop in the Arduino's sketch ). I have 4 sensors connected to Arduino: 3 of them will print one simple float value to the Serial port each other and these values will be printed on my Processing interface as numeric values. Instead, the 4th sensor, specifically the pressure sensor, will print automatically one value per second for (i.e.) 3 minutes on the serial port, when trigged (through Arduino) by pressing one button on the Processing interface. To realize the interrupt for the pressure sensor I thought to have two button (one to start the measurement and the other to stop it) dedicated in the Processing interface.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 36
|
 |
« Reply #8 on: November 27, 2012, 10:39:56 am » |
Just FYI: #include <Time.h> #include <TimeAlarms.h>
void setup() { Serial.begin(9600); Serial.println("Waiting for command"); } AlarmID_t temptimer; void loop() { // this is where the "polling" occurs if(Serial.available()){ char ch=Serial.read(); switch(ch) { case '1': // start recording? temptimer = Alarm.timerRepeat(1, Tempfunct); break; case '2': // stop recording? Alarm.disable(temptimer); break; default: Serial.print(ch); Serial.println(" : unknown command!"); } } }
// function to be called void Tempfunct() { // do whatever reading Serial.println(analogRead(A0)); } This is perhaps kinda heavy for what you appear to be doing (should use the "blink without delay" method), but just wanted to followup. Also, TimeAlarms.cpp needs to be updated for Arduino 1.0. Replace: #include <WProgram.h> With: #if ARDUINO >= 100 #include <Arduino.h> #else #include <WProgram.h> #endif Thank you for your reply. I prefer to use every case to control a method and each method to control a sensor: so I imagine to have something like: #include <Time.h> #include <TimeAlarms.h>
void setup() { Serial.begin(9600); Serial.println("Waiting for command"); } AlarmID_t temptimer; void loop() { // this is where the "polling" occurs if(Serial.available()){ char ch=Serial.read(); switch(ch) { case '1': // control sensor 1 sens1(); break; case '2': // control sensor 2 sens2(); break;
case'3': // control pressure sensor pressfunct(); break; default: Serial.print(ch); Serial.println(" : unknown command!"); } } }
void sens1(){ //do something;} void sens2(){ //do something;}
// function to control pressure sensor (start/stop measurement) void pressfunct() { while(key==...){ //start measurement (i.e f=1 data for second);} //measurement continue until i press another key : key2==... //after Arduino receive key2, stop measurement and return to "void loop()", waiting for..
}
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6388
-
|
 |
« Reply #9 on: November 27, 2012, 10:41:31 am » |
That sounds reasonable. I don't know what buffering the Processing interface applies when writing to the serial port - you would need to find out whether it is able to write single character commands as you are assuming; quite likely it is.
Nothing you're describing on the Arduino side requires your sketch to use interrupts - all the behaviour you're describing can be achieved by straight forward coding within loop().
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 36
|
 |
« Reply #10 on: November 27, 2012, 10:50:37 am » |
That sounds reasonable. I don't know what buffering the Processing interface applies when writing to the serial port - you would need to find out whether it is able to write single character commands as you are assuming; quite likely it is.
Nothing you're describing on the Arduino side requires your sketch to use interrupts - all the behaviour you're describing can be achieved by straight forward coding within loop().
Yes, Processing can write single character to serial port: this is what i do with Processing. For me, this situation is like having a sort of "measurement loop" inside one of the "case". When Arduino receive a preset "start-key" (start character), it starts measuring. When the user press another button in the Processing interface, it send preset "stop-key" (stop character) to Arduino: Arduino feels like to have an external interrupt, stops the measurement and return to void loop(){...} cycle.
|
|
|
|
« Last Edit: November 27, 2012, 11:20:59 am by 8bit_Biker »
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6388
-
|
 |
« Reply #11 on: November 27, 2012, 05:18:13 pm » |
For me, this situation is like having a sort of "measurement loop" inside one of the "case". When Arduino receive a preset "start-key" (start character), it starts measuring. When the user press another button in the Processing interface, it send preset "stop-key" (stop character) to Arduino: Arduino feels like to have an external interrupt, stops the measurement and return to void loop(){...} cycle.
No, that's NOT how I'd do it. You want to avoid designing your code so that it stops and waits for something to happen (the command to end monitoring); that's a blocking design which would need you to replicate logic all over the place. The benefit of following the non-blocking approach demonstrated in the 'blink without delay' example is that your sketch can handle multiple actions and events in a consistent way without all your separate bits of code needing to explicitly cooperate or depend on each other; it gives you a nice simple architecture that scales very well. In loop() add your code to receive commands from the serial port and set a 'monitoring enabled' flag to indicate whether the regular monitoring should be happening based on the commands received. Also in loop() test whether the 'monitoring enabled' flag is set and then whether it's time to collect a sample, and if it is then you collect and transmit the sample. Other pieces of code in loop() could deal with other things you might need to do concurrently such as blinking LEDs or whatever.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 36
|
 |
« Reply #12 on: November 28, 2012, 03:10:54 am » |
No, that's NOT how I'd do it.
You want to avoid designing your code so that it stops and waits for something to happen (the command to end monitoring); that's a blocking design which would need you to replicate logic all over the place. The benefit of following the non-blocking approach demonstrated in the 'blink without delay' example is that your sketch can handle multiple actions and events in a consistent way without all your separate bits of code needing to explicitly cooperate or depend on each other; it gives you a nice simple architecture that scales very well.
In loop() add your code to receive commands from the serial port and set a 'monitoring enabled' flag to indicate whether the regular monitoring should be happening based on the commands received. Also in loop() test whether the 'monitoring enabled' flag is set and then whether it's time to collect a sample, and if it is then you collect and transmit the sample. Other pieces of code in loop() could deal with other things you might need to do concurrently such as blinking LEDs or whatever.
Thank you for your reply!This solution seems good, but I haven't understand it very well. Can you explain it to me with an example?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 36
|
 |
« Reply #13 on: December 06, 2012, 09:32:56 am » |
Just FYI: #include <Time.h> #include <TimeAlarms.h>
void setup() { Serial.begin(9600); Serial.println("Waiting for command"); } AlarmID_t temptimer; void loop() { // this is where the "polling" occurs if(Serial.available()){ char ch=Serial.read(); switch(ch) { case '1': // start recording? temptimer = Alarm.timerRepeat(1, Tempfunct); break; case '2': // stop recording? Alarm.disable(temptimer); break; default: Serial.print(ch); Serial.println(" : unknown command!"); } } }
// function to be called void Tempfunct() { // do whatever reading Serial.println(analogRead(A0)); } This is perhaps kinda heavy for what you appear to be doing (should use the "blink without delay" method), but just wanted to followup. Also, TimeAlarms.cpp needs to be updated for Arduino 1.0. Replace: #include <WProgram.h> With: #if ARDUINO >= 100 #include <Arduino.h> #else #include <WProgram.h> #endif Hi, I've tried to use your method, but it seems it doesn't work for me! after the Tempfunct has been called, nothing happens! Why??
|
|
|
|
|
Logged
|
|
|
|
|
|