Save Data from Arduino to .txt with Processing

Hi,
I’m trying to save my sensor data from the Arduino in a text-file with Processing. Now I really struggle with the Code for Processing. All I want is to save several data from the Arduino into .txt. With my actual Code I always get a “NullPointerException” for my “saveStrings()”-command. In a Sketch before I already generated a .txt-file but there was no vlaues in it. I’m also not sure with the string into sting-array command. I hope you can help me, code below.

Processing-Code:

import processing.serial.*;

Serial myPort;
String vals;
String[] splitvals;

void setup()
{
  String portName = Serial.list()[2];
  myPort = new Serial(this, portName, 9600);
}

void draw()
{
  if (myPort.available() > 0)
  {
    vals = myPort.readStringUntil('\n');
  }
//  println(vals);
  splitvals = split(vals, ' '); 
  saveStrings("meineDatei.txt", splitvals);
}

Thanks! Arpe

i think it is more as question regarding the program flow:

-a- if now new line from arduino is available,
your code try to use the empty / the last vals content

-b- if you save the array ( generated from ONE line ) to the file
( remark: mode overwriting / processing can not append )
the file will contain max only the split-ed last line
writing its array to lines in the file.

-c- also it can work to use the

if (myPort.available()

inside draw, please check on
https://processing.org/reference/libraries/serial/serialEvent_.html


point seems that you try to use data without knowing

  • if there are any and
  • what is the content

so start again, test line by line, and print the content of the data to console,
use a structure with

boolean diagp = true;
//..
if ( diagp ) println(vals);

so you later can disable that diagnostic printing

Thank you very much!
Your hints are very helpfull. I wrote a new Sketch after checking the “serialEvent” command. With the new sketch (see below). I already can save my data, line after line, from the Arduino in a .txt file. Now I have another problem with the saving of the data. My first line after the setup is “Millis Value1 Value2”. After this line I expect my values from the Arduino but before they are indicated, random numbers are indicated. You can see this in the Picture below. Every time I start the Processing-sketch from the beginning, the “random” numbers have another value. Do you have any ideas how I can fix this or where they come from?

Processing sketch:

import processing.serial.*;

Serial myPort;
PrintWriter output;
String val;

void setup()
{
  myPort = new Serial (this, Serial.list()[2], 115200);
  output = createWriter("myFile.txt");
  output.println("Millis"+ "\t" + "Value 1" + "\t" + "Value 2");
}

void draw ()
{
  output.println(val);
}

void serialEvent(Serial s)
{
   String rx = myPort.readStringUntil('\n');
   if (rx!=null)
   {
     val = rx;
   }
}

void keyPressed()
{
  output.flush();
  output.close();
  exit();
}

Picture of the .txt file:

again you try to save to file ?something?
in every draw loop ( 60 times per second )
without knowing that / what data have arrived.

only save to file if new data.

so move the

output.println(val);

out of draw and into serialEvent after

val = rx;

also that is the moment where you should print “val” content to console
so you see that/what data have arrived.


optional:
the concept to export to file with a header line
sounds more like you want/need to make a CSV file
so you should store the data into a
https://processing.org/reference/Table.html
and only on command ( keyboard?) do a onetime
https://processing.org/reference/saveTable_.html

and also this makes it possible to use the data ( from table ) inside the sketch
to draw something with it.


1 Like

I didnt knew that it’s possible to save them in a table. That should be the better way.
Im not sure in some points:
1.) Does the storage into the table have to be in the “serialEvent” to make sure that I only save data if there are new data? If yes, what comes in draw? It seems like that it is not possible to let it open.
2.) How can I split the array, which I get from the Arduino (3 values) into several variables so i can storage them into my table?
I appreciate your support a lot!

Edit: Since my draw is empty I always get:

Error, disabling serialEvent() for COM4
Null

And I have no idea why. I also got it when I did it with the sketch before and a empty draw.

yes, when you have new data ( a arduino line )
split it ( by your used delimiter in the arduino print line command )
https://processing.org/reference/splitTokens_.html
a a temporary string variable array, (and convert it to numbers )

in a batch add a table row and feed that variables in.
https://processing.org/reference/TableRow.html


draw () {}
is needed ( like for the serialEvent to run ) but can be empty!

if you get error you might have a typo

I threw together some code to send data from Arduino to Processing.
On the Processing side I converted the incoming String data to data type (String, int or float) and stored in array.
It may help as an example.

Arduino:

void setup() 
  {
  // initialize the serial communication:
  Serial.begin(9600);
  prevTime = millis();
  }

void loop() 
  {

> Blockquote

currTime = millis();
  diffTime = currTime - prevTime;
  prevTime = currTime; 
  // send the value of analog input 0:
  Serial.print(count++); Serial.print(' ');
  Serial.print(millis()); Serial.print(' ');
  Serial.print(diffTime); Serial.print(' ');
  Serial.print(random(0, 255));
  Serial.println();
  delay(1);
  }

Processing:

import processing.serial.*;

Serial myPort;
String vals;
String[] splitvals;
String[] d0 = new String[1000];
int[] d1 = new int[1000];
int[] d2 = new int[1000];
float[] d3 = new float[1000];
int i = 0;

void setup()
  {
// List all the available serial ports:
  printArray(Serial.list()); 
    
  String portName = Serial.list()[2];
  myPort = new Serial(this, portName, 9600);
  myPort.clear();
  delay(100);
  myPort.clear();
  }

void draw()
  {
  if (myPort.available() > 0)
    {
    vals = myPort.readStringUntil('\n');
    println(vals);
    }
   
//  vals = ("one two three four");
  
  if (vals != null && true)   // Check for null and other condition "true"
    {
    splitvals = split(vals, ' '); 
    saveStrings("meineDatei.txt", splitvals);
    
    printArray(splitvals);
    
    d0[i] = splitvals[0];
    d1[i] = int(splitvals[1]);
    d2[i] = int (splitvals[2]);
    d3[i] = float(splitvals[3]);
    
    println(d0[i], d1[i], d2[i], d3[i]);
    println("-----------------------------------------");
    
    i++;
    }
  }
Output:
0] "COM4"
[1] "COM5"
[2] "COM6"
[3] "COM10"
[4] "COM11"
0 0 0 232

[0] "0"
[1] "0"
[2] "0"
[3] "232
"
0 0 0 232.0
-----------------------------------------
1 1 1 19

[0] "1"
[1] "1"
[2] "1"
[3] "19
"
1 1 1 19.0
-----------------------------------------
2 2 1 158

[0] "2"
[1] "2"
[2] "1"
[3] "158
"
2 2 1 158.0
-----------------------------------------

Output can be cleaned up (That quote did not belong there all alone like that!) by adding:
vals = trim(vals);
I will leave it as an exercise to put in the correct place in your code.

It will likely crash when i goes over 999!

Update:
It WILL crash when i goes over 999! Just tried it…

1000 17382 20 81
[0] "1000"
[1] "17382"
[2] "20"
[3] "81"

ArrayIndexOutOfBoundsException: 1000

:slight_smile: