Page 1 of 1

Smooth an Array of Analog Values and Print them

Posted: Fri Nov 08, 2019 1:23 am
by knightridar
This code can be useful if anyone wants to get a bunch of analog values and smooth out the results and then output them after smoothing them.

The array helps to prevent repetition of code and so makes things more efficient.
I have to thank user 6v6gt on the Arduino forums for helping to complete it when I was totally lost with respect to multidimensional arrays.

This code is only reading ADC1 channel values because I read somewhere in the Espressif ESP32 documentation that WiFi can't be used if other certain channels are being used for ADC,etc. My application uses WiFi and ESP-Now.

However, for other non WiFi based applications people just have to add on the correct pins and duplicate the code as they make the array larger.

Code: Select all

// ESP32 adc conversion
#include <driver/adc.h>

// Define the number of samples to keep track of. The higher the number, the
// more the readings will be smoothed, but the slower the output will respond to
// the input. Using a constant rather than a normal variable lets us use this
// data to determine the size of the readings array.
const uint8_t numReadings = 64;
const uint8_t numSensors = 4;

uint32_t readings[numSensors][numReadings];   // multi-dimensional readings from analog input
uint32_t readIndex = 0;              // the index of the current reading
uint32_t total[numSensors] = {0};    // the running total
uint32_t average = 0;                // the average

// interval to stabilize analog input smoothing readings
// ADC1 Channel read time ~9.5µs per sample --> 64 readings x 9.5 = 608 µs = .608 ms
uint8_t numReadingsInterval = 2;
uint32_t numReadingsStart = 0;

void setup()
{
  Serial.begin(115200);

  // Voltage divider analog in pins
  adc1_config_width(ADC_WIDTH_12Bit);
  adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //Pin34

  adc1_config_width(ADC_WIDTH_12Bit);
  adc1_config_channel_atten(ADC1_CHANNEL_7, ADC_ATTEN_DB_11); //Pin35

  adc1_config_width(ADC_WIDTH_12Bit);
  adc1_config_channel_atten(ADC1_CHANNEL_1, ADC_ATTEN_DB_11); //Pin37

  adc1_config_width(ADC_WIDTH_12Bit);
  adc1_config_channel_atten(ADC1_CHANNEL_2, ADC_ATTEN_DB_11); //Pin38

  // initialize all the readings to 0
  // multidimensional array takes into account multiple sensors and multiple readings for each sensor
  for (uint8_t thisReading = 0; thisReading < numReadings; thisReading++)
  {
    for ( uint8_t j = 0; j < numSensors; j++)  readings[j][thisReading] = 0;
  }
}

//loop function being used to smooth analog input values
// void OnDataSent function sends values over and over again
void loop()
{
  if ( millis() - numReadingsStart >= numReadingsInterval * numReadings )
  {
    numReadingsStart = millis();

    // Read the sensor
    uint16_t AzimuthCW = adc1_get_raw(ADC1_CHANNEL_6); //Pin34
    uint16_t AzimuthCCW = adc1_get_raw(ADC1_CHANNEL_7); //Pin35

    uint16_t ElevationCW = adc1_get_raw(ADC1_CHANNEL_1); //Pin37
    uint16_t ElevationCCW = adc1_get_raw(ADC1_CHANNEL_2); //Pin38

    uint16_t  inputPin[ numSensors ] = {AzimuthCW, AzimuthCCW, ElevationCW, ElevationCCW};

    uint8_t ai;

    for (ai = 0; ai < numSensors ; ai++)
    {
      // subtract the last reading:
      total[ ai ] = total[ ai ] - readings[ai][readIndex];
      // read from the sensor:
      readings[ai][readIndex] = inputPin[ai];
      // add the reading to the total:
      total[ai] = total[ai] + readings[ai][readIndex];
      // calculate the average:
      average = total[ai] / numReadings;
    }

    // advance to the next position in the array:
    readIndex = readIndex + 1;
    // if we're at the end of the array...
    if (readIndex >= numReadings)
    {
      // ...wrap around to the beginning:
      readIndex = 0;
    }

    uint16_t ACW = total[0] / numReadings; // AzimuthCW
    uint16_t ACCW = total[1] / numReadings; // AzimuthCCW
    uint16_t ECW = total[2] / numReadings; // ElevationCW
    uint16_t ECCW = total[3] / numReadings; // ElevationCCW

    Serial.print("AzimuthCW: ");
    Serial.println(ACW);
    Serial.print("AzimuthCCW: ");
    Serial.println(ACCW);
    Serial.print("ElevationCW: ");
    Serial.println(ECW);
    Serial.print("ElevationCCW: ");
    Serial.println(ECCW);
  }
}

Re: Smooth an Array of Analog Values and Print them

Posted: Mon Nov 11, 2019 10:01 am
by zekageri
Can i use it to measure on one pin a 4khz signal?

Re: Smooth an Array of Analog Values and Print them

Posted: Wed Nov 13, 2019 7:06 pm
by knightridar
https://esp32.com/viewtopic.php?f=2&t=1075&start=10

This is what I found hope it helps.
They claim 6 khz but results not so good.

Re: Smooth an Array of Analog Values and Print them

Posted: Thu Nov 14, 2019 12:21 am
by tommeyers
It looks like an unweighted rolling average. All good. Is that correct?

Each type has different natures.

Tom Meyers