serial event in subroutine dont work?

i see and tested some nice code http://atlas-scientific.com/_files/code/Arduino-sample-code-EZ-COM-MEGA.pdf

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?

/*
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?

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.

What are you expecting your code to do ? What does it actually do ? Where is the call to serialEvent() ?

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.

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()...

  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)

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

  1. Quit playing with serial event!

Mark

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.

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.

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.

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

@holmes4 / Mark

  1. 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?

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:

 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

serial_menu_T3stream.zip (4.62 KB)