Multiple values for incoming data being printed

Hi,
I had a problem with my Processing data collection: essentially when my data comes in from the Arduino and to Processing, I save it onto a csv file. However, on the csv file it so happens that a value for one time stamp, such as 16 seconds and 5 milliseconds, get printed many many times onto the file, and its corresponding output. Does anyone know why this happens and what I can do to prevent it? I essentially want one time stamp to correspond to one value.

Hi @saaqib.m We really need to see the code, for Processing and Arduino, each in a code block.

As well as that, try this. Use the Arduino IDE’s Serial Monitor to look at what’s coming from the Arduino. That is just as often as you expect it? e.g. one every second? So you know the problem is not in the Arduino code? (Now we need the Processing code.)

Hi Richard,

Thank you for your response, here are some snippets of the code, all of which are relevent:

Arduino:

#include <SoftwareSerial.h> 
int analog_output;                         //Serial Read output
int sample_output;
int r_pin = A0;                              //Initialising output pin
unsigned long delayStart = 0;          // the time the delay started
unsigned long DELAY_TIME = 5000;       //1500 is equal to 1.5 seconds
int value;
int i = 0;

void setup() {              
  Serial.begin(9600);           // Starting serial communication at 9600 Baud Rate
  delayStart = millis();      //start delay
}

void loop() {
  analog_output = analogRead (r_pin);    // Reading from the resistor
  Serial.print(analog_output);        // Sending the output to Processing IDE
  Serial.print(' ');
  Serial.println(0);


  if (delayStart % DELAY_TIME  == 0) { 
    Serial.print(analog_output);
    Serial.print(' ');
    Serial.println(analog_output);

  }
i++;
}

Processing:

Serial myPort;                           // The serial port - object from serial class
String[] list = new String[3];           // For serial port
boolean newData = false;                 // Sets incoming data to false at the beginning
float inByte;                            // For incoming serial data
int xPos = 0;                            // Horizontal position of the graph (from bottom of screen) 
String inString;                         // Data recieved from serial port
int lastxPos=0;                          // X position from (0,0) of graph 
int lastheight=700;                      // Y position from (0,0) of graph 
                                         // - (Also Y length of graph)
                                         // Note: This number should be the Y value of the size() function in void setup()
int X = 1000;                            // X length of graph                     
                                         // Note: This number should be the X value of the size() function in void setup()
int halflength = X/2;       
String Timer = "Time Elapsed: ";
int boxLength = 700;
int rectSize = 30;
int min;
int sec;
int millisec;
int msec = millis()/1000;
float Sfreq = 1;
//float TSfreq = 1/Sfreq;

Table table;

void setup () {
  size(1000, 700);                               // Set the window size:   
  smooth();
  String portName = Serial.list()[0];
  myPort = new Serial(this,portName, 9600);    // A serialEvent() is generated when a newline character is received
  myPort.bufferUntil('\n');                     // Sets a specific byte to buffer until before calling serialEvent()
  background(0);                              // Set inital background colour
    

  table = new Table();
  table.addColumn("Time Elapsed: ");
  table.addColumn("Signal ADC Value: ");
  table.addColumn("Voltage (V): ");
  table.addColumn("Sampled Value: ");
  
  frameRate(60);
}

void serialEvent (Serial myPort) {
  // get the ASCII string:
  inString = myPort.readStringUntil('\n');
  //println(inString);
  String [] splitstr = splitTokens(inString);
  if (splitstr[0] != null) {
    //inString = trim(inString);                          // trim off whitespaces.
    inByte = float(trim(splitstr[1]));                    // convert to a number.
    float inScreen = map(inByte, 0, 1023, 0, height);     // map to the screen height.
    println(inScreen);
    newData = true; 
  }

  Vout = 5*inByte/1023;
  
  TableRow newRow = table.addRow();
  newRow.setString("Time Elapsed: ", txt);
  newRow.setFloat("Signal ADC Value: ", inByte);
  newRow.setFloat("Voltage (V): ",Vout);
  if (splitstr[1] != null){
  newRow.setFloat("Sampled Value: ",float(splitstr[1]));
  }
}

This should be everything relevant! Let me know if unclear. Thank you.

Hi again @saaqib.m, I’ve run your code in Arduino and Processing. In the draw() of your Ard code there are two blocks of code sending the same value, total of 3 times. I guess you were trying different things. In my version I’ve just used one. I’ve used the loop delay so that it sends twice per second. Let’s keep things slow until it’s right, then speed it up. You need to make sure it’s not too fast for the PC and Processing. I’ve used a zero to terminate and no println(). Println will add \r\n to the output. If you bufferuntil one of those, I think the other will be on the string you’re given, and unless you trim it of it will mess up your csv format. So I’ve used zero.

When I ran your Processing sketch, it never called the serialEvent. I tried to see why, couldn’t so took the serialEvent from the help and changed to bufferUntil(‘0’). Now it just prints the numbers received.

I suggest you try both my examples together, they try my Ard program with your Processing sketch (but in there change bufferUntil(’\n’) to (‘0’), and change the port name.

Arduino:

#include <SoftwareSerial.h>
int aval;
int r_pin = A0;


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

void loop() {  
  aval = analogRead (r_pin);
  Serial.print(aval);
  Serial.print(0);
  delay(500);
}

Processing

import processing.serial.*; 
 
Serial myPort;
String inString;  
 
void setup() { 
  myPort = new Serial(this, "COM18", 9600); 
  myPort.bufferUntil('0'); 
} 
 
void draw() { 
  background(0); 
  text("received: " + inString, 10,50); 
} 
 
void serialEvent(Serial p) { 
  inString = p.readString(); 
  print(inString); print(" ");
}
1 Like

Hi Richard,

Thank you very much for your response and your code is very nice to work with! Allow me to elaborate further. The 2 blocks being printed is my kind of ‘sampling’, it isn’t the most effective right not but that is not the focus. For now every time the time reaches the DELAY_TIME it should print the ‘sampled’ value to the Processing. So from the Arduino I have 2 sets of sets of printed values, one set that prints ALL the data for Processing to draw and the other ‘sampled’ one to store in my table. I then use splitTokens() in my Processing the use array indexing to obtain the right piece of data. I hope that makes sense.

I am still yet to try your buffer(‘0’) and I have been using the ‘\n’ because it was something easy to work with, but I shall also try your method.

I also apologise for the SerialEvent not working properly. If you could tell me what error you obtained then I can help you. I can send my draw() function if needed to!

Again many thanks

Thank you! I shall have a look.

Don’t apologise for your serial event not working. I don’t know why, assumed it worked on your PC but not on mine. I was cutting it down to see how it differed from the example, but gave up.

try this example see how receiving an sending then mange your code

// This example code is in the public domain.
import processing.serial.*;
int bgcolor;   // Background color
int fgcolor;   // Fill color
Serial myPort;      // The serial port
int[] serialInArray = new int[3]; // Where we'll put what we receive
int serialCount = 0;     // A count of how many bytes we receive
int xpos, ypos;     // Starting position of the ball
boolean firstContact = false;  // Whether we've heard from the
          // microcontroller
void setup() {
 size(256, 256); // Stage size
 noStroke();  // No border on the next thing drawn
 // Set the starting position of the ball (middle of the stage)
 xpos = width/2;
 ypos = height/2;
 // Print a list of the serial ports, for debugging purposes:
 println(Serial.list());
 // I know that the first port in the serial list on my mac
 // is always my FTDI adaptor, so I open Serial.list()[0].
 // On Windows machines, this generally opens COM1.
 // Open whatever port is the one you're using.
 String portName = Serial.list()[0];
 myPort = new Serial(this, portName, 9600);
}
void draw() {
 background(bgcolor);
 fill(fgcolor);
 // Draw the shape
 ellipse(xpos, ypos, 20, 20);
}
void serialEvent(Serial myPort) {
 // read a byte from the serial port:
 int inByte = myPort.read();
 // if this is the first byte received, and it's an A,
 // clear the serial buffer and note that you've
 // had first contact from the microcontroller.
 // Otherwise, add the incoming byte to the array:
 if (firstContact == false) {
 if (inByte == 'A') {
  myPort.clear();   // clear the serial port buffer
  firstContact = true;  // you've had first contact from the microcontroller
  myPort.write('A');  // ask for more
 }
 }
 else {
 // Add the latest byte from the serial port to array:
 serialInArray[serialCount] = inByte;
 serialCount++;
 // If we have 3 bytes:
 if (serialCount > 2 ) {
  xpos = serialInArray[0];
  ypos = serialInArray[1];
  fgcolor = serialInArray[2];
  // print the values (for debugging purposes only):
  println(xpos + "t" + ypos + "t" + fgcolor);
  // Send a capital A to request new sensor readings:
  myPort.write('A');
  // Reset serialCount:
  serialCount = 0;
 }
 }
}

arduino

/*
 Serial Call and Response
 Language: Wiring/Arduino
 This program sends an ASCII A (byte of value 65) on startup
 and repeats that until it gets some data in.
 Then it waits for a byte in the serial port, and
 sends three sensor values whenever it gets a byte in.
 Thanks to Greg Shakar and Scott Fitzgerald for the improvements
 The circuit:
 * potentiometers attached to analog inputs 0 and 1
 * pushbutton attached to digital I/O 2
 Created 26 Sept. 2005
 by Tom Igoe
 modified 24 April 2012
 by Tom Igoe and Scott Fitzgerald
 This example code is in the public domain.
 http://www.arduino.cc/en/Tutorial/SerialCallResponse
 */
int firstSensor = 0; // first analog sensor
int secondSensor = 0; // second analog sensor
int thirdSensor = 0; // digital sensor
int inByte = 0;   // incoming serial byte
void setup()
{
 // start serial port at 9600 bps:
 Serial.begin(9600);
 while (!Serial) {
 ; // wait for serial port to connect. Needed for Leonardo only
 }
 pinMode(2, INPUT); // digital sensor is on digital pin 2
 establishContact(); // send a byte to establish contact until receiver
      // responds
}
void loop()
{
 // if we get a valid byte, read analog ins:
 if (Serial.available() > 0) {
 // get incoming byte:
 inByte = Serial.read();
 // read first analog input, divide by 4 to make the range 0-255:
 firstSensor = analogRead(A0)/4;
 // delay 10ms to let the ADC recover:
 delay(10);
 // read second analog input, divide by 4 to make the range 0-255:
 secondSensor = analogRead(1)/4;
 // read switch, map it to 0 or 255L
 thirdSensor = map(digitalRead(2), 0, 1, 0, 255);
 // send sensor values:
 Serial.write(firstSensor);
 Serial.write(secondSensor);
 Serial.write(thirdSensor);
 }
}
void establishContact() {
 while (Serial.available() <= 0) {
 Serial.print('A'); // send a capital A
 delay(300);
 }
}
1 Like

try to use 2 arrays you are using just one

void serialEvent (Serial myPort) {
  // get the ASCII string:
  inString = myPort.readStringUntil('\n');
  //println(inString);
  String [] splitstr = splitTokens(inString);
  if (splitstr[0] != null) {
    //inString = trim(inString);                          // trim off whitespaces.
    inByte = float(trim(splitstr[1]));                    // convert to a number.
    float inScreen = map(inByte, 0, 1023, 0, height);     // map to the screen height.
    println(inScreen);
    newData = true; 
  }

here is 3 arrays

// Add the latest byte from the serial port to array:
 serialInArray[serialCount] = inByte;
 serialCount++;
 // If we have 3 bytes:
 if (serialCount > 2 ) {
  xpos = serialInArray[0];
  ypos = serialInArray[1];
  fgcolor = serialInArray[2];
  // print the values (for debugging purposes only):
  println(xpos + "t" + ypos + "t" + fgcolor);
  // Send a capital A to request new sensor readings:
  myPort.write('A');
  // Reset serialCount:
  serialCount = 0;
 }
1 Like