Trouble with incoming serial bytes being read incorrectly (or something)

milesg

Member
Hey all, I've got another weird one for you! This one is driving me absolutely nuts, but I think I've boiled it down to the core issue, so hopefully someone can point me in the right direction. Buckle up! :p

So, in short, I'm trying to write a little function that'll interpret some EI-Bisynch commands sent over serial to the Teensy. Nothing was working, so I made this example code which illustrates what things aren't working. Note, that I have gotten identical results out of 2 Teensy 4.1s.

Code:
#include <Arduino.h>
void getEIBisynch();
void parseEIBisynch(String input);

String inputString="";

void setup() {
  Serial3.begin(9600, SERIAL_7E1);
  Serial.begin(9600);
}

void loop() {
} 

void serialEvent3() {
  getEIBisynch();
}

void getEIBisynch() { // Read all bytes into inputString until an ETX or ENQ is received
  inputString=""; // start with empty string
  while (Serial3.available()>0) {
    char inChar = Serial3.read();
    inputString += inChar; // add it to the string
    delay(2);
    if (inChar == '\x03' || inChar == '\x05') { // \x03 is End of Transmission, \x05 is Enquiry.
      parseEIBisynch(inputString); // presumably a complete command. Send it to be parsed
      break;
    }
  }
}

void parseEIBisynch(String input) {
  // assemble expected string to compare with input
  // String testA = '\x04'+"3322V"+'\x05'; // I don't know why this doesn't work, but whatever.
  String testA = '\x04';
  testA += "3322PV";
  testA += '\x05';

  // Send data to Serial Monitor:
  Serial.print("input: ");
  Serial.println(input);
  Serial.println("input Binary:");
  for (int i=0; i<input.length(); i++) {
    Serial.println(input.charAt(i), BIN);
  }
  delay(250);
  Serial.print("testA: ");
  Serial.println(testA);
  delay(250);
  Serial.println("testA Binary:");
  for (int i=0; i<testA.length(); i++) {
    Serial.println(testA.charAt(i), BIN);
  }
  Serial.print("input.indexOf(Prefix): ");
  Serial.println(input.indexOf("3322"));
  delay(250);
  Serial.print("testA.indexOf(Prefix): ");
  Serial.println(testA.indexOf("3322"));

  // Echo the received data back to the device
  Serial3.print(input); 
}

As you can see above, I'm simply reading in the data sent from my PC's serial terminal, printing out the data and some comparison strings(in binary so I can see what's wrong) to my VSCode terminal, and then sending the received data back to my PC serial port.

But you can clearly see here in my VSCode terminal, that my 2s and EOTs aren't being received correctly:
VSCode Terminal.JPG
This is manifesting in this example by having a failure to match strings with indexOf(). Whoops: Ignore "Prefix" in these last 2 lines of this screenshot. That was just something leftover from before. You can see the actual code is just comparing with "3322".

The real crazy thing is that when I send it back, everything goes out correctly (screenshot of my PC's serial terminal app connected to Serial3 on the Teensy through a MAX3232):
Serial3 ASCII Terminal.JPG

And here's some proof from my logic analyzer that everything is going in/out correctly on the RX/TX of the Teensy's port:
Serial3 RX-TX.jpg

Any idea why I'm getting junk data out of some of my received characters? How is it possible that I can send that same junk back and it looks good on the other end?

I haven't tried much more than the alphanumeric characters in this example, but I know '1' also doesn't work. And I expect others to behave this way too... Perhaps I'll try that next to see how far this issue reaches.
 
Last edited:
The 8 bits you read are 7 bits of data and the parity bit (in the high order position).
The character '3' is hex 0x33 = 00110011. There are an even number of bits in the 7 data bits so the high order bit is zero.
But the character '2' is hex 0x32 = 00110010. There are an odd number of bits in the data bits so when you receive it, it has the high order bit set and you print 10110010.
Same goes for EOT. It is binary 00000100 but it is odd parity so you receive it as 10000100 with the parity bit set.

Pete
 
P.S. to clarify: that is why you don't match EOT. You are looking for 0x04, but it is received as 0x84. And you can match '3' because it is already even parity, but you can't match '2' because it is received as 0xB2.
The easiest fix might be to strip parity from the message as it is received so that a comparison will work.

Pete
 
Wow! Thanks for the quick answer, I knew something fishy was going on, but it was clearly outside of my knowledge. I really appreciate it!

I had assumed that since I started that port with Serial3.begin(9600, SERIAL_7E1); that it'd interpret the full byte as-sent, but deliver them to my String as their basic ASCII value. I guess not.

I know for sure that the instruments which will be communicating with this Teensy are always going to be configured to send/receive in 7E1. Any thoughts on how I can easily strip the parity bit from the offending characters? Or somehow read them in without that bit from the get-go?

From earlier testing I believe my stripped characters (or characters declared in the program) will still be sent out correctly so that the receiving device wont have any issues. Does this sound correct?

Thanks again Pete!
 
Bingo!
I just added:

Code:
bitClear(inChar, 7);

after the Serial.read();

Unless anyone has a good reason why this'll end up screwing me, I think I'll proceed to develop my function with that line in place.

Thank you Pete, you do live up to your screen name :)
 
The bitClear will fix the incoming parity issue. You've implied that the parity bit is added to transmitted characters so you should be OK.

Pete
 
Back
Top