Go Down

Topic: serial event in subroutine dont work? (Read 994 times) previous topic - next topic

kllsamui

Jan 27, 2013, 06:33 am Last Edit: Jan 27, 2013, 06:42 am by kllsamui Reason: 1
i see and tested some nice code http://atlas-scientific.com/_files/code/Arduino-sample-code-EZ-COM-MEGA.pdf
Code: [Select]

String inputstring = "";                                                       //a string to hold incoming data from the PC
String sensorstring3 = "";                                                      //a string to hold the data
boolean input_stringcomplete = false;                                          //have we received all the data from the PC
boolean sensor_stringcomplete3 = false;                                         //have we received all the data


 void setup(){                                                                //set up the hardware
    Serial.begin(115200);                                                      //set baud rate for the hardware serial port_0
    Serial3.begin(38400);                                                     //set baud rate for software serial port_3
    inputstring.reserve(5);                                                   //set aside some bytes for receiving data from the PC
    sensorstring3.reserve(30);                                                 //set aside some bytes for receiving data
    }



  void serialEvent() {                                                         //if the hardware serial port_0 receives a char              
              char inchar = (char)Serial.read();                               //get the char we just received
              inputstring += inchar;                                           //add it to the input String
              if(inchar == '\r') {input_stringcomplete = true;}                //if the incoming character is a <CR>, set the flag
             }  


 void serialEvent3(){                                                          //if the hardware serial port_3 receives a char
             char inchar = (char)Serial3.read();                               //get the char we just received
             //sensorstring3 += inchar;                                        //kll add it to the input String
             if(inchar == '\r') {sensor_stringcomplete3 = true;}               //if the incoming character is a <CR>, set the flag
             else {  sensorstring3 += inchar; }                                //kll
            }



void loop(){                                                                   //here we go....
   
 if (input_stringcomplete){                                                   //if a string from the PC has been received fully
     Serial3.print(inputstring);                                              //send that string
     inputstring = "";                                                        //clear the string:
     input_stringcomplete = false;                                            //reset the flag used to tell if we have received a completed string from the PC
     }

if (sensor_stringcomplete3){                                                   //if a string has been received fully
     Serial.println(sensorstring3);                                            //send that string to the PC's serial monitor
     sensorstring3 = "";                                                       //clear the string:
     sensor_stringcomplete3 = false;                                           //reset the flag used to tell if we have received a completed string
     }
}


like for a terminal emulation ...

but when i tried to use the event in a code
like question and answers in a subroutine it did not work.

can you pls try that following code and tell me what you think?

Code: [Select]
/*
KLL serial event test
*/
String inputstring = "";                                                       //a string to hold incoming data from the PC
boolean input_stringcomplete = false;                                          //have we received all the data from the PC

 void setup(){                                                                //set up the hardware
    Serial.begin(115200);                                                     //set baud rate for the hardware serial port_0
    inputstring.reserve(5);                                                   //set aside some bytes for receiving data from the PC KLL but seems to work also for longer strings??
    }

  void serialEvent() {                                                         //if the hardware serial port_0 receives a char              
              char inchar = (char)Serial.read();                               //get the char we just received
              inputstring += inchar;               //add it to the inputString
              Serial.print(" S0: ");
              Serial.println(inchar,HEX);
              if(inchar == '\r') {input_stringcomplete = true;}                //if the incoming character is a <CR>, set the flag
             }
             
 void askquestion() {
     Serial.println("Question: do you love me? ");
     int var = 0;
     while(var < 20){  // do something repetitive times
                  delay(200);
                  var++;  Serial.print(".");
                  if (input_stringcomplete){
                      Serial.print(" askquestion loop got: ");
                      Serial.print(inputstring);                                               //send that string back
                      Serial.println();
                      inputstring = "";                                                        //clear the string:
                      input_stringcomplete = false;                                            //reset the flage used to tell if we have recived a completed string from the PC
                      break;
                                           }
                     } // end while
                   Serial.println(" timeout ");    
                   } // ask question

void loop(){                                                                   //here we go....

 if (input_stringcomplete){                                                   //if a string from the PC has been recived in its entierty
     Serial.print(" main loop got: "); Serial.println(inputstring);
     inputstring = "";                                                        //clear the string:
     input_stringcomplete = false;                                            //reset the flage used to tell if we have recived a completed string from the PC
     }
 askquestion();    

}


looks like a character is only catched in a main loop, ( and only one per loop).
so question - answer will never work?

any ideas what i do wrong?

kllsamui

found info
http://arduino.cc/en/Tutorial/SerialEvent
/* 
  SerialEvent occurs whenever a new data comes in the
hardware serial RX.  This routine is run between each
time loop() runs, so using delay inside loop can delay
response.  Multiple bytes of data may be available.
*/

so its correct what i see and this function is of limited use.

UKHeliBob

#2
Jan 27, 2013, 12:59 pm Last Edit: Jan 27, 2013, 01:11 pm by UKHeliBob Reason: 1
What are you expecting your code to do ?
What does it actually do ?
Where is the call to serialEvent() ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

kllsamui

#3
Jan 27, 2013, 01:48 pm Last Edit: Jan 27, 2013, 02:06 pm by kllsamui Reason: 1
for a sub menu like operation i need several "questions AND answers" via serial link ( USB, operator ).
means i must stay inside a sub routine without going back to main loop inbetween,
or i would loose the reference, what answer is for what question.

the serialEvent is a interrupt routine, so not to be called here, ( only filled with functionality )
and it works perfect in a main loop structure like in the first example.

code example 2 is to show where the problem is only. pls try it.
it does not get anything from the serial line as long it is in the subroutine.
Code: [Select]
Question: do you love me?
.................... timeout
Question: do you love me?
.................... timeout
Question: do you love me?
.................... timeout
S0: 79
Question: do you love me?
.................... timeout
S0: 65
Question: do you love me?
.................... timeout
S0: 73
Question: do you love me?
.................... timeout
S0: D
main loop got: yes

Question: do you love me?
.................... timeout
Question: do you love me?
.................... timeout


so instead of using this serialEvent interrupt function i must go back to the usual Serial.available()...

holmes4

1. Its a function there are no routines (sub or other wise) in C/C++

2. Never use the String class with Arduino (there's a fault in it)

3.
Quote
for a sub menu like operation i need several "questions AND answers" via serial link ( USB, operator ).
means i must stay inside a sub routine without going back to main loop inbetween,
or i would loose the reference, what answer is for what question.


Completely wrong! See the blink without delay example and Finite State Machines in in the playground

4. Quit playing with serial event!

Mark

UKHeliBob

Your serialAvailable() function is only removing one character from the input buffer each time it is called and it is only called at the end of loop().  However, askQuestion() blocks loop() from running again until the delay of 4 seconds is over, by which time it is too late for serialAvailable() to get another character and add it to the string, and this includes the CR, so the input never finishes before the 4 seconds is up and even then only has one character in it.

If I were you I would leave serialEvent() alone.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

AWOL

Quote
However, askQuestion() blocks loop() from running again until the delay of 4 seconds is over
...by which time, the Serial input buffer could have overflowed 720 times, and you would never know.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

PaulS

Quote
Where is the call to serialEvent() ?

The serialEvent() functions are called at the end of loop(), if there is serial data on the specific port. The user does not need to code a call to the serialEvent() functions.

kllsamui

thanks for all the input:
i see : NOT USE STREAM, NOT USE EVENT.

@holmes4 / Mark
Quote
3. Completely wrong! See the blink without delay example and Finite State Machines in in the playground 

i understand that delay is bad, i try without, but the job:
ask a question " pls. give a setpoint; default 12.46: "
- i must wait for operator input,
- but check also on a timeout,
- check if the number provided is good,
- use a default number if not
+ and do something with that input
_____ while all this i can not go back to the main loop ( i think)
        as much i hate to block all other jobs in main loop
     thats why i started testing about the serialEvent.
and regarding this i do not understand your answer? you have seen code what can do that?

kllsamui

#9
Jan 28, 2013, 08:19 am Last Edit: Jan 28, 2013, 02:12 pm by kllsamui Reason: 1
pls find here ( attached ZIP ) my first working example, what combines all 3 ways to deal with serial input:

input check NO WAIT for a operator menu system ( by one character )
( what still allow the main loop to run 1000000 / 16sec. )

input question .. answer
for string / and number int/real with default number / type WAIT with time out

stream by serialEvent for sensor input from T3 (MEGA)
connected sensor: http://atlas-scientific.com/product_pages/sensors/ec-sensor.html

looks like:
Code: [Select]
KLL serial menu
adjust terminal to AUTOSCROLL, Carriage Return, 115200
hit [space] [ENTER] to get MENU list

MENU:
[space] this list
[d] enable diagnostic
[t] enable timecheck
[n] test number input
__________sensor ___________________
[c] send measure command to sensor T3
[e] send measure stop command to sensor T3
[i] send ref info command to sensor T3
select:
sensor on T3 command I<CR>
E,V3.0,4/12
sensor on T3 command C<CR>
2045,1104,0
2178,1176,0
2000,1080,0
debug ON
T3: 32 T3: 30 T3: 30 T3: 30 T3: 2C T3: 31 T3: 30 T3: 38 T3: 30 T3: 2C T3: 30 T3: D2000,1080,0
T3: 32 T3: 30 T3: 32 T3: 32 T3: 2C T3: 31 T3: 30 T3: 39 T3: 32 T3: 2C T3: 30 T3: D2022,1092,0
T3: 32 T3: 30 T3: 32 T3: 32 T3: 2C T3: 31 T3: 30 T3: 39 T3: 32 T3: 2C T3: 30 T3: D2022,1092,0
debug OFF
1978,1068,0
2022,1092,0
sensor on T3 command E<CR>

Question numberinput, default 98.7654:
int: -3456 real: -3456.79

Question numberinput, default 98.7654:  no number input, use default!
int: 98 real: 98.77


Go Up