0

I have Arduino Due R3 (84MHz) and I am trying to find the mean of value from AnalogRead. I have to set the sampling rate of 8000 samples/second with 4 channels. I tried using for loop for this purpose.

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int i = 0;
int sensorPin = A0;
int sensorValue = 0;
int highest=0;
int lowest=0;
float mean=0;



void setup() 
{
  Serial.begin(9600);  
  analogWriteResolution(12);  // set the analog output resolution to 12 bit (4096 levels)
  analogReadResolution(12);   // set the analog input resolution to 12 bit
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  lcd.print("Hello");

}

void loop() 
{


  for(;;)
  {
    mean=0;
    for(i=0;i<8000;i++)
    {
       sensorValue = analogRead(sensorPin);
     highest=max(highest,sensorValue);
     lowest=min(lowest,sensorValue);
     mean = mean + (highest-lowest);
    }
    mean = mean/8000;
    delay(10);
    lcd.setCursor(0, 1);
    lcd.print(mean);
  }

Will this set sampling rate to 8000 samples/sec ?

Also I was receiving a lot of noise at A0 which often led to the lowest value to be 0. In the image : The red wave is a constant dc voltage of 2.7 V from power supply. The  red wave is constant dc voltage of 2.7V How do I overcome this noise so that mean value is accurate and precise ?

3

Just to as a complement to Majenko's answer (which I second), there are a couple of flaws in your program that may be related to your problem:

  • lowest is always zero, as it is initialized to 0 and cannot increase
  • your computation of the mean is incorrect: the mean is the sum of the readings divided by their number
  • you fail to reset lowest and highest between consecutive runs of 8000 samples
  • there is no point in putting all of loop() inside an infinite loop.

Assuming you really intend to print summary statistics on runs of 8000 samples, as your code suggests, I would write it like this:

const int SENSOR_PIN = A0;
const int SAMPLE_COUNT = 8000;
const uint32_t SAMPLE_PERIOD = 125;  // 125 us

void loop()
{
    long sum = 0;
    int lowest = INT_MAX, highest = 0;

    uint32_t lastTime = micros();
    for (int i = 0; i < SAMPLE_COUNT; i++) {

        // Wait until it's time.
        while (micros() - lastTime < SAMPLE_PERIOD) ;
        lastTime += SAMPLE_PERIOD;

        // Take and process the sample.
        int sensorValue = analogRead(SENSOR_PIN);
        sum += sensorValue;
        highest = max(highest, sensorValue);
        lowest = min(lowest, sensorValue);
    }
    float mean = (float) sum / SAMPLE_COUNT;
    Serial.print("mean: "); Serial.print(mean);
    Serial.print(", minimum: "); Serial.print(lowest);
    Serial.print(", maximum: "); Serial.println(highest);
    Serial.flush();
}

Edit: I changed the code in order to keep a roughly constant sampling rate of 8000 samp/s. The main change is that, before taking a reading, we wait until it's time to do so (until micros() - lastTime >= SAMPLE_PERIOD).

Note that lastTime could be updated with lastTime = micros(), in which case it would have hold the time we last took a sample. By updating it with lastTime += SAMPLE_PERIOD it instead holds the time we shoud have taken the last sample. This is the right choice for enforcing a given average sampling rate.

Running on an Uno: I have no experience with the Due, but here are some remarks that would apply to an Uno, or any other AVR-based Arduino:

  • analogRead() takes about 110 µs, which means we cannot sample more than one channel, and we only have about 15 µs to process the sample. Here the processing is simple enough that the Arduino can do it in this limited time.
  • There is some jitter in the sampling, because micros() has a limited resolution of 4 µs, because of the timer interrupt kicking in from time to time, and because the while loop takes a finite amount of time.

If I were to do something similar on an Uno, I would forgo analogRead(), configure the ADC to be triggered by a timer, and set the timer to trigger the DC every 125 µs. Not only would this get rid of the jitter, it would also allow the CPU to do its job in parallel with the ADC, instead of just sitting idle and waiting until the ADC is done. This would allow for more complex per-sample processing.

About the Due: As I said, I have no experience with this board. It has a more capable processor, but this tells you nothing about the speed of its ADC. I would expect to face the same issues as with the Uno, though maybe to a lesser degree. I guess it should be possible to trigger the ADC from a timer, but I have no idea how to do so.

  • Thanks for the corrections. Actually I wanted to calculate maximum and minimum per cycle and then calculate the mean of their difference for the given number of samples. I have updated my code also. Sorry for Incovenience.Also how do I set the sampling rate to around 8000 samples/sec if I'm using 4 channels with Arduino Due R3 (84 MHz) ? – Sam Thornton Jun 10 '17 at 6:44
  • @SamThornton: About the sampling rate, see the expanded answer. – Edgar Bonet Jun 10 '17 at 12:20
  • Thanks !! Just there is 1 doubt ? Why can't I use mutiple channels ? What if use nested loop like for(int i=0;i<4;i++) { for(int j=0;j<8000;j++) //take input and process } – Sam Thornton Jun 10 '17 at 15:08
  • @SamThornton: Yes, you can read one waveform on one channel, then another one on the other channel and so on. What you cannot do, at least with this scheme, is sample the four channels simultaneously at 8 kS/s. Unless your ADC is way faster than the ones on the AVRs. – Edgar Bonet Jun 10 '17 at 16:48
  • Oh I see. Thanks ! BTW Is there a way to do it simultaneously ? – Sam Thornton Jun 10 '17 at 19:48
0

Will this set sampling rate to 8000 samples/sec ?

No, that will make it perform a block of 8000 samples as fast as it can. There's absolutely nothing in there that has anything to do with time, so how can "seconds" be included in the description of it?

How do I overcome this noise so that mean value is accurate and precise ?

That depends on where the noise is coming from. Maybe if you slowed down your sampling you wouldn't get the noise. Maybe if you made a better connection to whatever it is you're sampling you'd get less noise. Maybe if you added some external filtering you'd get less noise. Maybe if you used a different mathematical model for determining what your average value is you'd not care about the noise.

  • Can you tell me the way to calculate the mean such that I don't have to care about the noise ? – Sam Thornton Jun 10 '17 at 6:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.