Go Down

Topic: Multiple Analog Inputs and Sampling Rate Question (Read 420 times) previous topic - next topic

bkenefick323

Hello,

I am relatively new to working with Arduino and I am working on a project that requires two analog inputs to be sampled with a delay of 1 millisecond. When analyzing the data I noticed that the data points are grouped at certain times and, therefore, wouldn't necessarily mean that each point is 1 ms apart (see the attached Serial Monitor image). Maybe it is a simple fix and I just don't know what I'm doing, but I was wondering if there was a way to get the Arduino to only read one data point at a time, but still achieve the same speed? For my calculations, I need to be able to make the assumption that each data point is 1 ms apart and the entire dataset is 10 seconds total.

Thanks in advance!

Wawa

millis() or micros() can be used to make things happen at set intervals.
It helps if you understand the technique used in the "BlinkWithoutDelay" sketch in the examples of the IDE.
Leo..

pylon


bkenefick323

The device now actually takes three inputs, but the same problem is occurring using the code below. I am currently messing around with millis()/micros() suggestion from above.

*Note: All of the inputs are correctly working, and I am getting reasonable waveforms, but I need to make sure that the time intervals are correct

Code:

int pinZeroEar = A0 ;
int pinOneFinger = A1 ;
int pinTwoECG = A2 ;
int valA0 ;
int valA1 ;
int valA2 ;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600) ;
  pinMode(pinZeroEar, INPUT) ;
  pinMode(pinOneFinger, INPUT) ;
  pinMode(pinTwoECG,INPUT) ;
  pinMode(10, INPUT) ;
  pinMode(11, INPUT) ;
}

void loop() {
  // put your main code here, to run repeatedly:
  valA0 = analogRead(pinZeroEar) ;
  valA1 = analogRead(pinOneFinger) ;

  Serial.print(valA1) ; // need A0 (finger) first for MATLAB code
  Serial.print("/") ;
  Serial.print(valA0) ; // ear values
  Serial.print("/") ;
 
  if((digitalRead(10) == 1) || (digitalRead(11) == 1)){
    Serial.println('!') ;
  }
  else{
    valA2 = analogRead(pinTwoECG) ;
    Serial.println(valA2) ; // ECG values
  }
 
  delayMicroseconds(100) ;
}

Idahowalker

#4
May 23, 2019, 04:58 pm Last Edit: May 23, 2019, 05:09 pm by Idahowalker
One of the things you might want to consider is to make the delayMicroseconds use a calculated variable. What I mean is that using a hard coded 100 does not mean that your measurements will occur on a precise time. Each measurement that you take and calculate takes time, each print statement eats a lot of time. The time to take a measurement, print, and calculate the result is added to your delay time, making your delay time to measurement longer and disrupting the 1mS sampling time.


By using a variable and calculating the time to run your code summed with the desired timing interval your code will adjust itself to try for 1mS timing, automatically.


Next, you should use code tags to have your posted code look like this:
Code: [Select]

int pinZeroEar = A0 ;
int pinOneFinger = A1 ;
int pinTwoECG = A2 ;
int valA0 ;
int valA1 ;
int valA2 ;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600) ;
  pinMode(pinZeroEar, INPUT) ;
  pinMode(pinOneFinger, INPUT) ;
  pinMode(pinTwoECG,INPUT) ;
  pinMode(10, INPUT) ;
  pinMode(11, INPUT) ;
}

void loop() {
  // put your main code here, to run repeatedly:
  valA0 = analogRead(pinZeroEar) ;
  valA1 = analogRead(pinOneFinger) ;

  Serial.print(valA1) ; // need A0 (finger) first for MATLAB code
  Serial.print("/") ;
  Serial.print(valA0) ; // ear values
  Serial.print("/") ;
 
  if((digitalRead(10) == 1) || (digitalRead(11) == 1)){
    Serial.println('!') ;
  }
  else{
    valA2 = analogRead(pinTwoECG) ;
    Serial.println(valA2) ; // ECG values
  }
 
  delayMicroseconds(100) ;
}


You can, also just delay 1mS between each reading.

wvmarle

With that code your time intervals are NOT correct. Impossible to get even nearly correct this way, especially with those print statements slowing you down big time (about 1 ms per character printed at 9,600 bps!). That screen shot (next time please just post those numbers between code tags in the forum, the same tags as you should use to post your code itself) shows 34 ms between readings.

So first of all change that Serial speed to something more sensible, like 115,200 bps. That allows you to print 11 characters in a millisecond. So that's your printing budget for the three values you try to read. Luckily this gets placed in a buffer so you don't have to wait for it to happen, just make sure the buffer empties faster than you fill it. So no more than 11 characters to print!

Assuming your readings are between 100 and 999, printing three values, two spacer, and a line termination would require 12 characters. So that's a problem already. You have no choice but to up the Serial speed further: 230,400 or 250,000 bps. That will do. 23 characters per ms, so three values of four digits + two spaces + line termination = 15 characters. So that's settled.

Then: one analogRead() takes about 110 µs, they must be done in succession, not at the same time.

This gives you a reading every 1 ms (1,000 µs) for 10 seconds upon pressing the reset button.

Code: [Select]

void setup() {
  Serial.begin(240300) ; // Remember to change the settings of your Serial monitor to match this number.
  pinMode(pinZeroEar, INPUT) ;
  pinMode(pinOneFinger, INPUT) ;
  pinMode(pinTwoECG,INPUT) ;
  pinMode(10, INPUT) ;
  pinMode(11, INPUT) ;
  uint32_t lastReading;
  uint32_t startReading = millis();
  while (millis() - startReading < 10000) { // Do this for 10 seconds.
    if (micros() - lastReading > 1000) {
      lastReading += 1000;
      valA0 = analogRead(pinZeroEar) ;
      valA1 = analogRead(pinOneFinger) ;

      Serial.print(valA1) ; // need A0 (finger) first for MATLAB code
      Serial.print('/') ;
      Serial.print(valA0) ; // ear values
 
      if((digitalRead(10) == 1) || (digitalRead(11) == 1)) {
        Serial.println("/!") ;
      }
      else{
        valA2 = analogRead(pinTwoECG) ;
        Serial.print('/') ;
        Serial.println(valA2) ; // ECG values
      }
    }
  }
}

void loop() {}
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

JohnRob

Just a quick observation.... I believe the timestamp of the serial output is the time it was printed not when the data was "taken"

Please do not PM me with thread based messages.  If your thoughts are worth responding,  the group should benefit from your insight.

wvmarle

Just a quick observation.... I believe the timestamp of the serial output is the time it was printed not when the data was "taken"
Correct - but you see there's a 34 ms interval between subsequent groups of prints, that means the prints are sent by the Arduino at that interval.
As each print should take some time (1 ms per character to transfer) this time obviously not accurate.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

Knight_Templar

It depends on how many sensors you wish to use:


1) for up to 5-10 sensors you can use a multiplexer. Above that it gets unreliable in the cheap versions.

2) for an unlimited (yes almost unlimited) number of sensors, you can use the photon-pixel coupling method which is a new thing, 2019 level stuff. It allows you to read all the sensors in parallel.

Specifically for 1 ms sampling (for lets say 4000 sensors or how ever many you want) you can use the photon-pixel coupling method which requires a video camera. In your case, unfortunately, for 1ms you will need a 1000 fps video camera (which Arduino can not tolerate). If you wish to sample these sensors in 41 milliseconds, you can use any webcam or the Arduino camera at 24 fps.

Arduino camera can go to a maximum of 60 fps, and that means that the maximum sampling speed will be of 16 milliseconds (which is pretty good since you can read a huge array of sensors in parallel). But you say you need 1 millisecond, and that requires a 1000 fps camera  :o


To summarize this:

| Sensor sampling | 1 ms | 16 ms| 41 ms
| Video camera | 1000 fps| 60 fps| 24 fps



Read this for exact explanation on the principles and the implementation: P.A. Gagniuc et al. Photon-pixel coupling: A method for parallel acquisition of electrical signals in scientific investigations. MethodsX, 6:968-979, 2019.

Go Up