0
votes

Background: I was trying to create a system that would be able to read serial data from an incoming Serial.print, Serial.println, or Serial.write message. Then, after parsing the incoming message, save the text as a variable which would then be printed onto an LCD or a different Serial port. I was able to get Serial.write messages working successfully, but I ran into issues when trying to parse Serial.print messages. Since Serial.print messages convert the binary ASCII characters to Base 10 ASCII prior to sending it, and since Serial communication sends one character at a time when communicating, I was unable to separate a message into its individual ASCII characters after receiving it. For example, when the text "red" was sent, '11410110010' was received. Similarly "test" returned '11610111511610'. (please note that the '10' appended to the end of both of them are the newline ['\n'] characters)

In search of a solution to this problem, I tried to see how the Arduino IDE does it via viewing the source code of the Serial Monitor on GitHub. This is what I found with my limited understanding of Java:


Here is the code and hardware that I was using if it is helpful. Aside from that, if any other information is needed, please tell me.

Sender Device: Sparkfun Pro Micro

Receiver Device: Arduino Duemilonove

Pin 14 of the Pro Micro is connected to Pin 9 of the Duemilonove

Pin 16 of the Pro Micro is connected to Pin 8 of the Duemilonove

The LCD is configured properly to the Duemilonove with the pins found in the Receiver Code

Sender Code (Pro Micro):

//If anything is sent from the Arduino IDE's Serial Monitor to the Device,
//foreword that message to the device connected to its Software Serial pins (The Receiver/ The Duemilonove)

#include <SoftwareSerial.h>
SoftwareSerial mySerial(14, 16);

void setup() {
  Serial.begin(115200);
  mySerial.begin(115200);
}

void loop() {
  if (Serial.available()) {      // If anything comes in Serial (USB),
    mySerial.print(Serial.read());   // read it and send it out mySerial (Software Serial)
  }
}

Receiver Code (Duemilonove):

#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
//SoftwareSerial mySerial(14, 16); for pro micro
SoftwareSerial mySerial(8, 9); //for Uno or Duemilanove
char lineOne[16];
char lineTwo[16];
char tempChar;
bool change = false;
bool newLineBuffer = false;

void setup() {
  Serial.begin(115200);
  mySerial.begin(115200);
  lcd.begin(16, 2);
}

void loop() {
  SerialCheck();
  newLineShift();
  updateLCD();
}
void SerialCheck() {
  if (mySerial.available()) {      // If anything comes in mySerial (Software Serial Port),
    tempChar=mySerial.read();
    change=true;
  }

  if (Serial.available()) {     // If anything comes in Serial (USB port)
    tempChar=Serial.read();
    change=true;
  }
}
void newLineShift(){
  if(change){
    if(tempChar=='\n'){
      if(newLineBuffer){
        lineChange();
      }else{
        newLineBuffer=true;
      }
    }else{
      if(newLineBuffer){
        lineChange();
      }
      for (byte i = 0; i < 15; i = i + 1) {
        if(!lineOne[i]=='\0'){
          //Do nothing lol
        }else{
          lineOne[i]=tempChar;
          break;
        }
      }
      newLineBuffer=false;
    }
  }
  
}
void updateLCD(){
  if(change){
    lcd.clear();
    Serial.println("Line Two is: "+ (String)lineTwo);
    lcd.setCursor(0, 0);
    lcd.print(lineTwo);
    Serial.println("Line One is: "+ (String)lineOne);
    lcd.setCursor(0, 1);
    lcd.print(lineOne);
  }
  change=false;
  tempChar='\0';
}
void lineChange(){
  for (byte i = 0; i < 15; i = i + 1) {
      lineTwo[i]=lineOne[i];
      lineOne[i]='\0';
    }
}
1
Instead of finding the ASCII string representation of the decimal code of an individual ASCII character (which potentially turns 1 byte into 3), why not just transmit the original character?JohnFilleau
If it helps, the requirement was to able to understand things that were sent via Serial.print or Serial.write to a device that you are not allowed to change the code of. If I were able to, I would just make everything Serial.write messages and leave it at that.SpiritSeal

1 Answers

0
votes

read() returns an int. They do this so it can return -1 when there is nothing there to read. Normally we're only interested in the byte that was read which is in the low 8 bits.

So when you write this:

mySerial.print(Serial.read());

the version of print that gets called is the one for printing an int variable. That version breaks the number down into ascii and the '114' from the r in red becomes a '1', a '1', and a '4'.

Instead you want to call the version for printing a char. You're only worried about the char variable that was read anyway. So try this:

char c = Serial.read();
mySerial.print(c);

or even:

mySerial.print((char)Serial.read());

and that will get you the version of print that you want.

Alternatively you can just write the byte that you read back directly by using write instead of print. Since write sends the byte out exactly as is, it will send the 114 byte just like it read it and you'll see 'r' on the other end.

mySerial.write(Serial.read());