Problem with parsing data from serial input

hi everyone, i have a java program writing to the serial monitor through the jssc lib a byte value, after reading the serial input basics by robin, and basically copying his example of reading binary data, i have an output format that looks like this <00100> 8 times, now the problem is parsing this data to a byte so i can output it using a shift register, but i have some difficulties with it, basically, i'm saving the recieved bits in a char array, but i can't convert it to a byte value, basically if the each index of the char array read something like 00100, i want to put this value into a byte, i'm using the atoi function but the outputByte outputs the binary value of the integer insted of just storing the value as is, i feel like i'm missing something obvious, i would really aprreciate if someone can guide to the right direction because i'm just newbie.

char recievedByte[8];
byte outputByte;
bool newData = false;
bool recievingData = false;

void setup() {
  Serial.begin(9600);
  setUp();
  Serial.println("write something"); // just a temporarily solution for inputing the data manually
  delay(5000);
}

void loop() {
  readData();  

  if(newData){
    Serial.print("Received Pattern: ");
    Serial.println(outputByte,BIN);
  }
}

void readData(){
  char recievedBit = 0;
  int index = 0;
  while(Serial.available()&& newData == false){
    recievedBit = Serial.read();

    Serial.print("Data: ");
    Serial.println(recievedBit);

    if(recievingData == true){
      if(recievedBit != '>'){
        recievedByte[index] = recievedBit;
        index++;
      }else{
        recievedByte[index] = '\0';
        Serial.println(recievedByte);
        outputByte = atoi(recievedByte);
        recievingData = false;
        index = 0;
        newData = true;
      }
    }else if(recievedBit == '<'){
      recievingData = true;
    }
  }
}

Is there actually a protocol you follow from the java side ? Or just sending 1 byte ?

atoi does not handle binary numbers, it is base 10.

Instead use strtol() which can take a base parameter.

Good question.

Eight numbers separated by comma, or sixteen adjacent hex digits, each on a CR/LF line
would have been my choice.

Here is one way to do it. I am reposting your sketch because there were a few issues I had to fix in it to get it to work properly.

char recievedByte[9];
byte outputByte;
bool newData = false;
bool recievingData = false;

void setup() {
  Serial.begin(9600);
}

void loop() {
  readData();  

  if(newData){
    outputByte = 0;
    for (int i = 0; recievedByte[i] != '\0';i++)
    {
      outputByte = outputByte << 1;
      outputByte |= recievedByte[i] & 0x01;
    }
    Serial.print("Received Pattern: ");
    Serial.println(outputByte, BIN);
    newData = false;
  }
}

void readData(){
  char recievedBit = 0;
  static int index = 0;
  while(Serial.available()&& newData == false){
    recievedBit = Serial.read();

    if(recievingData == true){
      if(recievedBit != '>'){
        recievedByte[index] = recievedBit;
        index++;
      }else{
        recievedByte[index] = '\0';
        recievingData = false;
        index = 0;
        newData = true;
      }
    }else if(recievedBit == '<'){
      recievingData = true;
    }
  }
}

let me rephrase

so you are sending, in ASCII, with '<' as a start marker and '>' as an end marker and your byte is only 5 bits long and you do so 8 times in a row

correct?

what value then do you need to reconstruct? the 8 bytes (with only 5 bits each) or something else? (sounds like a character definition for 5x8 char matrix)

FYI: this version supports any number of bits up to 8 assuming less than 8 bits go in the least significant bits of the output byte. Also, you should probably check to make sure the input characters are only '0' and '1'.

the char buffer is not necessary, you could build the end result byte (or larger) as you go (shift left, add the corresponding bit to the char received)

Agreed. I made the quickest change I had time for. If the char buffer is not needed then I would dispense with it.

no, i'm just sending a string formatted like that <00000>... 8 times

thank you so much it worked! and yes only '0' and '1' are being sent as input.

totally untested, typed here... so mind the bugs and typos but you could try something like this

byte received[8]; // we wait for a sequence of 8 "<binary_byte>" coming through serial.

void printReceived() {
  Serial.print(F("Received: "));
  for (byte b = 0; b < sizeof received; b++) {
    Serial.print(F("0b")); Serial.print(received[b], BIN); Serial.write(' ');
  }
  Serial.println();
}

bool getData() {
  static bool incomingByte = false;
  static byte currentByte = 0;
  int r = Serial.read();  // -1 if there is nothing to read
  switch (r) {
    case '<': incomingByte = true; received[currentByte] = 0; break;
    case '>': incomingByte = false; currentByte++; break;
    case '0':
      if (incomingByte) received[currentByte] <<= 1;
      break;
    case '1':
      if (incomingByte) {
        received[currentByte] <<= 1;
        received[currentByte] |= 1;
      }
      break;
    default: break; // ignore everything else
  }
  if (currentByte >= sizeof received) {
    currentByte = 0;
    return true;
  }
  return false;
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (getData()) { // we received the 8 elements
    printReceived();
  }
}

There is no input error checking, once you have received the '<' whatever comes next if it's 0 or 1 will be added in a byte after shifting the content left but that won't crash (no overflow, the byte just keep accumulating and extra bits get dropped). Once you get the '>' then you are done for that byte and ready for the next one.

Once you got 8 sequences , getData() returns true and the 8 sequences are printed and you are ready for the next 8 ones

try sending (at 9600 bauds) for example

<1><11><111><1111><11111><111111><1111111><11111111>

the output should be (if it works)

Received: 0b1 0b11 0b111 0b1111 0b11111 0b111111 0b1111111 0b11111111

there is no char buffer involved to be parsed afterwards, you get the bytes directly into the array.

yep it worked as expected! thank you so much for your time, i learned a few new things along the way, it didn't came to mind to just simply shift and add the byte, thanks again!

Great
Have fun

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.