0
Offline
Jr. Member
Karma: 0
Posts: 50
Arduino rocks
|
 |
« on: February 28, 2011, 05:15:52 pm » |
Hi, I am currently doing some software interfacing with arduino. As there are no physical buttons/switches involved, how can I produce an interrupt to the program? My program is big, and it has lots of loops and, yes. delays. So interrupt is really needed. (but without pressing any physical switches) Here's the code for the interrupt #include <avr/interrupt.h>
//volatile int bumper; // have we hit something
void setup(){ Serial.begin(9600); pinMode(2, INPUT); // Make digital 2 an input // attach our interrupt pin to it's ISR attachInterrupt(0, bumperISR, CHANGE); // we need to call this to enable interrupts interrupts(); }
// The interrupt hardware calls this when we hit our left bumper void bumperISR(){
// bumper = 1; Serial.println("interrupt!");
}
void loop(){ // if bumper triggered /*if(bumper > 0){ Serial.println("tadaaa"); delay(5000); bumper = 0; }*/ Serial.println(millis()); delay(10997); // we could do lots of other stuff here. } If using this physical interrupt (using switch), it's a success. I've tried to hook the interrupt pin (digital pin 2 of Mega) to the RX pin. so that, when I print some text, it will blink and trigger the the attachInterrupt(0, bumperISR, CHANGE). (it will repeat the interrupt twice, as the status will be low> high > low. But as usual, all my serial input to the arduino will be corrupted. (I will be sending some string starting with '<' and end with '>'. e.g <ms1-1> so that the arduino will recognize this string, and turn on/off something. Any ideas? Thank you.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Sr. Member
Karma: 1
Posts: 360
I'm 15. I like making things. I like breaking things better.
|
 |
« Reply #1 on: February 28, 2011, 05:50:16 pm » |
I guess I don't understand what you are asking. What do you want to trigger the interrupt? What does your code do? Can you please post it?
EDIT: Is it that you want to have an interrupt trigger when you receive serial data? Unfortunately, because serial itself is interrupt driven, it is unwise to assign a seperate interrupt to it. I think you are better just checking for serial at various times in your code.
|
|
|
|
« Last Edit: February 28, 2011, 06:06:05 pm by bilbo »
|
Logged
|
Alice asked the Chesire Cat, who was sitting in a tree, "What road do I take?" The cat asked, "Where do you want to go?" "I don't know," Alice answered. "Then," said the cat," it really doesn't matter, does it?"
-Lewis Carrol
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 50
Arduino rocks
|
 |
« Reply #2 on: February 28, 2011, 07:40:35 pm » |
My code, usually will listen to the serial line for an action and execute few patterns. first, it will listen any start string which starts with '<' and end with '>'. There are few patterns that involved the usage of 'delay', so i really need the interrupt to make sure, like an example, when I'm running pattern 1, then suddenly when I click pattern2 on my vb application, it will listen and executes directly. The patterns are situated in 345(); and 123(); subroutines. here are some details of the code. //*********** START LOOP FUNCTION******** //----WILL BE REPEATED THROUGHOUT THE PROCESS void loop() { inByte=0; inByte = Serial.read(); string_len=0; // clear the array of inByte if (inByte == '<'){ read_serial(); // If Start of line ("<") is found, call read_serial() function } checkbuttonstate(); } //*********** END LOOP FUNCTION********
//*********** START CHECK BUTTON STATE SUBROUTINE******** void checkbuttonstate(){
if(buttautostate==0 && buttmanstate==1) // manual mode { if(buttmode1==1 && buttmode2==0 && buttmode3==0){ // check for song mode position 123(); //play 123 dialog 345(); buttmode1=0; // clear back status } if(buttmode1==0 && buttmode2==1 && buttmode3==0){ //play mission impossible song missionimpossiblesequence(); buttmode2=0; //clear back status } if(buttmode1==0 && buttmode2==0 && buttmode3==1){ //play blue danube song repeatbluedanube(); ` endbluedanube(); buttmode3=0; //clear back status } } return; } .........................................
//*********** END CHECK BUTTON STATE SUBROUTINE********
void read_serial() // FUNCTION FOR READING THE SERIAL MESSAGE { Serial.println("processing"); while (inByte!= '>') // As long as end string not found, keep reading until 'break' found. break does not work with 'if' { if (Serial.available() > 0) // if new data is available, repeat this loop until Serial.available= 0 { if(Serial.available()>1){ inByte = Serial.read(); // Read new byte //Serial.print("READ : "); // Display the new byte stringx[string_len] = inByte; // Save the data in a character array // Serial.println(string[string_len]); // Print the characters that was recieved. -1 so that we would not read the '>' end string string_len++; //add array } if(Serial.available()==1){ // if serial is on the last bit. receiving '>' inByte=Serial.read(); // Read new byte. make it overflow as we dont want to save '>' in string. } } else if (Serial.available() == 0) // if serial buffer has all been read, and still '>' does not found, execute this line { //Serial.println("end string not available, data string invalid"); // If end string not in the string // Serial.println("$N"); //print FAIL SIGNATURE Serial.flush(); // clear the serial buffer before reading new data memset(stringx, 0, sizeof(stringx)); // clear the memory array break; // get out of the while loop } }
if (inByte == '>') //only execute the command if the end string '>' found { //******* START PUMP STATUS CHECKING if (strcmp(stringx, "mp-1") == 0){ // test to see if the two strings are equal mainpmpsw_on(); Serial.println ("main pump is on"); //put a new line // blinkLED(ledPin, 2, leddelay); }
..............// end checkbuttonstate
void read_serial() // FUNCTION FOR READING THE SERIAL MESSAGE { Serial.println("processing"); while (inByte!= '>') // As long as end string not found, keep reading until 'break' found. break does not work with 'if' { if (Serial.available() > 0) // if new data is available, repeat this loop until Serial.available= 0 { if(Serial.available()>1){ inByte = Serial.read(); // Read new byte //Serial.print("READ : "); // Display the new byte stringx[string_len] = inByte; // Save the data in a character array // Serial.println(string[string_len]); // Print the characters that was recieved. -1 so that we would not read the '>' end string string_len++; //add array } if(Serial.available()==1){ // if serial is on the last bit. receiving '>' inByte=Serial.read(); // Read new byte. make it overflow as we dont want to save '>' in string. } } else if (Serial.available() == 0) // if serial buffer has all been read, and still '>' does not found, execute this line { Serial.flush(); // clear the serial buffer before reading new data memset(stringx, 0, sizeof(stringx)); // clear the memory array break; // get out of the while loop } }
if (inByte == '>') //only execute the command if the end string '>' found { //******* START PUMP STATUS CHECKING /* if (strcmp(stringx, "ms-1") == 0){ // test to see if the two strings are equal mainsw_on(); Serial.println ("main switch is on"); //put a new line // blinkLED(ledPin, 2, leddelay); // blinkLED(ledPin, times, delay); } if (strcmp(stringx, "ms-0") == 0){ // test to see if the two strings are equal mainsw_off(); Serial.println ("main switch is off"); //put a new line //blinkLED(ledPin, 2, leddelay); } */ if (strcmp(stringx, "mp-1") == 0){ // test to see if the two strings are equal mainpmpsw_on(); Serial.println ("main pump is on"); //put a new line // blinkLED(ledPin, 2, leddelay); } ................ end void serial read
void 123(){ //print welcome screen first printwelcomelcd(); //set delay for starting delay(3000); //play introduction to 123 - signal low digitalWrite(7, LOW); // delay for 123 dialog to play delay(17000); //123 dialog finished //set 123 dialog trigger pin off - signal high digitalWrite(7, HIGH); return; } //*********** END 123 SUBROUTINES ********
|
|
|
|
« Last Edit: February 28, 2011, 07:42:45 pm by aminbahar »
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #3 on: February 28, 2011, 07:47:30 pm » |
else if (Serial.available() == 0) // if serial buffer has all been read, and still '>' does not found, execute this line { //Serial.println("end string not available, data string invalid"); // If end string not in the string // Serial.println("$N"); //print FAIL SIGNATURE Serial.flush(); // clear the serial buffer before reading new data memset(stringx, 0, sizeof(stringx)); // clear the memory array
If there is no serial data to read, there is nothing to flush. It is not necessary to NULL every element in the char array. Simply put a NULL in the 0 position. Every time you add a character, add a NULL, too. The code for 345() was not include, but the code in 123() just screams for using millis() and following the lead of the blink without delay example. Then, the whole idea of needing an interrupt to get the controllers attention goes out the window. There is even a TimedAction library that you might want to look at.
|
|
|
|
|
Logged
|
|
|
|
|
Saint Petersburg, Russia
Offline
Full Member
Karma: 2
Posts: 103
Amateur
|
 |
« Reply #4 on: February 28, 2011, 08:32:34 pm » |
But as usual, all my serial input to the arduino will be corrupted. (I will be sending some string starting with '<' and end with '>'. e.g <ms1-1> so that the arduino will recognize this string, and turn on/off something.
You may use "software" interrupts for this. http://www.arduino.cc/en/Reference/AttachInterruptThe HardwareSerial class doesn't use USART_RX_vect interrupt, so if your sketch should receive data from USART while other code is executing, you should add this feature manually instead using Serial class. Read uC datasheet for USART code examples and HardwareSerial source code to learn how it works, then write your own USART receiver code. http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 50
Arduino rocks
|
 |
« Reply #5 on: February 28, 2011, 08:38:06 pm » |
Pauls, the 345 subroutine will look like this. (still there are delay), and I will be looping through all these kind of patterns throughout the program. void 345() { //start cycle pattern for(int pin=nozz1; pin<=nozz5; pin++) { ledallredon(); digitalWrite(nozz1, LOW); digitalWrite(pin, HIGH); // set the valve on delay(180); // delay digitalWrite(pin, LOW); // set the LED off delay(180); // delay }
for(int pin=nozz1; pin<=nozz5; pin++) { digitalWrite(nozz1, LOW); digitalWrite(pin, HIGH); // set the valve on delay(180); // delay digitalWrite(pin, LOW); // set the LED off delay(180); // delay } ledalloff(); return; } The main reason there is some long delay, is in the subroutine 123, I will be turning on waveshield module. During this time, it will stay in that loop, and wait until the mp3 finished playing. TimedAction, will it act similar to delay? but without stopping the program?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 50
Arduino rocks
|
 |
« Reply #6 on: February 28, 2011, 08:43:01 pm » |
@Vanyamba, Is it like this? #include <avr/interrupt.h>
//volatile int bumper; // have we hit something
void setup(){ Serial.begin(9600); pinMode(2, INPUT); // Make digital 2 an input // attach our interrupt pin to it's ISR attachInterrupt(0, bumperISR, CHANGE); // we need to call this to enable interrupts interrupts(); }
// The interrupt hardware calls this when we hit our left bumper void bumperISR(){
// bumper = 1; Serial.println("interrupt!");
}
void loop(){ // if bumper triggered /*if(bumper > 0){ Serial.println("tadaaa"); delay(5000); bumper = 0; }*/ Serial.println(millis()); delay(10997); // we could do lots of other stuff here. } How I should connect the RX pin to the interrupt pin? As I've tried direct connect it, and the interrupt does not read my serial.read properly. (or maybe, nothing). Any diagram on how I can make this happen?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 50
Arduino rocks
|
 |
« Reply #7 on: March 01, 2011, 09:59:18 am » |
any updates?
|
|
|
|
|
Logged
|
|
|
|
|
Saint Petersburg, Russia
Offline
Full Member
Karma: 2
Posts: 103
Amateur
|
 |
« Reply #8 on: March 01, 2011, 11:41:25 am » |
@Vanyamba,
Is it like this?
Slightly more difficult. How I should connect the RX pin to the interrupt pin?
You sure you need interrupts. But you can't use them. Maybe this task can be resolved without interrupts. Any diagram on how I can make this happen?
I like diagrams, it's true.
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Full Member
Karma: 2
Posts: 110
Kittens eat Arduinos
|
 |
« Reply #9 on: March 01, 2011, 02:33:34 pm » |
The HardwareSerial implementation (.cpp) does use the RX interrupt, and puts the received data in a ring buffer for the sketch to read later... Even if you modified the HardwareSerial implementation to call one of your functions when it copied '>' into the ring buffer (which is not hard to do, but does create a mess that is hard to look after as new versions of the Arduino software are released) there is still the problem that you are using humungous delay()s in your code. If you delay(10000) in your code, then the sketch can not respond sensibly to the command for 10 seconds! If you really want to keep the structure of the code relatively unchanged you need to do something like static char cmd_i = 0 ; define CMD_L 10 static char cmd[CMD_L] ;
void checkSerial(void) { if (Serial.available()) { char ch ; if (cmd_i >= CMD_L) cmd_i = 0 ; cmd[cmd_i++] = ch = Serial.read() ; if (ch == '>') checkCommand() ; } }
static bool abortDelay = false ; void my_delay(int n) { abortDelay = false ; long end = millis() + n ; while (end > millis()) { checkSerial() ; if (abortDelay) return ; } }
then call my_delay() rather than the normal one.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 50
Arduino rocks
|
 |
« Reply #10 on: March 04, 2011, 01:39:02 am » |
@dafid, That looks like a good option. Meaning, rather than just delay, we will use my_delay() which will check for the serial every single loop. By the way, I would like to ask, how does the delay or milis works? Does delay(1000); would be same as for(int i=0;i<1000;i++){ ...} Does every single line execution resembles '1'? Any reading details that I can go through to understand this more? EDIT: another thing, what this code does: static bool abortDelay = false ; Thank you.
|
|
|
|
|
Logged
|
|
|
|
|
|