Hello,I'm new to arduino and have problem setting up my sample frequency.
I've got a working script for reading data at sample frequency 50 Hz. All the data is stored in a .csv file in processing.
Here is my arduino code:
const byte sensorPin = A0;
void setup() {
Serial.begin(115200);
}
void loop() {
int reading = analogRead(sensorPin);
Serial.println(reading);
delay(20);
}
And My processing code:
import processing.serial.*;
Serial mySerial;
PrintWriter output;
int lf = 10; // Linefeed in ASCII
void setup() {
mySerial = new Serial( this, Serial.list()[3], 115200 );
output = createWriter( "sensordata.csv" );
}
void draw() {
if (mySerial.available() > 0) {
String value = mySerial.readStringUntil(lf);
if ( value != null ) {
if (value.length() > 2) {
output.print( value );
}
}
}
}
void keyPressed() {
output.flush(); // Writes the remaining data to the file
output.close(); // Finishes the file
exit(); // Stops the program
}
The problem is when I want to change my sample frequency to 200 Hz(even 100 Hz) isn't capturing all the samples in the csv file. When I capture 1 minute of data = 60*200= 12000 samples,I only got 3278 of samples equal to around 16 seconds. So where is The problem?
The only thing I changed from 50 Hz to 200Hz is changing the Arduino code with a delay of 5 ms=1/200 Hz
const byte sensorPin = A0;
void setup() {
Serial.begin(115200);
}
void loop() {
int reading = analogRead(sensorPin);
The problem is when I want to change my sample frequency to 200 Hz(even 100 Hz) isn't capturing all the samples in the csv file.
How are you changing the sample frequency?
void draw() {
if (mySerial.available() > 0) {
String value = mySerial.readStringUntil(lf);
if ( value != null ) {
if (value.length() > 2) {
output.print( value );
}
}
}
}
Unlike the loop() function on the Arduino, draw() is NOT called over and over AS FAST AS POSSIBLE.
Therefore, you should NOT do serial IO in draw(). You should use mySerial.bufferUntil() in setup(), to define what constitutes a packet (lf is a fine terminator). Then, you should implement the serialEvent() method and do the serial IO there.
The serialEvent() method will be called as often as required, whenever a line feed arrives.
bn1234:
The problem is when I want to change my sample frequency to 200 Hz(even 100 Hz) isn't capturing all the samples in the csv file. When I capture 1 minute of data = 60*200= 12000 samples,I only got 3278 of samples equal to around 16 seconds. So where is The problem?
The biggest problem seems to be with your processing code.
I don't know about processing.
But in case you just want to log data to file, I'd simply use a "serial terminal program" and activate the "log to file" option, and all the data received will be saved to that file.
For Windows operating systems you can use Realterm logging serial data to a log file (without any programming, it is a user option).
A smaller problem occurs with your Arduino code: You are sending slightly slower than one sample every five milliseconds, because you forget, that
the analogRead() function call needs time
the loop() code needs some time
But that is just a small error, you will perhaps send one sample in 5.2 milliseconds, or something like that.
Please let me know if you need Arduino code to send out samples exactly taken each 5.0 milliseconds.
I want to capture data at a 'known' sample frequency f.e 200 Hz,so thus sending out 5 ms. If the data sended is 5.2 ms,meaning 1/5.2ms=192.3077 Hz. That is also good, but I have to know the 'exact' sample frequency(the sample frequency should stay the same).
The reason why I ask, is because I want to process the captured data in MATLAB, and visualize the data over time, which is possible if I knew the exact sample frequency.
And the troubleshoot is indeed in processing, I'm going to look further for serial monitor software.
bn1234:
I want to capture data at a 'known' sample frequency f.e 200 Hz,so thus sending out 5 ms. If the data sended is 5.2 ms,meaning 1/5.2ms=192.3077 Hz. That is also good, but I have to know the 'exact' sample frequency(the sample frequency should stay the same).
The reason why I ask, is because I want to process the captured data in MATLAB, and visualize the data over time, which is possible if I knew the exact sample frequency.
And the troubleshoot is indeed in processing, I'm going to look further for serial monitor software.
Here is an Arduino code to keep a more accurate 5ms sample period than you get by using "delay()":
const byte sensorPin = A0;
void setup() {
Serial.begin(115200);
}
unsigned long lastSampleTime;
void loop() {
if (micros()-lastSampleTime>=5000)
{
lastSampleTime+=5000;
int reading = analogRead(sensorPin);
Serial.println(reading);
}
}
The accuracy is then the same as the accuracy of your Arduinos 16 MHz frequency clocking (16 MHz crystal or oscillator).