Serial Print Question

Hi there,

I am currently working on a script that is reading values sent from an app on my phone via bluetooth (I am using an HC-05 module). These values can range anywhere between 0 and 100 and are sent every second. I would like to use specific values to change the colour of an LED.

For example:

If the serial monitor reads 9 I would like the LED to turn red.
And if the serial monitor reads 10 I would like the LED to turn green.

This works with values 9 and below but anything 10 and over does not. I am hoping someone could help me understand this.

Here is my script:

int incomingByte = 0; // for incoming serial data
int red_light_pin= 9;
int green_light_pin = 10;
int blue_light_pin = 11;

void setup() {
  Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
  pinMode(red_light_pin, OUTPUT);
  pinMode(green_light_pin, OUTPUT);
  pinMode(blue_light_pin, OUTPUT);
}

void loop() {
  // send data only when you receive data:
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();
    Serial.print(incomingByte, DEC);
    Serial.print("\n");        //New line 

if(incomingByte == '9') {            
digitalWrite(red_light_pin, 255);  
digitalWrite(green_light_pin, 0);  
digitalWrite(blue_light_pin, 0); 
}

else if(incomingByte == '10') {           
digitalWrite(red_light_pin, 0);  
digitalWrite(green_light_pin, 255);  
digitalWrite(blue_light_pin, 0);  
}

}
}

Thank you!

how can an incoming byte (your read only ONE character) be == '10' (two characters).. that's not even legit C++ code...

I would suggest to study Serial Input Basics to handle this

(or you could send the data in binary and as 0 to 100 fits on one byte, then that would work (but you need to compare with numbers, not ASCII codes)

1. In a Bluetooth Terminal (Bluetooth Application), there are usually the following two settings for the commands along with options for terminating character (CR = 0x0D or LF = 0x0A):
ASCII and HEX.

2. If you choose ASCII Mode and \n (LF) as terminating character and send 9, then 0x39 (00111001 = the ASCII code of 9) and 0x0A (ASCII code of LF) would be sent from BT to Arduino. In that case, you have to execute these codes at the Arduino side:

char incomingByte[3] = "";
if(strcmp(incomingByte, "9") == 0)  //to ON the built-in L (LED) of UNO

3. If you choose ASCII Mode and \n (LF) as terminating character and send 10, then 0x31, 0x30, and 0x0A would be sent from BT to Arduino. In that case, you have to execute these codes at the Arduino side:

char incomingByte[3] = "";
if(strcmp(incomingByte, "10") == 0)  //to OFF the built-in L (LED) of UNO

4. In the BT terminal of my phone, there is no option for DEC (decimal) command; but, I can select ASCII Mode and LF character.

5. Here is a demonstration sketch using 'NANO + BT+ phone (Fig-2)' for you to ON/OFF built-in L (LED) of UNO; where, 9 is sent to ON the LED and 10 is sent to OFF the LED. The settings in my phone are: ASCII and LF; Btn1 of BT Terminal is configured for 9 and Btn2 of BT terminal is configured for 10. Edit: The sketch is valid only for a 3-charcater string including the LF; after reception, the LF character must be replaced by a null character.

#include<SoftwareSerial.h>
SoftwareSerial SUART(5, 6); //SRX = D5, STX = D6

char incomingByte[3] = ""; // for incoming serial data
int red_light_pin = 13;//9;
int i = 0;

void setup()
{
  Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
  SUART.begin(9600);
  pinMode(red_light_pin, OUTPUT);
  digitalWrite(red_light_pin, LOW);
}

void loop()
{
  byte n = SUART.available();  //checking if a character has come from phone via BT
  if (n != 0)
  {
    incomingByte[i] = SUART.read();  //save the arrived character in array
    if (incomingByte[i] != '\n')           //checking if LF (\n) character has arrived
    {
      i++;           //adjust the arraay index
    }
    else     //arrived charcater is LF character
    {
      incomingByte[i] = '\0';    //add null byte in the position of LF character
      Serial.println(incomingByte);  //print received string; 9 is 1-character string; 10 is 2-character string
      i = 0;
      if (strcmp(incomingByte, "9") == 0)  //string comparison fro equality
      {
        digitalWrite(red_light_pin, HIGH);
      }
      if (strcmp(incomingByte, "10") == 0)
      {
        digitalWrite(red_light_pin, LOW);
      }
    }
  }
}

smBT.png
Figure-1: Serial Monitor of NANO

hc5-2.png
Figure-2: Connection diagram between NANO and BT using software UART (SAURT) Port

smBT.png

hc5-2.png

@golam. - remember OP said he can also see send « 100 ». You will have a buffer overflow. Make the buffer at least 1 byte larger

It’s a good practice to test if there is enough space before writing somewhere in memory and not blindly trust the end user.

I would also ignore \r just in case

J-M-L:
@golam. - remember OP said he can also see send « 100 ». You will have a buffer overflow. Make the buffer at least 1 byte larger

It’s a good practice to test if there is enough space before writing somewhere in memory and not blindly trust the end user.

I would also ignore \r just in case

I have just given a demonstration sketch for a possible command not exceeding 3 charcaters including the terminating one (the LF).

I appreciate your concern, and I hope that the OP will take care of it by extending the size of the receive array.

Understood - just wanted to make sure OP gets this or it will come bite him

Thank you both for your feedback on this post. I really appreciate it. I am fairly new to Arduino so this is a tad challenging for me to follow. I did however come up with a new sketch using character values.

This is working for me and the RGB is changing colour although it does not work for the first 32 characters (I just read that these are non-printing characters). I was planning on just using else if for all for char values for 0 to 100. For now I just added 8 values to my sketch.

(attached two photos)

char data = 0;                //Variable for storing received data
int red_light_pin= 9;
int green_light_pin = 10;
int blue_light_pin = 11;

void setup() 
{
  Serial.begin(9600);         //Sets the data rate in bits per second (baud) for serial data transmission
  pinMode(red_light_pin, OUTPUT);
  pinMode(green_light_pin, OUTPUT);
  pinMode(blue_light_pin, OUTPUT);
}
void loop()
{
if(Serial.available() > 0)  // Send data only when you receive data:
{
data = Serial.read();      //Read the incoming data and store it into variable data
Serial.print(data);        //Print Value inside data in Serial monitor
Serial.print("\n");        //New line 

if(data == 'F') {            
digitalWrite(red_light_pin, 255);  
digitalWrite(green_light_pin, 0);  
digitalWrite(blue_light_pin, 0); 
}

else if(data == 'G') {           
digitalWrite(red_light_pin, 255);  
digitalWrite(green_light_pin, 64);  
digitalWrite(blue_light_pin, 0);  
}

else if(data == 'H') {           
digitalWrite(red_light_pin, 255);  
digitalWrite(green_light_pin, 128);  
digitalWrite(blue_light_pin, 0);  
}

else if(data == 'I') {           
digitalWrite(red_light_pin, 255);  
digitalWrite(green_light_pin, 191);  
digitalWrite(blue_light_pin, 0); 
}

else if(data == 'J') {           
digitalWrite(red_light_pin, 255);  
digitalWrite(green_light_pin, 255);  
digitalWrite(blue_light_pin, 0);
}

else if(data == 'K') {           
digitalWrite(red_light_pin, 191);  
digitalWrite(green_light_pin, 255);  
digitalWrite(blue_light_pin, 0);
}

else if(data == 'L') {           
digitalWrite(red_light_pin, 128);  
digitalWrite(green_light_pin, 255);  
digitalWrite(blue_light_pin, 0);
}

else if(data == 'M') {           
digitalWrite(red_light_pin, 0);  
digitalWrite(green_light_pin, 255);  
digitalWrite(blue_light_pin, 0);
}

}
}

Which control structure would be faster -- if-else or case-switch?

Any ideas on how I could read values 0 to 32 with my script?

Thanks again!

austinwb:
Any ideas on how I could read values 0 to 32 with my script?

this will read any byte. 0 to 32 included - you have nothing special to do.
data = Serial.read();      //Read the incoming data and store it into variable datathey are just non printable symbols attached to those bytes in ASCII, but you could still compare themif (data == 7) {...}

Note @golam's point, when you start having many if-else then switch/case will be more efficient.

Thank you for your help. I am still confused about one thing.

If the character value for 49 is 1, then what would I put for the character value of 1?

Using this link as reference:

Thanks again!

austinwb:
If the character value for 49 is 1, then what would I put for the character value of 1?

Let us consult the following Table (Fig-1):


Figure-1:

1. If you want to see this character: 1 in the OutputBox (Fig-2) of the Serial Monitor, then you need to send this ASCII code/value: is 0x31 (49 decimal) to the Serial Monitor.

2. If you send this ASCII code/value: 0x31 (49 decimal) in the Serial Monitor, then you will see this character: 1. on the OutputBox of the Serial Monitor.

3. If you send this ASCII code/value: 0x01 (1 decimal) in the Serial Monitor, then you will see this character: SOH (Start of Header) on the OutputBox of the Serial Monitor; but note that SOH is a non-printable character and in that case, you might be seeing some kind of ghost/garbage in the OutputBox of the Serial Monitor.


Figure-2:

If the character value for 49 is 1, then what would I put for the character value of 1?

I am afraid that your question makes no sense

The ASCII value (decimal) for the character '1' is 49
The ASCII value (decimal) for the character '2' is 50
The ASCII value (decimal) for the character '3' is 51

Can you see the pattern here ?

GolamMostafa:
Which control structure would be faster -- if-else or case-switch?

S/he's running 960 cps maximum.

TheMemberFormerlyKnownAsAWOL:
S/he's running 960 cps maximum.

960 cps
==> 960 characters per sec
==> 960x10 bits/sec
==> Bd = 9600?

Yes what he meant is that optimizing the if/else or switch does not matter much compared to the speed of data entry, the code will loop many times waiting for the next char anyway

J-M-L:
Yes what he meant is that optimizing the if/else or switch does not matter much compared to the speed of data entry, the code will loop many times waiting for the next char anyway

But, I asked the question to the OP from another point of view and it is to be sure that he understands:

In if-else structure, all the conditions are checked even the very first condition has been satisfied.

In case-switch structure, the program flow breaks when the very first condition is satisfied.

Good question gets good answer.

GolamMostafa:
Let us consult the following Table (Fig-1):


Figure-1:

1. If you want to see this character: 1 in the OutputBox (Fig-2) of the Serial Monitor, then you need to send this ASCII code/value: is 0x31 (49 decimal) to the Serial Monitor.

2. If you send this ASCII code/value: 0x31 (49 decimal) in the Serial Monitor, then you will see this character: 1. on the OutputBox of the Serial Monitor.

3. If you send this ASCII code/value: 0x01 (1 decimal) in the Serial Monitor, then you will see this character: SOH (Start of Header) on the OutputBox of the Serial Monitor; but note that SOH is a non-printable character and in that case, you might be seeing some kind of ghost/garbage in the OutputBox of the Serial Monitor.


Figure-2:

Yes, when I receive any of the non printable characters (0 to 32 decimal) from my phone I cannot see them in the serial monitor. Which makes sense. But my question is how can I take those incoming non printable values and use them to change the colour of my LED. I can easily do this with the printable values as you can see in my script in my previous post. I hope I am making sense. I apologize for my lack of experience.

You can extract the numerical value, save it in a variable and use it.

@Golam

In if-else structure, all the conditions are checked even the very first condition has been satisfied.

What do you mean ?? That’s nonsense...