Hello,
I am trying to sample EMG data from Seeeduino Grove at 1KHz using the code below. However, when I check the collected data, I am able to retrieve about 1000 values in around 10s (which means ~100Hz frequency).
Any idea on what is possibly going wrong?
Thank you
// Grove - EMG Sensor demo code
// This demo will need a Grove - Led Bar to show the motion
// Grove - EMG Sensor connect to A0
// note: it'll take about serval seconds to detect static analog value
// when you should hold your muscle static. You will see led bar from level 10 turn to
// level 0, it means static analog value get ok
#include <SoftwareSerial.h>
int static_analog_dta0 = 0; // static analog data
int static_analog_dta2 = 0;
unsigned long intervalTime = 1; // f = 1/1ms = 1000 Hz
unsigned long lastMeasureTime = 0;
unsigned long currentTime = 0;
SoftwareSerial espSerial(5, 6);
// get analog value
int getAnalog(int pin)
{
long sum = 0;
for(int i=0; i<32; i++)
{
sum += analogRead(pin);
}
return sum>>5;
}
void setup()
{
Serial.begin(230400);
espSerial.begin(230400);
long sum0 = 0;
long sum2 = 0;
for(int i=0; i<=10; i++)
{
for(int j=0; j<100; j++)
{
sum0 += getAnalog(A0);
sum2 += getAnalog(A2);
delay(1);
}
Serial.println(10-i);
}
sum0 /= 1100;
sum2 /= 1100;
static_analog_dta0 = sum0;
static_analog_dta2 = sum2;
Serial.print("static_analog_dta0 = ");
Serial.println(static_analog_dta0);
Serial.print("static_analog_dta2 = ");
Serial.println(static_analog_dta2);
}
void loop()
{
currentTime = millis();
if ( currentTime - lastMeasureTime >= intervalTime )
{
int val0 = getAnalog(A0);
int val2 = getAnalog(A2); // get Analog value, to convert to volts: *5/(2^10-1) (range 0-5V)
Serial.print(val0);
Serial.print(" ");
Serial.println(val2);
espSerial.print(val0);
espSerial.print(" ");
espSerial.println(val2);
lastMeasureTime = currentTime;
// delay(10);
}
}
Okay, any idea how to speed things up if possible? Ideally, I would like to read data from 8 sensors simultaneously so in this case the data acquisition rate will go even way lower (8*3==24ms ~ 30ms per sample or 33 Hz).
If you need to read that analog pin 32 times in a rawwith your arduino, there's nothing to do. It takes that long. Also serial.prints etc take some time...
But you read the pin value 32 times and then divide it by 32, each time. And this takes time, as Kmin pointed.
Do you really need that? If the value is not so stable you could consider a small capacitor in the pin or something. Maybe averaging, but not 32 times.
I don't know, do the maths, but it doesn't really fit.
// Grove - EMG Sensor demo code
// This demo will need a Grove - Led Bar to show the motion
// Grove - EMG Sensor connect to A0
// note: it'll take about serval seconds to detect static analog value
// when you should hold your muscle static. You will see led bar from level 10 turn to
// level 0, it means static analog value get ok
#include <SoftwareSerial.h>
int static_analog_dta0 = 0; // static analog data
int static_analog_dta2 = 0;
unsigned long intervalTime = 1; // f = 1/1ms = 1000 Hz
unsigned long lastMeasureTime = 0;
unsigned long currentTime = 0;
SoftwareSerial espSerial(5, 6);
// get analog value
int getAnalog(int pin)
{
long sum = 0;
for(int i=0; i<32; i++)
{
sum += analogRead(pin);
}
return sum>>5;
}
void setup()
{
Serial.begin(230400);
espSerial.begin(115200);
long sum0 = 0;
long sum2 = 0;
for(int i=0; i<=10; i++)
{
for(int j=0; j<100; j++)
{
sum0 += getAnalog(A0);
sum2 += getAnalog(A2);
delay(1);
}
Serial.println(10-i);
}
sum0 /= 1100;
sum2 /= 1100;
static_analog_dta0 = sum0;
static_analog_dta2 = sum2;
Serial.print("static_analog_dta0 = ");
Serial.println(static_analog_dta0);
Serial.print("static_analog_dta2 = ");
Serial.println(static_analog_dta2);
}
void loop()
{
//currentTime = millis();
//if ( currentTime - lastMeasureTime >= intervalTime )
//{
int val0 = analogRead(A0);
int val2 = analogRead(A2); // get Analog value, to convert to volts: *5/(2^10-1) (range 0-5V)
Serial.print(val0);
Serial.print(" ");
Serial.println(val2);
/*espSerial.print(val0);
espSerial.print(" ");
espSerial.println(val2);*/
//lastMeasureTime = currentTime;
// delay(10);
//}
}
Okay this is my new code, basically got rid of the 32 reads in the loop, I am only using analogRead which is supposed to take about 100us. But still, if I read one sensor I get 200Hz, if I read 2 sensors I get 100Hz.
Software serial is sued to send the data to a nodemcu, which can be disregarded for now.
Remove that softwareserial
Try to raise serial baudrate
Serial.print all your values in one command (not three lines) as a string...
But first try just with one analog read and serialprint.
The rate will be totally dependant on the serial print. If the numbers are 1 digit then it prints fast. If they are 3 digits then it takes longer and the sample rate goes down.
If you want a consistant sample rate, you can't do a print, you need to save the data to an array.