EMG_Sensor Reading Frequency

Arduino Uno
Hi guys, I'm trying to do my thesis project and i need to read the values from my Myoware EMG_sensor. I've read from many papers that the frequency needed for reading the EMG signal is about 10KHZ. I've also read that Arduino Uno has a sampling rate of 9.6KHz (or even less due to the Serial Communication)
I'd love to know if there's a way of increasing the sampling rate and if using delays affects also in my frequency rate. On the other hand i'd like to know if there's a way of differentiate the values of my two sensors (like idk printing a character next to the first sensor value to differentiate it from the second) That might sound a little bit newbie, i know but i'm not really familiar with Arduino. For example if i were using a python code i would use print(sensorValue1, end='*')

Here's my code:

// These constants won't change. They're used to give names to the pins used:
const int analogInPin1 = A0;  // Analog input pin that the EMG_Sensor is attached to
const int analogInPin2 = A1;

int sensorValue1 = 0;        // value read from the pot
int sensorValue2 = 0;

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
}

void loop() {
  // read the analog in value:
  sensorValue1 = analogRead(analogInPin1);
  sensorValue2 = analogRead(analogInPin2);
  
  // print the results to the Serial Monitor:
  //Serial.print("sensor = ");
  if (sensorValue1 > 25 && sensorValue1>25){  //print values higher than 25
    Serial.print(sensorValue1);
    Serial.print(sensorValue2);
    delay(2);  
    // wait 2 milliseconds before the next loop for the analog-to-digital
    // converter to settle after the last reading:    
  }  
}

Thanks you in advance!!
Oh, I'm just reading the sensor values from the A0 and A1 analog pins.

You can sample faster with an Uno, but you lose resolution. See this page.

You do not need to preface the samples, the order that they are sent can identify who they are. I would recommend start and end markers to be sent to frame each data packet. See the serial input basics tutorial.

Thanks you so much for your response, it was very helpful especially the input tutorial.

One last question, am i able to know what's the exactly frequency in which i'm receiving the data? I need that info because i need to plot the input value vs time (again, newbie question)

If you use micros() to schedule each sample read you know the frequency...

MarkT:
If you use micros() to schedule each sample read you know the frequency...

Mark, thanks you for this info, so this would work?

const int analogInPin1 = A0;  // Analog input pin that the EMG_Sensor is attached to
const int analogInPin2 = A1;

int sensorValue1 = 0;        // value read from the pot
int sensorValue2 = 0;
long previousMicros = 0; 
long interval = 1000; //interval between reads (1000Hz = 1000us) 

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
}

void loop() {
  unsigned long currentMicros = micros();
  if(currentMicros - previousMicros == interval)   //if 1000us pass, i start to read the values
    {
      sensorValue1 = analogRead(analogInPin1);  //read the analog values
      float voltage1 = sensorValue1 * (5.0 / 1023.0);  //convert the values in voltage
      Serial.println(voltage1); //prints the value of voltage  
      delay(2);  
      // wait 2 milliseconds before the next loop for the analog-to-digital
      // converter to settle after the last reading:   
    }   
}

On the other hand, would the delays and the loop affect my sampling rate?

would the delays and the loop affect my sampling rate?

The delay function is a command to "do nothing", so of course it affects your sampling rate. So does printing at the very slow rate of 9600 Baud (about 1000 characters per second).

That delay(2) statement alone reduces your sample rate to less than 500 Hz, and the printing causes an even greater reduction.

I would guess that the sample rate is around 100 Hz or less, using that code.

This comment indicates that the person who wrote that code does not understand Arduino very well:

      // wait 2 milliseconds before the next loop for the analog-to-digital
      // converter to settle after the last reading:

Thanks man, i'm so frustated because that's the original code of the company who makes the Sensor...

Could you give me a hand here? How could i setup the parameters in order to have a sampling rate of at least 1000Hz, this is SO frustating, this is just the first step of the long path i need to do in order to do the pattern recognition and any help would be amazing

The ADC samples at the default rate of 9.6 kHz and takes about 0.1 millisecond per reading. If you want to sample at 1 kHz, then you have less than 0.9 millisecond to send the data somewhere.

In principle you can do that with one sample if you use the serial Baud rate 115200 (about 10 characters per millisecond), but whether that Baud rate is actually realized depends on the exact nature of the connection between the Arduino and your computer, which you have not specified.

For example, the USB port on a PC is polled every millisecond, and that may be a limiting factor.

fastest loop:

void loop() {
Serial.println(analogRead(input_pin));
}

In the serial monitor you can turn on "show timestamp" which tells you the time at which each reading arrived at your PC. Copy and paste the data into an editor, or use a terminal program to log those data to a file and process at your leisure.

12:19:57.084 -> 574

Hi guys, i'm trying to get a fixed sampling frequency of 1000Hz because i need to read some EMG singal through the ADC, here's my code

int valorA0;
int t_sampling = 1; //1ms sampling (1000Hz)
volatile unsigned currentSampling = 0;
volatile unsigned previousSampling = 0;
volatile unsigned deltaSampling = 0;


void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  pinMode(A0,INPUT);   
}

// the loop routine runs over and over again forever:
void loop() {
  currentSampling =  millis();
  deltaSampling = (double) currentSampling - previousSampling;
  // read the input on analog pin 0:
  if( deltaSampling >= t_sampling){
    // read the input on analog pin 0:
    Serial.println(analogRead(A0));  //print the A0 pin value
    //Serial.println(millis());
    previousSampling = currentSampling;
  }  
}

The problem is that when i print just the line of

Serial.println(millis()) ;

it starts fine but after some prints the millis increase from 3, 4 6 or even 7. How could i achieve a properly fixed sampling rate of 1000Hz, should I use a baud rate of 115200? I've been searching and it's kind of difficult to achieve a solution, i'm a amateur with Arduino btw

You will not have much success interleaving analogRead() with Serial.print() at any significant rate.
You can drive the ADC [on at least an AVR based device- uno etc.] directly from a timer and you can queue the results and print them in batches.

The "volatile" and "double" in your code make no sense and may slow down execution.
All time related variables should be unsigned long, see the basic IDE examples for proper timing.

Also the baudrate can be increased to speed up Serial output.

Serial.begin(9600)Oops

Hi,
Is this related to this?
https://forum.arduino.cc/index.php?topic=708104.msg4758183#msg4758183

Tom... :slight_smile:

TomGeorge:
Hi,
Is this related to this?
EMG_Sensor Reading Frequency - Sensors - Arduino Forum

Tom... :slight_smile:

That's . . . embarrassing

How many bugs can be inserted by fixing other bugs - astonishing :wink:
Or is the code self-evolving, as kind of AI?

I picked this code out of a demodulator and adapted it for your EMG parameters. It can run at many kHz, but not when outputting directly to the serial monitor.
If the serial monitor is set to 115200 baud, it can tolerate a maximum of 250Hz before it starts reporting a data loss. At 500,000 baud and 1000Hz, there is no immediate data loss but the PC starts freezing.

It works by driving the ADC by timer 1 and the results are processed in the ADC's interrupt service routine and then queued. In the loop(), the queue is read and printed. If the queue is not emptied here quickly enough, results will go missing and the cumulative error count value will increase.

There are two parts, the main sketch and a separate queue which has to be placed in the sketch folder.

You can change the parameter frequency and the Serial.begin() statement to suit. It is fixed to read from pin A0.

You will almost certainly have difficulty dealing with that volume of data. An SD card may be useful for getting the data onto a PC for further processing.

ADC_Timer_V0_01.ino (2.88 KB)

Fifo.h (3.39 KB)

Tony, do you really need to read the raw emg signal?

The MyoWare board acts by measuring the filtered and rectified electrical activity of a muscle; outputting 0-Vs Volts depending the amount of activity in the selected muscle, where Vs signifies the voltage of the power source. It's that easy: stick on a few electrodes (not included), read the voltage out and flex some muscles!

I have a page here that examines the effect of sampling rate on measurement of a stochastic signal (ie one that carries information).

It seems to me the sampling rate of 1kHZ is the nyquist criterion for the EMG signal which is

band-limited to 500Hz

In which case you will not see the shape of the signal. So not quite sure what information you are trying to extract other than the overall signal amplitude - which you could get from the filtered & rectified signal, with a much lower sampling rate.

Sampling at 1kHZ you will very rapidly get a LOT of data - that would then need reducing.

Some good references here
https://www.researchgate.net/figure/Frequency-spectrum-of-EMG-signal_fig2_232905752

should I use a baud rate of 115200

Evidently you did not learn much from the responses you got from the same post of ten days ago, so take some time to read those over again.

I think you need to rethink your strategy.

First use a different MCU the Arduino Uno is old and according to the post here can barely do what you want. Most modern MCU have faster ADC with much better precision. If you get a good processor you can even do some signal analysis directly.

Regarding the ADC you need to look for one that you can program to work fully automatic. If you want to do signal analysis you need the signals to be sampled at the exact same interval. Using millis() is not precise enough. The sampling time can be off by 1ms every sample. And your maximum sampling rate is 1kHz. The same is true for micros. If you do not check often enough the sampling time will jitter. If you are good at math you could do some analysis and find out how big your error is. Or you control the ADC by hardware and not worry about that part.

A DMA controller might be useful to reduce the interrupt load on the processor. You can still start using interrupts to retrieve the ADC values and leave this for later as an optimization step.

Second, you said this is your thesis. What is the thesis in? How much time do you have? Is collecting the data part of your thesis or only the data analysis? Do you have any resources available? Maybe you need to collaborate with somebody else at your university and focus on data analysis and let an electronics student build you the hardware.

Threads merged.