Unsigned Bytes from Arduino Misbehaving


#1

Hello everyone,

I’m having some issues with data I’m reading from an Arduino Uno.

Essentially I’m using the Arduino as a DAQ and sending over 4 analog inputs over the Serial. The first two inputs (A0 and A1) are single bytes. The second inputs (A2 and A3) are arrays of two bytes each. I’m sending them using the Arduino Serial.write() function which writes them directly in binary. I send the data in the following format over the Serial: A0A1A2A3/n. My Processing script then reads whatever I sent until /n. This constitutes one reading. I perform a reading and send the values every 2000us (such that sampling freq = 500Hz).

They are sending fine - if I print on Arduino what I’m sending there is no issue. The problems is in Processing.

If I connect a potentiometer to the analog inputs and increase the pot’s output from 0 to 5V I see that my A0 and A1 (single bytes) as read on Processing increase fine until the value 127 at which they jump around from 30, 255, and other values. This happens until, after increasing the pot output further, it settles at 160 and increases normally up to 255 (the 5V limit). Why is it jumping like this at 127 and why doesn’t it increase normally, linearly, until 160?

I understand that Arduino bytes are unsigned whereas Processing bytes are signed. I read and saw an easy conversion that I integrated into my code (essentially adding & 0xff to the read byte). I’ve been playing around with this conversion trying different things but to no avail.

Here is my code:


void serialEvent(Serial myPort) {
  try {
    val = myPort.readStringUntil('\n');    //The newline separator separates each Arduino loop. We will parse the seperate readings by each newline separator.
    if (val!= null) { //We have a reading! Record it.

      val_char = val.toCharArray();

      if (val_char.length == 7) { // If the data was transmitted correctly - it will consist of 7 bytes (A0 =1, A1 = 1, A2 = 2, A3 = 2, \n =1.

        val_int[0] = int(byte(val_char[0]) & 0xff);
        val_int[1] = int(byte(val_char[1]) & 0xff);
        val_int[2] = int(byte(val_char[2]) & 0xff);
        val_int[3] = int(byte(val_char[3]) & 0xff);
        val_int[4] = int(byte(val_char[4]) & 0xff);
        val_int[5] = int(byte(val_char[5]) & 0xff);

        electro_val_code[0] = val_int[0];
        electro_val_code[1] = val_int[1];

        hemo_val_code[0] = (val_int[2]*256) + val_int[3]; // Translating the two bytes into a single int.
        hemo_val_code[1] = val_int[4]*256 + val_int[5]; 

        print(electro_val_code[0]); 
        print(',');
        print(electro_val_code[1]); 
        print(',');
        print(hemo_val_code[0]); 
        print(',');
        println(hemo_val_code[1]); 

Thanks!

R


#2

Hi TheGankerer, I tryed to convert char in int(byte(val_char[0]) & 0xff) and it woks fine…
Have You tryed in processing to look the variable val with println("val = " + val);?
Can You post the Arduino Serial.write() Statement?
I think the problem are in read or write statement…


#3

Hi Dennis,

Yeah I think the conversion works “fine”. If I do int(byte(val_char[0]) & 0xff) it works. The values printed in processing work fine from 0-~127 and ~160-255. Its between ~127 - ~ 160 where the values jump around and dont increase linearly as they should.

I have already tried printing the val_int values instead of the electro_val_code and hemo_val_code in processing. It’s the same problem.

The entire Arduino code is:

#define sampling_interval_hemo_us 2000U // The imposed sampling interval in microseconds.

unsigned long previous_micros_hemo = 0; 
unsigned int delta_micros_hemo = 0;

byte a0_val = 0;
byte a1_val = 0;
unsigned int a2_val = 0;
unsigned int a3_val = 0;

void setup() {
  Serial.begin(115200);   // Initialize serial communication at 115200 bits per second.
}

void loop()
{

  delta_micros_hemo = micros() - previous_micros_hemo; // The time difference between the current time and the previous hemodynamic sample.

  if ((delta_micros_hemo) >= sampling_interval_hemo_us) // If the delta is bigger than the hemodynamic sampling_interval -> Take new hemodynamic samples!
  {

    Serial.flush();
    a0_val = analogRead(0)/4; // The /4 is to scale the range from 0-1023 to a byte range 0-255.
    a1_val = analogRead(1)/4;
    a2_val = analogRead(2);
    a3_val = analogRead(3);

    // Write A0 (Byte)
    Serial.write(a0_val);

    // Write A1 (Byte)
    Serial.write(a1_val);
    
    // A2 (2 Byte) Buffer
    byte buf_a2[2];
    buf_a2[0] = (a2_val >> 8) & 255;
    buf_a2[1] = a2_val & 255; 
    Serial.write(buf_a2,2);

    // A3 (2 Byte) Buffer
    byte buf_a3[2];
    buf_a3[0] = (a3_val >> 8) & 255;
    buf_a3[1] = a3_val & 255;
    Serial.write(buf_a3,2);
    Serial.print('\n');

    previous_micros_hemo = micros();  
  }

delay(0.1);
}```

I'm sure that the arduino code is working because I printed (a0_val) (not shown in code above) and the values increase linearly and in a stable manner from 0-255 without any funny stuff.

Thanks Dennis

#4

Ok, Tonight I try to reproduce all Your system …
Can You post the Processing Code?
I’m curious to understand what not work.


#5

Sure!

The entire Arduino code is:

#define sampling_interval_hemo_us 2000U // The imposed sampling interval for the hemodynamic channels, in microseconds. 1000us -> fs= 1kHz. 2000us -> fs=500Hz. 1428us -> 700Hz. 

// For the hemodynamic channels
unsigned long previous_micros_hemo = 0;
unsigned int delta_micros_hemo = 0;

byte a0_val = 0;
byte a1_val = 0;
unsigned int a2_val = 0;
unsigned int a3_val = 0;

void setup() {
  Serial.begin(115200);   // Initialize serial communication at 115200 bits per second.
}

void loop()
{

  delta_micros_hemo = micros() - previous_micros_hemo; // The time difference between the current time and the previous hemodynamic sample.

  if ((delta_micros_hemo) >= sampling_interval_hemo_us) // If the delta is bigger than the hemodynamic sampling_interval -> Take new hemodynamic samples!
  {

    Serial.flush();
    a0_val = analogRead(0) / 4;
    a1_val = analogRead(1) / 4;
    a2_val = analogRead(2);
    a3_val = analogRead(3);

    previous_micros_hemo = micros();

    // Write A0 (Byte)
    Serial.write(a0_val);

    // Write A1 (Byte)
    Serial.write(a1_val);

    // A2 (2 Byte) Buffer
    byte buf_a2[2];
    buf_a2[0] = (a2_val >> 8) & 255;
    buf_a2[1] = a2_val & 255;
    Serial.write(buf_a2, 2);

    // A3 (2 Byte) Buffer
    byte buf_a3[2];
    buf_a3[0] = (a3_val >> 8) & 255;
    buf_a3[1] = a3_val & 255;
    Serial.write(buf_a3, 2);
    
    Serial.print('\n');
  }

  delay(0.1);
}

The entire Processing code is:

// Same as v1 but expecting a input stream of 2-bytes per analog channel.

import processing.serial.*;
Serial myPort; //creates a software serial port on which you will listen to Arduino

int fs = 500; // The original Arduino code's sampling frequency.
int rec_length = 60; // The length of the recording before we write the file, in seconds.
int[] val_int = {0, 0, 0, 0, 0, 0}; // The array storing the analog input values as ints (rather than their binary 'char' format).
int[] electro_val_code = {0, 0};
int[] hemo_val_code = {0, 0};

long numReadings = fs*rec_length; // Keeps track of how many readings you'd like to take before writing the file. 

int readingCounter = 0; // Counts each reading to compare to numReadings.

char[] val_char;

String fileName, val, month;
String str_file_name = "v4_test";

void setup()
{
  String portName = Serial.list()[1]; // '1' corresponds to COM6.

  myPort = new Serial(this, portName, 115200); //set up your port to listen to the serial port
  
}

void serialEvent(Serial myPort) {
  try {
    val = myPort.readStringUntil('\n');    //The newline separator separates each Arduino loop. We will parse the data by each newline separator.
    if (val!= null) { //We have a reading! Record it.

      val_char = val.toCharArray();

      if (val_char.length == 7) {

        val_int[0] = int(byte(val_char[0]) & 0xff);
        val_int[1] = int(byte(val_char[1]) & 0xff);
        val_int[2] = int(byte(val_char[2]) & 0xff);
        val_int[3] = int(byte(val_char[3]) & 0xff);
        val_int[4] = int(byte(val_char[4]) & 0xff);
        val_int[5] = int(byte(val_char[5]) & 0xff);

        electro_val_code[0] = val_int[0];
        electro_val_code[1] = val_int[1];

        hemo_val_code[0] = (val_int[2]*256) + val_int[3];
        hemo_val_code[1] = val_int[4]*256 + val_int[5];
        
        print(electro_val_code[0]); 
        print(',');
        print(electro_val_code[1]); 
        print(',');
        print(hemo_val_code[0]); 
        print(',');
        println(hemo_val_code[1]); 

      }
    }
  }
  catch(RuntimeException e) {
    e.printStackTrace();
  }
}

void draw()
{

}

#6

I find where are the problem, in the processing code at line 30:

myPort.readStringUntil('\n');

this instruction read a String and not a byte (sent from Arduino)
I changed this line in:

val_byte = myPort.readBytesUntil(10);

(the number 10 represent the ln for carriage return)
now the Sketch Works fine…

this is the complete code:

// Same as v1 but expecting a input stream of 2-bytes per analog channel.

import processing.serial.*;
Serial myPort; //creates a software serial port on which you will listen to Arduino

int fs = 500; // The original Arduino code's sampling frequency.
int rec_length = 60; // The length of the recording before we write the file, in seconds.
int[] val_int = {0, 0, 0, 0, 0, 0}; // The array storing the analog input values as ints (rather than their binary 'char' format).
int[] electro_val_code = {0, 0};
int[] hemo_val_code = {0, 0};

long numReadings = fs*rec_length; // Keeps track of how many readings you'd like to take before writing the file. 

int readingCounter = 0; // Counts each reading to compare to numReadings.

byte[] val_byte = new byte[7];

String fileName, val, month;
String str_file_name = "v4_test";

void setup()
{
  String portName = Serial.list()[1]; // '1' corresponds to COM6.

  myPort = new Serial(this, portName, 115200); //set up your port to listen to the serial port
}

void serialEvent(Serial myPort) {
  try {
    val_byte = myPort.readBytesUntil(10);    //The newline separator separates each Arduino loop. We will parse the data by each newline separator.
    if (val_byte != null) { //We have a reading! Record it.

      if (val_byte.length == 7) {

        val_int[0] = int(byte(val_byte[0]) & 0xff);
        val_int[1] = int(byte(val_byte[1]) & 0xff);
        val_int[2] = int(byte(val_byte[2]) & 0xff);
        val_int[3] = int(byte(val_byte[3]) & 0xff);
        val_int[4] = int(byte(val_byte[4]) & 0xff);
        val_int[5] = int(byte(val_byte[5]) & 0xff);

        electro_val_code[0] = val_int[0];
        electro_val_code[1] = val_int[1];

        hemo_val_code[0] = (val_int[2]*256) + val_int[3];
        hemo_val_code[1] = val_int[4]*256 + val_int[5];

        print(electro_val_code[0]); 
        print(',');
        print(electro_val_code[1]); 
        print(',');
        print(hemo_val_code[0]); 
        print(',');
        println(hemo_val_code[1]);
      }
    }
  }
  catch(RuntimeException e) {
    e.printStackTrace();
  }
}

keep us up to date…


#7

YESSS IT WORKS!

Thank you Dennis!!! I would never have got this on my own!