Problem with split() and serialEvent

I’m trying to send data from Arduino to Processing.

On the Arduino file, the code prints the value of the sensor (I’m only using one sensor) every time a button is pressed (only using one button). I just need 9 values, so in case it prints a tenth, it prints it on a new line.

Here is how the string comes out in Arduino Serial Monitor.

113,206,46,212,102,195,211,114,33,

Arduino code:

//Constants(won't change), variables (change):
const int buttonPin = 8;   
const int flexPin = A0; //pin A0 to read flex sensor - analog input
const int speakerPin = 13;
bool takeAnalogReadings(uint16_t* p_numReadings = nullptr, uint16_t** p_analogVals = nullptr);

int buttonState = 0; //counts the number of button presses
int sensorValue = 0; //save flex sensor - analog value
int sensorMin = 20;  // minimum sensor value
int sensorMax = 600;   // maximum sensor value
 

void setup(){
  Serial.begin(9600);       //Begin serial communication
  

  // calibrate flex sensor during the first three seconds
  while (millis() < 3000) {
      sensorValue = analogRead(flexPin);
    // record the maximum sensor value
    if (sensorValue > sensorMax) {
      sensorMax = sensorValue;
    }
    // record the minimum sensor value
    if (sensorValue < sensorMin) {
      sensorMin = sensorValue;
    }
 }

 //Serial.println("\nBegin\n");

}

void loop(){
  sensorValue = analogRead(flexPin);         //Read and save analog value from flex sensor
  buttonState = digitalRead(buttonPin);
  sensorValue = map (sensorValue, sensorMin, sensorMax, 10, 500);
  sensorValue = constrain(sensorValue, 10, 500);
  

    if (buttonState == HIGH){  
      uint16_t numReadings;
      uint16_t* analogVals;
      bool readingsDone = takeAnalogReadings(&numReadings, &analogVals);
      if (readingsDone)
      {
        Serial.println();
      }
    }
   }
  
bool takeAnalogReadings(uint16_t* p_numReadings, uint16_t** p_analogVals) {
  static const uint16_t NUM_READINGS = 9;
  static uint16_t i = 0; // index  
  static uint16_t analogVals[NUM_READINGS];
  
  bool bufferIsFull = false; // set to true each time NUM_READINGS have been taken
  analogVals[i] = sensorValue;
  Serial.print(analogVals[i]); Serial.print(",");
  delay(1000);
  i++;
  if (i >= NUM_READINGS)
    {
      bufferIsFull = true;
      i = 0; // reset to beginning of array, so you don't try to save readings outside of the bounds of the array
    }

  // Assign the user-passed-in pointers so that the user can retrieve the data if they so desire to do it this way
  if (p_numReadings != nullptr){
    *p_numReadings = NUM_READINGS;
  }
  else if (p_analogVals != nullptr){
    *p_analogVals = analogVals;
  }
  return bufferIsFull;
  }
    

On Processing, I’m trying to split the data into separate float values to then use them to draw ellipses.
So the first value will be x1, the second value will be x2, etc… The first problem I encounter is that I can’t see the values on the console even if I print them. The second problem is that it seems like the split() is not breaking down the data into the different float variables so the ellipses are not drawn. The port and baud are correct. Any ideas of what could I’ve been doing wrong?

Processing code:

import processing.serial.*;

Serial myPort; //Serial port
String inString; //Input string from serial port
int lf = 10; //ASCII linefeed
float x1, x2, x3, x4, x5, x6, x7, x8, x9;
boolean dataReceived;



void setup() {
  printArray(Serial.list());
  myPort = new Serial(this, Serial.list()[1], 9600);
  myPort.bufferUntil(lf);
  
  size (800,800);
  delay(1000);
  
  x1 = 0;
  x2 = 0;
  x3 = 0;
  x4 = 0;
  x5 = 0;
  x6 = 0;
  x7 = 0;
  x8 = 0;
  x9 = 0;
  
  dataReceived = false;
  
}
 
 
 
void draw() {
    if (dataReceived){
      println (x1, x2, x3, x4, x5, x6, x7, x8, x9);
      dataReceived = false;
    }
    background (240);
    noStroke();
    
    ellipse(200, 200, x1, x1);
    ellipse(400, 200, x2, x2);
    ellipse(600, 200, x3, x3);
    ellipse(200, 400, x4, x4);
    ellipse(400, 400, x5, x5);
    ellipse(600, 400, x6, x6);
    ellipse(200, 600, x7, x7);
    ellipse(400, 600, x8, x8);
    ellipse(600, 600, x9, x9);
      
    fill(218, 142, 114);
     
}


void serialEvent(Serial p){
  inString = p.readString();
  if (inString!= null) {
    dataReceived = true;
    //split values with comma
    String[] list = split(inString, ',');
    if (list.length > 1){
    //assign values in processing

    x1 = float(list[0]);
    x2 = float(list[1]);
    x3 = float(list[2]);
    x4 = float(list[3]);
    x5 = float(list[4]);
    x6 = float(list[5]);
    x7 = float(list[6]);
    x8 = float(list[7]);
    //trim the last element in list to remove the line feed character
    x9 = int(trim(list[8]));
    
    printArray(list);
    }
  }
}

I tried using these two examples, but neither of them worked for me.

Thank you in advance.

1 Like

Try this right after you receive string:
println(inString);

Try a delay() in setup() of Processing:

I like to test code on receiving side with simulated data:

String s = "113,206,46,212,102,195,211,114,33," + "\n";

print(s);

s = s.trim(); // Trims that \n before processing string

print(s);
println();

println(s);

String [] splitData = split(s, ',');

printArray(splitData);
printArray(float (splitData));

println(float(splitData[0]));

float [] splitFloats = float(split(s, ','));

printArray(splitFloats);

:)

1 Like

Thank you! it seems to work now.

Hello,

Can you share what worked?

I work a lot with Arduino communications and it helps me as well.

Thanks!

:)

Sure! I just needed to add the println(inString) as you mentioned and incremented the delay in Processing. Here both codes. You’ll see that I added extra things but for personal decision.

Arduino code:

//Constants(won't change), variables (change):
const int buttonPin = 8;   
const int flexPin = A0; //pin A0 to read flex sensor - analog input
const int speakerPin = 13;
bool takeAnalogReadings(uint16_t* p_numReadings = nullptr, uint16_t** p_analogVals = nullptr);

int buttonState = 0; //counts the number of button presses
int sensorValue = 0; //save flex sensor - analog value
int sensorMin = 20;  // minimum sensor value
int sensorMax = 600;   // maximum sensor value
 

void setup(){
  Serial.begin(9600);       //Begin serial communication
  

  // calibrate flex sensor during the first three seconds
  while (millis() < 1000) {
      sensorValue = analogRead(flexPin);
    // record the maximum sensor value
    if (sensorValue > sensorMax) {
      sensorMax = sensorValue;
    }
    // record the minimum sensor value
    if (sensorValue < sensorMin) {
      sensorMin = sensorValue;
    }
 }

 //Serial.println("\nBegin\n");

}

void loop(){
  sensorValue = analogRead(flexPin);         //Read and save analog value from flex sensor
  buttonState = digitalRead(buttonPin);
  sensorValue = map (sensorValue, sensorMin, sensorMax, 10, 500);
  sensorValue = constrain(sensorValue, 10, 500);
  
    if (buttonState == HIGH){  
      uint16_t numReadings;
      uint16_t* analogVals;
      bool readingsDone = takeAnalogReadings(&numReadings, &analogVals);
      if (readingsDone)
      {
        Serial.println();
      }
    }
   }
  
bool takeAnalogReadings(uint16_t* p_numReadings, uint16_t** p_analogVals) {
  static const uint16_t NUM_READINGS = 9;
  static uint16_t i = 0; // index  
  static uint16_t analogVals[NUM_READINGS];
  
  bool bufferIsFull = false; // set to true each time NUM_READINGS have been taken
  analogVals[i] = sensorValue;
  Serial.print(analogVals[i]); Serial.print(",");
  delay(1000);
  i++;
  if (i >= NUM_READINGS)
    {
      bufferIsFull = true;
      i = 0; // reset to beginning of array, so you don't try to save readings outside of the bounds of the array
    }

  // Assign the user-passed-in pointers so that the user can retrieve the data if they so desire to do it this way
  if (p_numReadings != nullptr){
    *p_numReadings = NUM_READINGS;
  }
  else if (p_analogVals != nullptr){
    *p_analogVals = analogVals;
  }
  return bufferIsFull;
  }
  

and Processing code:

import processing.serial.*;

Serial myPort; //Serial port
String inString; //Input string from serial port
int lf = 10; //ASCII linefeed
float x1, x2, x3, x4, x5, x6, x7, x8, x9;
boolean dataReceived;



void setup() {
  //printArray(Serial.list());
  String portName = Serial.list()[1]; 
  myPort = new Serial(this, portName, 9600);
  myPort.bufferUntil(lf);
  
  size (800,800);
  delay(2000);
  
  x1 = 0;
  x2 = 0;
  x3 = 0;
  x4 = 0;
  x5 = 0;
  x6 = 0;
  x7 = 0;
  x8 = 0;
  x9 = 0;
  
  dataReceived = false;
  
  fill(random(255), random(255), random(255), 100);
  
}
 
 
 
void draw() {
    if (dataReceived){
      //println (x1, x2, x3, x4, x5, x6, x7, x8, x9);
      dataReceived = false;
    }
    background (240);
    noStroke();
    
    ellipse(200, 200, x1, x1);
    ellipse(400, 200, x2, x2);
    ellipse(600, 200, x3, x3);
    ellipse(200, 400, x4, x4);
    ellipse(400, 400, x5, x5);
    ellipse(600, 400, x6, x6);
    ellipse(200, 600, x7, x7);
    ellipse(400, 600, x8, x8);
    ellipse(600, 600, x9, x9);
      
     
}


void serialEvent(Serial p){
  inString = p.readString();
  if (inString!= null) {
    dataReceived = true;
    println(inString);
    //split values with comma
    String[] list = split(inString, ',');
    //if (list.length > 1){
    //assign values in processing

    x1 = (float(list[0]) * 1.3);
    x2 = (float(list[1]) * 1.3);
    x3 = (float(list[2]) * 1.3);
    x4 = (float(list[3]) * 1.3);
    x5 = (float(list[4]) * 1.3);
    x6 = (float(list[5]) * 1.3);
    x7 = (float(list[6]) * 1.3);
    x8 = (float(list[7]) * 1.3);
    //trim the last element in list to remove the line feed character
    x9 = (int(trim(list[8])) * 1.3);
    
    //printArray(list);
    //}
  }
}

Thanks again!

1 Like

Hello,

I am pleased that you got this working!
I usually test things here on my end (I have all the toys!) but busy working at home.
Very busy these days!

:)