Questions to Serial Input Basics

Hello!

I've found this very useful topic:

https://forum.arduino.cc/index.php?topic=288234.0

My first question is: when I tried the "Receiving single characters" code I got back the ""This just in ... " line 3 times, to any input. For example:

  1. I pressed "a" in serial monitor with Both NL and CR mode
  2. I got back 3 times "This just in ... " and after tthan the character 1 time.

"This just in ... "
"This just in ... "
"This just in ... "
a

Why is that happening? Why I got it 3 times?

char receivedChar;
boolean newData = false;

void setup() {
 Serial.begin(9600);
 Serial.println("<Arduino is ready>");
}

void loop() {
 recvOneChar();
 showNewData();
}

void recvOneChar() {
 if (Serial.available() > 0) {
 receivedChar = Serial.read();
 newData = true;
 }
}

void showNewData() {
 if (newData == true) {
 Serial.print("This just in ... ");
 Serial.println(receivedChar);
 newData = false;
 }
}

Thanks!

You received 3 chars: ‘a’ then ‘\r’ then ‘\n’

Are you 100% sure you gave us the right print out? They should be in that order, so first ‘a’ and then 2 chars you can’t really see in the console because they don’t have a visible symbol representation (‘\n’ will go to next line)

gyandras:

  1. I pressed "a" in serial monitor with Both NL and CR mode

In that mode when you send an 'a' the Serial Monitor also sends a Carriage Return and a Line Feed - so three characters altogether.

...R

PS. Note that in Arduino programming it is usual to refer to a single character 'a' with single quotes and multiple charcters (a string) "abcde" with double quotes.

Thank you Robin!

/unfortunately right now I'm couldn't reach my arduino so probably I missed the exact answer, but your answer is okay anyway/

Understood. So when we are talking about receiveing one character, it menas only 1 "useful" character and the ending characters, which in this case, in this mode is actually 3: a + cr + nl

So probably the right serial answer is:

"This just in ... "
a
"This just in ... "

"This just in ... "

Next question:

I'm trying to turn on/turn off a buzzer with the same single character, let's say 'a'.

Here's my code:

#define SpeakerPin 9

byte byteRead;

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  pinMode(SpeakerPin, OUTPUT);
  digitalWrite(SpeakerPin, LOW);
}

void loop() {

  if (Serial.available() > 0) {
    byteRead = Serial.read();
  }

    switch (byteRead) {
        { case 'a':
          int SpeakerPinState = digitalRead(SpeakerPin);
          Serial.print (SpeakerPinState);
          if (SpeakerPinState == 0)
          {
            delay(1)
            digitalWrite(SpeakerPin, 1);
          }
          else if (SpeakerPinState == 1)
          {
            delay(1)
            digitalWrite(SpeakerPin, 0);
          }
        }
        break;
    }
}

It works however if i comment the rows "delay(1)" it gives me back 0101010101 and I don't really understand why. Is the code stucks in the if cycle or do i make a mistake because I'm not only receiveing 'a' but the ending characters also?

Wouldn't it be much easier and more obvious to use

if (byteRead == 'a') {

And the way your program is written byteRead will stay as 'a' until another character is received. If you only want it to act once then when you have acted change the value of byteRead to something else. For example

if (byteRead == 'a') {
  byteRead = 0;
  int SpeakerPinState = digitalRead(SpeakerPin);
  Serial.print (SpeakerPinState);
  if (SpeakerPinState == 0)
  {
            // delay(1)
            digitalWrite(SpeakerPin, 1);
  }
  else if (SpeakerPinState == 1)
  {
            // delay(1)
            digitalWrite(SpeakerPin, 0);
   }
}

You must always keep in mind that serial data arrives very slowly by Arduino standards.

...R

Robin2:
Wouldn't it be much easier and more obvious to use

if (byteRead == 'a'){

I'll use the code to turn on and off several other ouputs, that's why I choose switch function.

So if I understand right, the 1 milisec delay worked because of the serial speed is 9600 baud and the next character after 'a' - which was the new line (or cr) - arrived ~ 1 milisec later and than the value of byteread changed from 'a' to that. That explains why stucked in 01010101's the serial monitor when I just sent 'a' without NL and CR; the character 'a' stucked in the byte read and the switch cycle was switching itself forever and ever.

If I remember well, I tried to send another character but the cycle diidn't stop. Why was that? Shouldn't have it quit? The byteRead value wasn't 'a' anymore...

Thank you very much Robin, absolutely clear answers and a good hint for my future codes!

gyandras:
I'll use the code to turn on and off several other ouputs, that's why I choose switch function.

That's reasonable.

However in your Reply #3 you have
switch (byteRead) {
{ case 'a':

and the red { is unnecessary and confusing.

...R

Hello!

I've done the multiple switching code and it works with one fault and with one sollution which I don't think is quite correct however it works.

/I only post the core of the code, all the setups are there as it was in my previous posts/

  if (Serial.available() > 0) {
    byteRead = Serial.read();

    switch (byteRead) {

      case '4':
        //      #define VillogokPin 4
        egygombos (4);
        break;

      case '5':
        //#define MotorA_Pin 5
        //#define MotorA_Pin2 6
        egygombos_motoriranyvalto (5, 6);
        break;

//      case '7':
//        //  #include <Servo.h>
//        //  #define ServoA_Pin 7
//        //void setup()
//        //  Servo servo_A; //létrehozza a servo objectet
//        //  servo_A.attach(ServoA_Pin);  // attaches the servo on pin 7 to the servo object
//        //  int servo_A_pos = 90; //induló érték 90
//        //  servo_A.write(servo_A_pos); //induló érték 90
//
//        byteRead = 0;
//        Servo servo_A;
//        servo_A.write(0);                  // sets the servo position according to the scaled value
//        delay(200);                           // waits for the servo to get there
//        servo_A.write(90);                  // sets the servo position according to the scaled value
//        delay(200);                           // waits for the servo to get there
//        servo_A.write(180);                  // sets the servo position according to the scaled value
//        delay(200);                           // waits for the servo to get there
//        servo_A.write(90);                  // sets the servo position according to the scaled value
//        delay(200);                           // waits for the servo to get there
//        break;

      case '9':
        //      #define MotorB_Pin 9
        //      #define MotorB_Pin2 10
        egygombos_motoriranyvalto (9, 10);
        break;

      case '2':
        //#define FenyhidPin 12
        egygombos (12);
        break;

      case '3':
        //#define LampaPin 13
        egygombos (13);
        break;
        
     case '\n':
        byteRead=0;
        break;
        
     case '\r':
        byteRead=0;
        break;

      default:
        byteRead = 0;
        Serial.println("No such output");
        break;
    }
  }
}

Question 1.

Is it okay how I manage the carriege return and the newline characters? Or is there a more elegant way (without the obvius answer "change the sending mode in serial monitor" :))

Question 2.

case '7' is commented, because I always get the following error:

exit status 1
'servo_A' was not declared in this scope

However it is in the setup part (check the double commented part of case 7, I copied there the initial setup lines).

If I add "Servo servo_A" (again) under case '7' than it works but I don't understand why do I have to write it there, because it is already declared earlier in the setup phase.

Thanks.

Please post all your code.
It seems such an obvious thing to ask, but still, it has to be done.

I only post the core of the code, all the setups are there as it was in my previous posts

First mention of a servo, as far as I can see

Here it is, I cleared a lot of comments bcs the forum said that I've reached the 9000 characters.
I've tried in this way and the error is the same so the fault is still inside somewhere.

I've also attached an error log which happens if I comment the "Servo servo_A" line out.

#define KapcsoloPin 3 
#define VillogokPin 4
#define MotorA_Pin 5
#define MotorA_Pin2 6
#define ServoA_Pin 7
#define MotorB_Pin 9
#define MotorB_Pin2 10
#define FenyhidPin 12
#define LampaPin 13

#define MeroTu A6

#define NUM_SAMPLES 10

int UbeUki = 4.2;
int Uref = 4.26;
float AkkuMinFesz = 11;

int sum = 0;
unsigned char sample_count = 0;
float voltage = 0.0;
float tapfesz = voltage * UbeUki;


#include <Servo.h>

byte byteRead;


void egygombos (int pin) {
  int pinState = digitalRead(pin);
  byteRead = 0;

  if (pinState == 0)
  {
    digitalWrite(pin, 1);
    int pinState = digitalRead(pin);
    Serial.print ("Az ");
    Serial.print (pin);
    Serial.print (" kimenet értéke:");
    Serial.println (pinState);
  }
  else if (pinState == 1)
  {
    digitalWrite(pin, 0);
    int pinState = digitalRead(pin);
    Serial.print ("Az ");
    Serial.print (pin);
    Serial.print (" kimenet értéke:");
    Serial.println (pinState);
  }
}

void egygombos_motoriranyvalto (int pin1, int pin2) {
  int pinState1 = digitalRead(pin1);
  int pinState2 = digitalRead(pin2);
  byteRead = 0;
  if (pinState1 == 0 && pinState2 == 0){
    digitalWrite(pin1, 1);
    digitalWrite(pin2, 0);
    int pinState1 = digitalRead(pin1);
    int pinState2 = digitalRead(pin2);

    Serial.print ("Az ");
    Serial.print (pin1);
    Serial.print (" kimenet értéke:");
    Serial.println (pinState1);
    Serial.print ("Az ");
    Serial.print (pin2);
    Serial.print (" kimenet értéke:");
    Serial.println (pinState2);
  }
  else if (pinState1 == 1 && pinState2 == 0){
    digitalWrite(pin1, 0);
    digitalWrite(pin2, 1);
    int pinState1 = digitalRead(pin1);
    int pinState2 = digitalRead(pin2);

    Serial.print ("Az ");
    Serial.print (pin1);
    Serial.print (" kimenet értéke:");
    Serial.println (pinState1);
    Serial.print ("Az ");
    Serial.print (pin2);
    Serial.print (" kimenet értéke:");
    Serial.println (pinState2);
  }
  else if (pinState1 == 0 && pinState2 == 1){
    digitalWrite(pin1, 0);
    digitalWrite(pin2, 0);
    int pinState1 = digitalRead(pin1);
    int pinState2 = digitalRead(pin2);

    Serial.print ("Az ");
    Serial.print (pin1);
    Serial.print (" kimenet értéke:");
    Serial.println (pinState1);
    Serial.print ("Az ");
    Serial.print (pin2);
    Serial.print (" kimenet értéke:");
    Serial.println (pinState2);
  }
}


void setup() {
  Serial.begin(9600); //serial portot indít 9600-al
  Serial.println("Tolhatod");

  pinMode (KapcsoloPin, OUTPUT);
  digitalWrite(KapcsoloPin, HIGH);

  pinMode(MotorA_Pin, OUTPUT);
  pinMode(MotorA_Pin2, OUTPUT);
  pinMode(MotorB_Pin, OUTPUT);
  pinMode(MotorB_Pin2, OUTPUT);

  digitalWrite (MotorA_Pin, LOW);
  digitalWrite (MotorA_Pin2, LOW);
  digitalWrite (MotorB_Pin, LOW);
  digitalWrite (MotorB_Pin2, LOW);

  Servo servo_A; //létrehozza a servo objectet
  servo_A.attach(ServoA_Pin);  // attaches the servo on pin 7 to the servo object
  int servo_A_pos = 90; //induló érték 90
  servo_A.write(servo_A_pos); //induló érték 90


  pinMode(VillogokPin, OUTPUT);
  pinMode(FenyhidPin, OUTPUT);
  pinMode(LampaPin, OUTPUT);

  digitalWrite(VillogokPin, LOW);
  digitalWrite(FenyhidPin, LOW);
  digitalWrite(LampaPin, LOW);


}

void loop() {

  if (Serial.available() > 0) {
    byteRead = Serial.read();

    switch (byteRead) {

      case '4':
        //      #define VillogokPin 4
        egygombos (4);
        break;

      case '5':
        //#define MotorA_Pin 5
        //#define MotorA_Pin2 6
        egygombos_motoriranyvalto (5, 6);
        break;

      case '7':
        //  #include <Servo.h>
        //  #define ServoA_Pin 7
        //void setup()
        //  Servo servo_A; //létrehozza a servo objectet
        //  servo_A.attach(ServoA_Pin);  // attaches the servo on pin 7 to the servo object
        //  int servo_A_pos = 90; //induló érték 90
        //  servo_A.write(servo_A_pos); //induló érték 90

        byteRead = 0;
        //Servo servo_A;
        servo_A.write(0);                  // sets the servo position according to the scaled value
        delay(200);                           // waits for the servo to get there
        servo_A.write(90);                  // sets the servo position according to the scaled value
        delay(200);                           // waits for the servo to get there
        servo_A.write(180);                  // sets the servo position according to the scaled value
        delay(200);                           // waits for the servo to get there
        servo_A.write(90);                  // sets the servo position according to the scaled value
        delay(200);                           // waits for the servo to get there
        break;

      case '9':
        //      #define MotorB_Pin 9
        //      #define MotorB_Pin2 10
        egygombos_motoriranyvalto (9, 10);
        break;

      case '2':
        //#define FenyhidPin 12
        egygombos (12);
        break;

      case '3':
        //#define LampaPin 13
        egygombos (13);
        break;
        
     case '\n':
        byteRead=0;
        break;
        
     case '\r':
        byteRead=0;
        break;

      default:
        byteRead = 0;
        Serial.println("No such output");
        break;
    }
  }
}

error.txt (1.85 KB)

The Servo_A in setup () is only visible in setup().

Google "C++ scope rules"

Perfect, I've moved it before void setup() and now it is okay.

Thank you very much for your help!