Clarity on Serial Monitor and Print/Write Commands

Hi, there!

Problem: I am writing to ask for guidance and advice on a situation that I dealing with on the Serial Monitor in conjunction with the Print/Write Commands. The problem I have is the text that I want to display (which is data from a PIC microcontroller) will not completely display - every other letter/number/symbol is removed. Example the phrase “I’m going somewhere to eat.” will read on the Serial Monitor as “Imgigsmweet a.”. What would cause this particular situation? Any and all advice would be greatly appreciated.

Background: I am using a PIC 18F4550 microcontroller and the Adafruit Huzzah32 - ESP32 Breakout Board (Bluetooth Device). The PIC 18F4550 is being used to collect voltage readings and convert them to analog and digital values from a variable power supply. The PIC 18F4550 is connected to the ESP32 using serial communication. The objective of the ESP32 Bluetooth Device is to collect the data from the PIC 18F4550 and send it wirelessly (i.e. Bluetooth) to my cell phone. The results of the data being displayed on my Cell Phone are the same as the Serial Monitor. I do use the Serial Monitor as a means to check my code.

Conclusion: I would like to know why the data from the PIC microcontroller would have every other letter/number/symbol removed. What concepts or specs or codes am I misunderstanding or lacking in knowledge with Arduino/PIC/ESP32 that would help solve this situation? I have attached my code, a diagram of the general layout of my hardware, and both the Serial Monitor and my Cell phone as it displays the data from the PIC 18F4550. I hope that I covered the necessary items needed for your help and if not then please let me know. I do thank you for your time and any and all help on this.

#include <BluetoothSerial.h>    //Header File for Serial Bluetooth, 
                                //will be added by default into Arduino.                            
BluetoothSerial ESP_32;         //Object for Bluetooth.

int INCOMING_DATA;              //Designated variable Integer that represents 
                                //ASCII value from CELL PHONE.
String SERIAL_DATA;             //created a character variable for BT.


void setup() 
  {
   Serial.begin(115200);        //Activates Serial Port.
   Serial1.begin(115200);       //Activates Serial1 Port.
   
   ESP_32.begin("ESP32 BLUETOOTH");   
                                //Activates Bluetooth and designates ID
                                //for BT signal when pairing w/cell phone.
                                 
   Serial.println("ESP32 is initialized. Proceed to pair using bluetooth.");
                                //Phrase is read on Serial Monitor.

   pinMode (13, OUTPUT);        //GPIO Pin is set as an LED output
   }

void loop() 
  { 
   if (ESP_32.available())      //Checks if Bluetooth is receiving data.
    { 
    INCOMING_DATA = ESP_32.read(); 
                                //Reads incoming data from CELL PHONE and 
                                //stores incoming data in INCOMING_DATA.
                                //NOTE: the data value from CELL PHONE is
                                //in the char form so on SERIAL MONITOR
                                //the value is in decimal value.                            
    Serial.print("Received: "); //Phrase is printed on SERIAL MONITOR as
                                //readable ASCII text.
    Serial.println(INCOMING_DATA);
                                //Prints data on SERIAL MONITOR & used to
                                //verify data sent from CELL PHONE.  
                                //NOTE: will receive DEC 13 and DEC 10 at
                                //end of each data from CELL PHONE that 
                                //represent a RETURN & END of Line of text.
    }

    if (INCOMING_DATA == 97)    //a on the keypad
        {                                     
        while (Serial1.available())
            {
            ESP_32.write(Serial1.read());             
            Serial.write(Serial1.read());
                                //Previous two codes write data from PIC and
                                //display it on CELL PHONE & SERIAL MONITOR.
            }
        }

        ////****This is the ESP32 LED On/Off Section****////
                
    if (INCOMING_DATA == 49)    //1 on the keypad.
        {
        digitalWrite(13, HIGH); //LED reads high.
        ESP_32.println("LED turned ON\nAnd will Remain ON!!");
                                //Indicates ouput status on CELL PHONE.
        ESP_32.println(" ");    //Places a space inbetween data.                                                  
        }
        
    if (INCOMING_DATA == 48)    //0 on the keypad.
        {
        digitalWrite(13, LOW);  //LED reads low.
        ESP_32.println("LED turned OFF\nAnd will Remain OFF!!");
                                //Indicates ouput status on CELL PHONE.
        ESP_32.println(" ");    //Places a space inbetween data.                                
        }    

    delay(1);
  }

Hello Sapphire_dragon,
Welcome to the forum. For posting your code properly on your first post ++Karma;

I don't know the answer to your problem but I am suspicious about using int for incoming data, which I would have thought would arrive in single bytes, not 2 bytes at a time. Storing single bytes in a variable designed for 2 bytes seems to be consistent with losing every other byte, especially as the data actually stores text.

Thank you PerryBebbinton! I didn't think of the type of variable was a problem and I appreciate the details!! I'll have to look into that then. I do have one question that you may know and that is how do you place an image without using the attachment feature as I have seen others do on posts? I'd rather have my pics seen if possible.

How do you place an image without using the attachment feature as I have seen others do on posts?
Images on here are a pain! You mean like this:

Attach the image as you have already found out how to do and save your post so the image uploads. Then hover over the link to the image and right click and select whatever in your browser allows you to copy the URL for the image you want. Edit your post. Use the insert an image tool in the tool bar, it's roughly in the middle. Paste the URL where shown. Save the changes.

For what it's worth I have a similar project with a PIC connected to an ESP8266. The ESP8266 I have has a 128 x 32 OLED on top, brilliant for displaying debug messages.

   while (Serial1.available())
            {
            ESP_32.write(Serial1.read());             
            Serial.write(Serial1.read());
                                //Previous two codes write data from PIC and
                                //display it on CELL PHONE & SERIAL MONITOR.
            }
        }

Every time you use Serial1.read(), you are reading in a character from the serial port. The two write statements above will each read one character, for a total of two, with the ESP_32 and Serial each getting every other character from the input. If you want to write an input character to two different outputs, you need to read it into a variable first, then write the variable.

Oh, wow! You're a diamond!! Thank you for sharing that info PerryBebbington!! I'll see if I can do that now b/c that shows all of what I am trying to relay but visually!!

I give credit to PerryBebbington on having an image placed on my post and again thank you!!

The pictures below are the diagrams and results of my project that I am having issues with. I hope that gives better clarity of my situation and thank you all for your help!

First - The Hardware Layout of the Variable Power Supply, PIC, and ESP32:

Second - The Data being Displayed on the Serial Monitor:

Third - The Data being Received by the Cell Phone:

Every time you use Serial1.read(), you are reading in a character from the serial port. The two write statements above will each read one character, for a total of two, with the ESP_32 and Serial each getting every other character from the input. If you want to write an input character to two different outputs, you need to read it into a variable first, then write the variable.

Hello, david_2018, and thank you for replying! Do pardon me but let me see if I understood you correctly sir. I summarized your recommended solution as:

1. create a variable (preferably a String).

2. assign said variable =Serial1.read().

3. use the write command to write on Serial Monitor and Cell ---> Serial.write(SERIAL1_DATA) as example.

Am I understanding your process correctly? I'll be trying this recommendation and report back on what I get and thank you!

Sapphire_Dragon:
Hello, david_2018, and thank you for replying! Do pardon me but let me see if I understood you correctly sir. I summarized your recommended solution as:

1. create a variable (preferably a String).

2. assign said variable =Serial1.read().

3. use the write command to write on Serial Monitor and Cell ---> Serial.write(SERIAL1_DATA) as example.

Am I understanding your process correctly? I'll be trying this recommendation and report back on what I get and thank you!

Looks correct, but use char or byte, not String, you are only reading a single character at a time, and String often leads to memory corruption problems.

Hey, david_2018! This is what I did and I greatly appreciate your help on this. And here are my results:

1. create a variable (char/byte will work - I did both!) —> char SERIAL1_DATA;

2. assign said variable to Serial1 Port —> SERIAL1_DATA=Serial1.read();

3. use write command to write on Serial Monitor and Cell Phone:

ESP_32.write(SERIAL1_DATA);
Serial.write(SERIAL1_DATA);

When placed and uploaded the Serial Monitor read the results that I was anticipating. The Cell Phone read the results but had a slight issue, which I am curious on but overall I am quite thrilled at the results! I have attached the results (displaying a message of analog and digital voltage values) of both the Serial Monitor and Cell Phone and updated the code.

#include <BluetoothSerial.h>    //Header File for Serial Bluetooth, 
                                //will be added by default into Arduino.
#include <HardwareSerial.h>
                                                            
BluetoothSerial ESP_32;         //Object for Bluetooth.

int INCOMING_DATA;              //Designated variable Integer that represents 
                                //ASCII value from CELL PHONE.
String SERIAL_DATA;             //created a character variable for BT.
char SERIAL1_DATA;              //Designated variable for Serial1 Port - PIC. 

void setup() 
  {
   Serial.begin(115200);        //Activates Serial Port.
   Serial1.begin(115200);       //Activates Serial1 Port.
   
   ESP_32.begin("ESP32 BLUETOOTH");   
                                //Activates Bluetooth and designates ID
                                //for BT signal when pairing w/cell phone.
                                 
   Serial.println("ESP32 is initialized. Proceed to pair using bluetooth.");
                                //Phrase is read on Serial Monitor.

   pinMode (13, OUTPUT);        //GPIO Pin is set as an LED output
   }

void loop() 
  { 
   if (ESP_32.available())      //Checks if Bluetooth is receiving data.
    { 
    INCOMING_DATA = ESP_32.read(); 
                                //Reads incoming data from CELL PHONE and 
                                //stores incoming data in INCOMING_DATA.
                                //NOTE: the data value from CELL PHONE is
                                //in the char form so on SERIAL MONITOR
                                //the value is in decimal value.                            
    Serial.print("Received: "); //Phrase is printed on SERIAL MONITOR as
                                //readable ASCII text.
    Serial.println(INCOMING_DATA);
                                //Prints data on SERIAL MONITOR & used to
                                //verify data sent from CELL PHONE.  
                                //NOTE: will receive DEC 13 and DEC 10 at
                                //end of each data from CELL PHONE that 
                                //represent a RETURN & END of Line of text.
    }

    if (INCOMING_DATA == 97)    //a on the keypad
        {                                     
        while (Serial1.available())
            {
            SERIAL1_DATA = Serial1.read();
            ESP_32.write(SERIAL1_DATA);             
            Serial.write(SERIAL1_DATA);
              
            //ESP_32.write(Serial1.read());             
            //Serial.write(Serial1.read());
                                //Previous two codes write data from PIC and
                                //display it on CELL PHONE & SERIAL MONITOR.
            }
        }

        ////****This is the ESP32 LED On/Off Section****////
                
    if (INCOMING_DATA == 49)    //1 on the keypad.
        {
        digitalWrite(13, HIGH); //LED reads high.
        ESP_32.println("LED turned ON\nAnd will Remain ON!!");
                                //Indicates ouput status on CELL PHONE.
        ESP_32.println(" ");    //Places a space inbetween data.                                                  
        }
        
    if (INCOMING_DATA == 48)    //0 on the keypad.
        {
        digitalWrite(13, LOW);  //LED reads low.
        ESP_32.println("LED turned OFF\nAnd will Remain OFF!!");
                                //Indicates ouput status on CELL PHONE.
        ESP_32.println(" ");    //Places a space inbetween data.                                
        }    

    delay(1);
  }

A better display of my attachments are below:

1. The Data on the Serial Monitor - Better Results!

2. The Data on My Cell Phone - Close to What I want BUT BETTER!

  • I would like to know why the two characters ^M are displayed at the beginning of my messages and curious as to what is the best way to remove them? I think I need to adjust my code in the PIC 18F4550?
  • I am curious to know what is the significance with using the char/byte over the String as a variable for the situation I am in using Serial Communication? Is it because a String is an array of characters (or multiple characters being) being read a once rather than one character at a time due to the nature of Serial Communication? I would like to know and understand this concept of using variable types and Serial Communication. And it would be appreciated.

control M is a carriage return, in ASCII code it is decimal 13 or hexidecimal 0x0D. Easiest way to correct the cell phone data is probably to just not send the character if it is a carriage return

if (INCOMING_DATA == 97)    //a on the keypad
       {                                     
       while (Serial1.available())
           {
           SERIAL1_DATA = Serial1.read();
           if (SERIAL1_DATA != 0x0D)
             {
             ESP_32.write(SERIAL1_DATA);             
             }
           Serial.write(SERIAL1_DATA);
            
           //ESP_32.write(Serial1.read());             
           //Serial.write(Serial1.read());
                               //Previous two codes write data from PIC and
                               //display it on CELL PHONE & SERIAL MONITOR.
           }
       }

I am curious to know what is the significance with using the char/byte over the String as a variable for the situation I am in using Serial Communication? Is it because a String is an array of characters (or multiple characters being) being read a once rather than one character at a time due to the nature of Serial Communication? I would like to know and understand this concept of using variable types and Serial Communication. And it would be appreciated.

Serial1.read() returns an integer, although I usually use char or byte since serial generally is used with ASCII text or 8-bit binary numbers. It will return a -1 value if there is nothing in the receive buffer, but since you are checking Serial1.available() that should never happen. Using String will not cause it to return more than a single character.

Avoiding String has nothing to do with the way you are using it, but with how poorly most arduino's manage memory. Space for String tends to get allocated and released as the data in it is changed and the length of the String changes, and the arduino is very poor at recovering the memory when it is no longer needed. With the small amount of memory available in most arduino's, this often leads to memory issues and hard to diagnose problems when a sketch that seemingly works well suddenly freezes or reboots.

Wow! Thank you david_2018!! You sir are gold!!!

I used the added code that you created and it worked. I used both decimal 13 and hex 0X0D to see what would happen and sure enough the carriage return symbol was removed! I would not have recognized the carriage return “^M” had you not identified it. I did not know that ^M is a Caret Notation, which is used to represent control characters on a terminal (in my case the app called Serial Bluetooth Terminal). The more I need to learn!

On the topic of the char/byte and String use, thank you for the verification on the data representation of the data being received or not. Also, your assessment on Arduino and String, your knowledge is impressive. Thank you for sharing and helping me out on this. I will attach and post the results on my Cell Phone, which should conclude this aspect of my project. Thank you all for your help and sharing your knowledge with me!! I’m looking forward to the next post.

Thank you, again, david_2018 for the correction and guidance. And PerryBebbington, thank you for your help as well. I am curious on your ESP8266 and the debugging of messages. If you have a link then I'd like to take a look and thank you again.

Below is the corrected code that is displaying the informationt on my Cell Phone using Serial Bluetooth Terminal.

Hello Sapphire,

Glad you got it sorted. I failed to notice what David spotted, which is slightly embarrassing as I am well aware of how to read serial data and that you can't read the same byte twice. No matter, you got your help.

Good luck with your project :slight_smile:

a couple points to make

There is the comment so it’s kinda OK, but for code readability, instead of using numbers if (INCOMING_DATA == 97)    //a on the keypad, why don’t you write directlyif (INCOMING_DATA == 'a')    //'a' has been typed on the keypad

The more worrisome piece for me is this:

if (INCOMING_DATA == 97)    //a on the keypad
       {                                     
       while (Serial1.available())
           {
               //  <do some stuff here>
           }
       }

Remember Serial is an asynchronous protocol, you should not try to second guess what has made it to the Serial buffer or not and remember also that your microprocessor is super fast compared to a Serial line at 115200 bauds → you might end up emptying the Serial1 input buffer faster than data is coming in.

The best way to handle this if you have an end marker for the message you expect to get is to perform your while loop not based on Serial1.available() but based on the fact you have received or not the end marker (and possibly add timeout in case there is a communication error).

I would suggest to study Serial Input Basics to learn more about best practices for dealing with a Serial line.

PerryBebbington:
I don't know the answer to your problem but I am suspicious about using int for incoming data, which I would have thought would arrive in single bytes, not 2 bytes at a time. Storing single bytes in a variable designed for 2 bytes seems to be consistent with losing every other byte, especially as the data actually stores text.

There is nothing getting lost really, you store each byte received in the least significant byte and the most significant byte will just be 0x00

The read() function does actually return an int, so it's actually a good practice to use the int type for storing what the method call returns. Ideally OP should check if the value is -1 which would indicate that the read() call failed for some reason (in practice it does only return -1 when you call read() and there was no byte available)

The read() function does actually return an int

I'm not saying you are wrong, but that seems wrong as serial ports receive incoming date in bytes. I would think the most sensible variable type would be byte, as the serial port does not know what the received data represents.

Hey, J-M-L! Thank you on those points. Especially, the one on my while loop! I have tried an if statement but that doesn’t work as I would hope. And, yes, I am trying to figure out a solution and came to the same conclusion! I’m just not certain what that solution is yet but I’ll post when I do! Again, thank you for pointing that out for me.

I’m not saying you are wrong, but that seems wrong as serial ports receive incoming date in bytes. I would think the most sensible variable type would be byte, as the serial port does not know what the received data represents.

This arises because the returned value is unsigned, and may carry any byte/char value between 0-255.

The value of -1 would otherwise be read as 255 (signed byte), so they had to use a signed to carry the possibility of indicating -1 for an ‘empty’ buffer.