Smoothing values TEMT6000 light sensor on ESP32 12bit ADC to uint8_t for ESP-Now

ESP32 has a 12 bit ADC. I've put a .1 microfarad capacitor in my circuit to reduce noise.
I've put ADC readings in an array and am smoothing the readings in an array as well.

I'm wondering if my delay time of 1 ms and number of 64 iterations is enough for smoothing to occur? I'm basing the delay time off of the arduino smoothing example on the the arduno website.

Also i'm going to use the ESP Now protocol to transfer these values to another ESP32.
The protocol only allows 250 bytes of data to be sent.
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/network/esp_now.html

esp_err_t esp_now_send(const uint8_t *peer_addr, const uint8_t *data, size_t len)

Send ESPNOW data.

I'm wondering if I mapped this properly since I declared my AzimuthVoltage global variable to be uint8_t and since the original Azimuth values have a range of 0-4096?

uint8_t AzimuthVoltage = 0;
// Apply the calibration to the sensor reading
  AzimuthVoltage = map(Azimuth, 0, 4096, 0, 255);

  //Sends analog values in this format: i.e. {255}
  uint8_t data[1] = {AzimuthVoltage};
/* 
  Smoothing

  Reads repeatedly from an analog input, calculating a running average and
  printing it to the computer. Keeps 1 reading in an array and continually
  averages them.

  created 22 Apr 2007
  by David A. Mellis  <dam@mellis.org>
  modified 9 Apr 2012
  by Tom Igoe

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Smoothing
*/

#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
// value to determine the size of the readings array.
const int numReadings = 64;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
long total = 0;                  // the running total
long average = 0;                // the average

uint8_t delay_numReadings = 1; // delay to process smoothing readings
unsigned long delay_time = 5000;  //Earth rotates .25 degrees/minute. In 4 minutes Earth rotates 1 degree.
unsigned long time_now = 0;

int Azimuth = 0;
uint8_t AzimuthVoltage = 0;

void setup() {
  Serial.begin(115200);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {

  time_now = millis();

  //Voltage divider analog in pins
  // https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
  // set up A:D channels

  adc1_config_width(ADC_WIDTH_12Bit);
  adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //Pin34

  // Read the sensor
  Azimuth =  adc1_get_raw(ADC1_CHANNEL_6);

  int inputPin[1] = {Azimuth};

 //analog inputs in an array
  uint8_t ai;

  for (ai = 0; ai < 2; ai++) {
    // subtract the last reading:
    total = total - readings[readIndex];
    // read from the sensor:
    readings[readIndex] = inputPin[ai];
    // add the reading to the total:
    total = total + readings[readIndex];
    // 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;
    }
    // calculate the average:
    average = total / numReadings;
    // send it to the computer as ASCII digits
  }
  while (millis() < time_now + delay_numReadings) {}

  // Apply the calibration to the sensor reading
  AzimuthVoltage = map(Azimuth, 0, 4096, 0, 255);

  //Sends analog values in this format: i.e. {255}
  uint8_t data[1] = {AzimuthVoltage};
  uint8_t i;

  for (i = 0; i < 1; i++) {
    Serial.print(data[i]);
    Serial.println(" ");
  }
  Serial.println(" ");

  //wait approx. [period] ms}
  while (millis() < time_now + delay_time) {}
}

Here is my sample serial output that I'm trying to reduce the variation for.
I kept my lighting condition the same (an led lamp post next to my desk)

6 
 
6 
 
5 
 
6 
 
7 
 
7 
 
5 
 
2 
 
2 
 
2 
 
2 
 
2 
 
2 
 
3 
 
4 
 
5 
 
6 
 
6 
 
5 
 
2

Can you explain this for loop:

for (ai = 0; ai < 2; ai++) { . . .

I don't see how you are collecting 64 readings before averaging them (if that is what you are intending to do). Also, don't use delay() statements to control the sampling interval. Use millis() instead.

Thanks for catching that ai should be less than 1. Since right now I am only getting adc readings from one analog input.

I basically modified the Arduino smoothing code on the Arduino site where input pins variable becomes an array and then 64 readings are taken for each array value. I hope I am doing that right.

I am using millis().
The delay wording may have caused the confusion.

You are right. I didn't phrase it correctly. This is blocking code which you should avoid:

while (millis() < time_now + delay_numReadings) {}

You have to move your map and print code to here:

    // calculate the average:
    average = total / numReadings;
    // send it to the computer as ASCII digits

if you are interested in the the average over 64 readings.

Oh man I didn’t know. I got that sample code on a site where it said it’s using millis as a substitute for delay. What would be a good substitute?

So I’ll add this code right before I calculate the average?
// Apply the calibration to the sensor reading
AzimuthVoltage = map(Azimuth, 0, 4096, 0, 255);

It makes sense. Though I’m still confused if my approach about mapping a 0-4096 value to an uint8_t variable is correct.

The mapping function looks OK to me (but you can test this by hardcoding some values and see what it does).

You've effectively created an equivalent of the delay() statement using millis() with this:

while (millis() < time_now + delay_time) {}

Normal would be something like this example which does not block the rest of the code:

uint32_t lastEventAtMs=0 ;   //global or static
. . .
void loop() {
  . . .
  if ( millis() - lastEventAtMs >= 12 ) {  // every 12 mS
     lastEventAtMs = millis() ;
     // code here which should be executed ever 12 mS
  }
  . . .
}

Even when you have got 2 sensors, this won't do what you want because it will interleave the results. You want first 64 results from sensor 1 then 64 from sensor 2

for (ai = 0; ai < 2; ai++) { . . .

You need to increment ai when you are processing the a batch of 64 results, resetting it to zero when it exceeds the number of sensors.

Okay. So I think I've got the millis() properly setup. I set the timings up with variables.
Isn't the whole point of the array to switch to the next variable in the array.
Isn't this portion of the code taking 64 readings of Input1 then takes it average prints it out, and then Input2 takes it average and then prints it out?

      for (ai = 0; ai < 2; ai++) {
        // subtract the last reading:
        total = total - readings[readIndex];
        // read from the sensor:
        readings[readIndex] = inputPin[ai];
        // add the reading to the total:
        total = total + readings[readIndex];
        // 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;

Here is the full code.
I've put the map function inside the for loop ai array.

/*
  Based off of smoothing example at:
  http://www.arduino.cc/en/Tutorial/Smoothing
*/

#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
// value to determine the size of the readings array.
const int numReadings = 64;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
long total = 0;                  // the running total
long average = 0;                // the average

uint32_t lastEventAtMs = 0;

// delay to process smoothing readings
uint8_t numReadingsInterval = 1;

// Delay time of void loop.
// For project reference Earth rotates .25 degrees/minute.
// In 4 minutes Earth rotates 1 degree.
uint32_t loopInterval = 5000;

int Azimuth = 0;
uint8_t AzimuthVoltage = 0;

void setup() {
  Serial.begin(115200);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {

  if ( millis() - lastEventAtMs >= loopInterval ) {  // every 5000 ms

    // code here which should be executed every 5000 ms
    lastEventAtMs = millis() ;

    //Voltage divider analog in pins
    // https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
    // set up A:D channels

    adc1_config_width(ADC_WIDTH_12Bit);
    adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //Pin34

    // Read the sensor
    Azimuth =  adc1_get_raw(ADC1_CHANNEL_6);

    int inputPin[1] = {Azimuth};

    //analog inputs in an array
    uint8_t ai;

    if ( millis() - lastEventAtMs >= numReadingsInterval ) {
      lastEventAtMs = millis() ;

      for (ai = 0; ai < 2; ai++) {
        // subtract the last reading:
        total = total - readings[readIndex];
        // read from the sensor:
        readings[readIndex] = inputPin[ai];
        // add the reading to the total:
        total = total + readings[readIndex];
        // 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;
        }
        // calculate the average:
        average = total / numReadings;
        // send it to the computer as ASCII digits

        // Apply the calibration to the sensor reading
        AzimuthVoltage = map(Azimuth, 0, 4096, 0, 255);
      }
    }
    //Sends analog values in this format: i.e. {255}
    uint8_t data[1] = {AzimuthVoltage};
    uint8_t i;

    for (i = 0; i < 1; i++) {
      Serial.print(data[i]);
      Serial.println(" ");
    }
    Serial.println(" ");
  }
}

I realized the average portion of the code would not get updated with the way mapping was currently coded.

After changing it to this below, I'm getting a serial readout of only 0. :confused:
I thought I was properly incrementing ai but I guess not.

   // Read the sensor
    Azimuth =  adc1_get_raw(ADC1_CHANNEL_6);

    int inputPin[1] = {Azimuth};
    int mappedPin[1] = {AzimuthVoltage};

    //analog inputs in an array
    uint8_t ai;

    if ( millis() - lastEventAtMs >= numReadingsInterval*numReadings ) {
      lastEventAtMs = millis() ;

      for (ai = 0; ai < 1; ai++) {
        // subtract the last reading:
        total = total - readings[readIndex];
        // read from the sensor:
        readings[readIndex] = inputPin[ai];
        // add the reading to the total:
        total = total + readings[readIndex];
        // 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;
        }
        // calculate the average:
        average = total / numReadings;
        // send it to the computer as ASCII digits

        // Apply the calibration to the sensor reading
        mappedPin[ai] = map(average, 0, 4096, 0, 255);
      }
    }
    //Sends analog values in this format: i.e. {255}
    uint8_t data[1] = {AzimuthVoltage};
    uint8_t i;

    for (i = 0; i < 1; i++) {
      Serial.print(data[i]);
      Serial.println(" ");
    }
    Serial.println(" ");
  }

You should post the whole code, not a fragment of it.
In principle, you should not have a 'for loop' within the the main loop in your case where there is a significant time interval involved.

But let's go back to the basics basics of the specification.

  • You have a number sensors connected to a adc channels.
  • You want to start with the first sensor.
  • You want to take readings from it at intervals of 1 mS.
  • when you have 64 readings from the current sensor, you want to calculate the average of the previous 64 sensor readings, print the average out and move on to the next sensor repeating the whole exercise.

Is that correct ?

  • or do you want to print out the average of each sensor at the end of a cycle when you have taken 64 readings from each of the N sensors ?
  • or do you want to interleave the readings from the sensors? That is read sensor 1, store the result, read sensor 2, store the result, and so on until you have 64 readings from each of the sensors, then calculate the average for each sensor, print these out and repeat the whole process '

As for coding, I suggest you get it working with just one sensor and strip out all the unnecessary code for handling multiple sensors and test it behaves as it should, then scale it back up to multiple sensors.

In the end, it is likely that the last code you supplied will need only a small reorganisation to work.

  1. You have a number of sensors connected to a adc channels.
  2. You want to start with the first sensor.
  3. You want to take 64 or xx readings from it at intervals of 1 mS for the smoothing loop.
  4. You want to print out the average of each sensor at the end of the smoothing cycle when you have taken
    64 or xx readings from each of the N sensors ?
  5. The 12 bit ADC values are mapped either in the smoothing loop or outside of it (0-4096-->0-255)
  6. ESP32 transmitter transmits those values using ESP-Now protocol (uses uint8_t for data variable)
  7. ESP32 receiver receives values via data variable
  8. ADC mapped values will determine motor direction of forward/reverse/stop.

I'm keeping it simple for now and just trying steps 1-5.
But first I'm going to go back to basics like you said and just try the smoothing code on its own without an array.

Sorry here is entire code. It's giving me a serial readout of zero now regardless of lighting condition, so I've made it worse:

/*
  Based off of smoothing example at:
  http://www.arduino.cc/en/Tutorial/Smoothing
*/

#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
// value to determine the size of the readings array.
const int numReadings = 64;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
long total = 0;                  // the running total
long average = 0;                // the average

uint32_t lastEventAtMs = 0;

// delay to process smoothing readings
uint8_t numReadingsInterval = 1;

// Delay time of void loop.
// For project reference Earth rotates .25 degrees/minute.
// In 4 minutes Earth rotates 1 degree.
uint32_t loopInterval = 5000;

int Azimuth = 0;
uint8_t AzimuthVoltage = 0;

void setup() {
  Serial.begin(115200);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {

  if ( millis() - lastEventAtMs >= loopInterval ) {  // every 5000 ms

    // code here which should be executed every 5000 ms
    lastEventAtMs = millis() ;

    //Voltage divider analog in pins
    // https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
    // set up A:D channels

    adc1_config_width(ADC_WIDTH_12Bit);
    adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //Pin34

    // Read the sensor
    Azimuth =  adc1_get_raw(ADC1_CHANNEL_6);

    int inputPin[1] = {Azimuth};
    int mappedPin[1] = {AzimuthVoltage};

    //analog inputs in an array
    uint8_t ai;

    if ( millis() - lastEventAtMs >= numReadingsInterval*numReadings ) {
      lastEventAtMs = millis() ;

      for (ai = 0; ai < 1; ai++) {
        // subtract the last reading:
        total = total - readings[readIndex];
        // read from the sensor:
        readings[readIndex] = inputPin[ai];
        // add the reading to the total:
        total = total + readings[readIndex];
        // 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;
        }
        // calculate the average:
        average = total / numReadings;
        // send it to the computer as ASCII digits

        // Apply the calibration to the sensor reading
        mappedPin[ai] = map(average, 0, 4096, 0, 255);
      }
    }
    //Sends analog values in this format: i.e. {255}
    uint8_t data[1] = {mappedPin[1]};
    uint8_t i;

    for (i = 0; i < 1; i++) {
      Serial.print(data[i]);
      Serial.println(" ");
    }
    Serial.println(" ");
  }
}

Here is basic smoothing code using no arrays and delay function:

/*
  Based off of smoothing example at:
  http://www.arduino.cc/en/Tutorial/Smoothing
*/

#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
// value to determine the size of the readings array.
const int numReadings = 64;

uint16_t readings[numReadings];      // the readings from the analog input
uint16_t readIndex = 0;              // the index of the current reading
long total = 0;                  // the running total
long average = 0;                // the average

// delay to process smoothing readings
uint8_t numReadingsInterval = 1;

// Delay time of void loop.
// For project reference Earth rotates .25 degrees/minute.
// In 4 minutes Earth rotates 1 degree.
uint32_t loopInterval = 5000;


void setup() {
  Serial.begin(115200);
  // initialize all the readings to 0:
  for (uint16_t thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {

//Voltage divider analog in pins
// https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
// set up A:D channels

adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //Pin34
// Read the sensor
uint16_t Azimuth =  adc1_get_raw(ADC1_CHANNEL_6);

  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = Azimuth;
  // add the reading to the total:
  total = total + readings[readIndex];
  // 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;
  }

  // calculate the average:
  average = total / numReadings;
  // send it to the computer as ASCII digits
  Serial.println(average);
  delay(numReadingsInterval);        // delay in between reads for stability
}

Here is some serial readout using only smoothing. The results seem very good for a 12 bit range of 0-4095:

78
77
77
77
79
80
80
80
79
78
77
77
78
79
80
80
79
78
77
77
78
79
80
80
79
78
77
77
77
78
80
80
80
79
78
77
77
78
79
80
80
79
78
77
77
78
79
80
81
80
79
78
77
78
79
80
81
80
79
78
77
78
79
80
80
80
79
78
77
77
78
79
80
81
80
79
78
77
78
79
80
81
80
79
78
77
77
78
80
81
80
80
78
78
77
78
79
80
81
80
79
78
77
78
79
80
81
80
79
78
77
78
79
80
81
80
80
78
77
77
78
79
80
81
80
79
78
77
78
79
80
81
80
79
78
77
78
79
80
81
80
80
78
77
77
78
79
80
81
80
79
78
77
78
79
80
81
80
79
78
77
78
79
80
81
81
80
78
78
77
78
80
81
81
80
79
78
77
78
79
81
81
81
79
78
78
78
79
80
81
81
80
79
78
78
78
80
81
81
80
79
78
78
78
79
81
81
80
79
78
78
78
79
80
81
81
80
79
78
77
78
80
81
81
80
79
78
77
78
79
80
81
80
79
78
77
78
79
80
81
81
80
78
78
77
78
79
81
81
80
79
78
77
78
79
80
81
80
79
78
77
78
79
80
81
80
80
78
78
77
78
80
81
81
80
79
78
77
78
79
80
81
80
79
78
77
77
78
80
80
80
79
78
77
77
78
79
80
80
80
78
77
77
78
79
80
80
80
79
78
77
77
78
80
80
80
79
78
77
77
78
79
80
80
80
78
77
77
77
79
80
80
80
79
78
77
77
78
80
80
80
79
78
77
77
78
79
80
80
80
78
77
77
78
79
80
81
80
79
78
77
77
78
80
80
80
79
78
77
77
78
79
80
80
80
79
78
77
78
79
80
81
80
79
78
77
77
79
80
81
80
79
78
77
77
78
79
80
81
80
79
78
77
78
79
80
81
80
79
78
77
77
78
80
80
80
79
78
77
77
78

I tried using millis() based on your example in post #6.
Hopefully I implemented it correctly.

In this line of code I multiplied the number of readings with the number of readings time interval to give the for loop enough time to get an average before resetting. Did I understand the concept properly?:

if ( millis() - lastEventAtMs >= numReadingsInterval* numReadings )

Now I want to slow down the serial print values after getting averages so I can easily see my results.
I wanted to do something like this near the end of the loop:

 ....Serial.println(average);}
if ( millis() - lastEventAtMs >= loopInterval){lastEventAtMs = millis() ;}

However, I am confused by what you said:

In principle, you should not have a 'for loop' within the the main loop in your case where there is a significant time interval involved.

Here is full code:

/*
  Based off of smoothing example at:
  http://www.arduino.cc/en/Tutorial/Smoothing
*/

#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
// value to determine the size of the readings array.
const int numReadings = 64;

uint16_t readings[numReadings];      // the readings from the analog input
uint16_t readIndex = 0;              // the index of the current reading
long total = 0;                  // the running total
long average = 0;                // the average

// delay to process smoothing readings
uint8_t numReadingsInterval = 1;
uint32_t lastEventAtMs=0 ;

// Delay time of void loop.
// For project reference Earth rotates .25 degrees/minute.
// In 4 minutes Earth rotates 1 degree.
uint32_t loopInterval = 5000;


void setup() {
  Serial.begin(115200);
  // initialize all the readings to 0:
  for (uint16_t thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {

// millis() -->Returns the number of milliseconds passed since the Arduino board began running the current program. 
// This number will overflow (go back to zero), after approximately 50 days.
// timing resets to 0 when millis() - lastEventAtMS becomes greater than or equal to numReadingsInterval * numReadings
// then loop proceeds with remaining functions
if ( millis() - lastEventAtMs >= numReadingsInterval* numReadings ){

lastEventAtMs = millis() ;

//Voltage divider analog in pins
// https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
// set up A:D channels

adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //Pin34
// Read the sensor
uint16_t Azimuth =  adc1_get_raw(ADC1_CHANNEL_6);

  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = Azimuth;
  // add the reading to the total:
  total = total + readings[readIndex];
  // 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;
  }

  // calculate the average:
  average = total / numReadings;
  // send it to the computer as ASCII digits
  Serial.println(average);
  }
}

Serial readout with flashlight pointed slightly sideways towards sensor:

313
314
313
313
314
313
313
314
314
313
314
314
313
314
314
313
314
314
313
314
314

This time I mapped the values after averaging them. I am concerned about whether or not the mappedAverage variable should be a uint16_t or if I can assign it uint8_t since ultimately I need to send it as an 8 bit value for ESP-Now protocol. In this example it seems like they kept it as int vs uint8_t
https://www.arduino.cc/reference/en/language/functions/math/map/:

/*
  Based off of smoothing example at:
  http://www.arduino.cc/en/Tutorial/Smoothing
*/

#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
// value to determine the size of the readings array.
const int numReadings = 64;

uint16_t readings[numReadings];      // the readings from the analog input
uint16_t readIndex = 0;              // the index of the current reading
long total = 0;                  // the running total
long average = 0;                // the average
uint8_t mappedAverage = 0;          // mapped average

// delay to process smoothing readings
uint8_t numReadingsInterval = 1;
uint32_t lastEventAtMs = 0 ;

// Delay time of void loop.
// For project reference Earth rotates .25 degrees/minute.
// In 4 minutes Earth rotates 1 degree.
uint32_t loopInterval = 5000;


void setup() {
  Serial.begin(115200);
  // initialize all the readings to 0:
  for (uint16_t thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {

  // millis() -->Returns the number of milliseconds passed since the Arduino board began running the current program.
  // This number will overflow (go back to zero), after approximately 50 days.
  // timing resets to 0 when millis() - lastEventAtMS becomes greater than or equal to numReadingsInterval * numReadings
  // then loop proceeds with remaining functions
  if ( millis() - lastEventAtMs >= numReadingsInterval * numReadings ) {

    lastEventAtMs = millis() ;

    //Voltage divider analog in pins
    // https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
    // set up A:D channels

    adc1_config_width(ADC_WIDTH_12Bit);
    adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //Pin34
    // Read the sensor
    uint16_t Azimuth =  adc1_get_raw(ADC1_CHANNEL_6);

    // subtract the last reading:
    total = total - readings[readIndex];
    // read from the sensor:
    readings[readIndex] = Azimuth;
    // add the reading to the total:
    total = total + readings[readIndex];
    // 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;
    }

    // calculate the average:
    average = total / numReadings;

    // map the average
    mappedAverage = map(average, 0, 4095, 0, 255);
                    // send it to the computer as ASCII digits
    Serial.println(mappedAverage);
  }
}

Serial readout with flashlight pointed sideways:

48
48
48
48
48
48
48
48
48
48
48
48
48
48
48
48
48

OK. So the averaging works for a single sensor and you get reasonable results under different light conditions ?
Maybe try also without any averaging and see if you still get similar results (even if these are not so smooth)

For those big numbers, you should work with long data types otherwise you may get truncation of the significant digits. After all the processing is complete, you can then assign the final value to a uint8_t (byte).

On the basis of the code you've posted for the single sensor, I've seen that want a rolling average so the changed rules in post #9 would be this (if it reflects what you want to do):

  1. You want to create a rolling average of 64 (or xx) readings and output the new value after each read.
  2. you want to handle multiple sensors simultaneously and will need an array, index etc. similar to readings[] etc. for each sensor.

I tried to read the values without smoothing.
There is definitely significant variation.
I will focus next on making an array.

For those big numbers, you should work with long data types otherwise you may get truncation of the significant digits. After all the processing is complete, you can then assign the final value to a uint8_t (byte).

Would uint32_t be better than using long?
For mapping I've used uint16_t since there is 4095 value being changed to 255, but uint8_t still output results for me.

Here is the code:

#include <driver/adc.h>

// delay for readings
uint8_t ReadingsInterval = 250;
uint32_t lastEventAtMs = 0 ;

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

void loop() {

  // millis() -->Returns the number of milliseconds passed since the Arduino board began running the current program.
  // This number will overflow (go back to zero), after approximately 50 days.
  // timing resets to 0 when millis() - lastEventAtMS becomes greater than or equal to numReadingsInterval * numReadings
  // then loop proceeds with remaining functions
  if ( millis() - lastEventAtMs >= ReadingsInterval ) {

    lastEventAtMs = millis() ;

    //Voltage divider analog in pins
    // https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
    // set up A:D channels

    adc1_config_width(ADC_WIDTH_12Bit);
    adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //Pin34
    // Read the sensor
    uint16_t Azimuth =  adc1_get_raw(ADC1_CHANNEL_6);

    // send it to the computer as ASCII digits
    Serial.println(Azimuth);
  }
}

Here are some serial outputs:

3312
3312
3312
3311
3312
3310
3310
3307
3308
3303
3302
3298
3301
3299
3294
3292
3293
3287
3285
3285
3281
3280
3277
3271
3267
3265

From post#6,

Even when you have got 2 sensors, this won't do what you want because it will interleave the results. You want first 64 results from sensor 1 then 64 from sensor 2

for (ai = 0; ai < 2; ai++) { . . .

You need to increment ai when you are processing the a batch of 64 results, resetting it to zero when it exceeds the number of sensors.

I'm unsure on how to reset it to zero if it exceeds the number of sensors.
Doesn't the array take care of this by moving onto the next analog input?

I took the array for loop outside of the smoothing function this time.
I am getting smoothed values, but it seems like it's only from one sensor.
For pin 35 (azimuth I have no sensors plugged into it).
In other words I should be getting a different or zero readout from it.

/*
  For project reference Earth rotates .25 degrees/minute.
  In 4 minutes Earth rotates 1 degree.

  Based off of smoothing example at:
  http://www.arduino.cc/en/Tutorial/Smoothing
*/

#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
// value to determine the size of the readings array.
const int numReadings = 64;

uint32_t readings[numReadings];      // the readings from the analog input
uint32_t readIndex = 0;              // the index of the current reading
uint32_t total = 0;                  // the running total
uint32_t average = 0;                // the average
uint16_t mappedAverage = 0;          // mapped average

// delay to process smoothing readings
uint8_t numReadingsInterval = 1;
uint32_t lastEventAtMs = 0 ;

void setup() {
  Serial.begin(115200);
  // initialize all the readings to 0:
  for (uint16_t thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {

  //Voltage divider analog in pins
  // https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
  // set up A:D channels

  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_6, ADC_ATTEN_DB_11); //Pin34



  // Read the sensor
  uint16_t Azimuth =  adc1_get_raw(ADC1_CHANNEL_7);
  uint16_t Elevation = adc1_get_raw(ADC1_CHANNEL_6);

  uint16_t  inputPin[2] = {Azimuth, Elevation};

  uint16_t ai;

  for (ai = 0; ai < 1; ai++) {

    // millis() -->Returns the number of milliseconds passed since the Arduino board began running the current program.
    // This number will overflow (go back to zero), after approximately 50 days.
    // timing resets to 0 when millis() - lastEventAtMS becomes greater than or equal to numReadingsInterval
    // then loop proceeds with remaining functions
    if ( millis() - lastEventAtMs >= numReadingsInterval ) {

      lastEventAtMs = millis();

      // subtract the last reading:
      total = total - readings[readIndex];
      // read from the sensor:
      readings[readIndex] = inputPin[ai];
      // add the reading to the total:
      total = total + readings[readIndex];
      // 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;
      }

      // calculate the average:
      average = total / numReadings;

      // map the average
      mappedAverage = map(average, 0, 4095, 0, 255);
    }
    Serial.println(mappedAverage);
  }
}

Some serial results:

77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77
77

referring to post #14:
Long ( int32_t ) here is a signed 32 bit number. uint32_t is an unsigned bit number. In general, you should be careful of using unsigned numbers in calculations involving potentially negative (intermediate) results. Although your smoothing calculation has a subtraction in it, as far as I see, it should not go negative so an unsigned number is OK. But, anyway, a long is large enough for your purpose, even though it can represent a number only half the size of a uint32_t.

The figures in your last post are clearly without mapping applied. Your mapping is, incidentally, a simple divide by 16 or, even simpler, a right shift of 4 bits.

referring to post #15:
if you want to smooth the results with a moving average and you want to interleave the readings, you need to duplicate the data structurs to store the historical results for each sensor. You can't, for example, mix the old readings from sensor 1, sensor 2 etc. in the same array readings[].

You can do this with arrays for the duplicated items. This example simply illustrates the use of an array structure which could be appropriate here. There may be items you don't need to duplicate like readIndex.

. . .
uint8_t numSensors = 2 ;
uint32_t readings[numSensors][numReadings];   //multi-dimensional
uint32_t total[numSensors] = {0};
. . .
loop() {

  if ( millis() - lastEventAtMs >= numReadingsInterval ) {
    lastEventAtMs = millis();
    . . .
    for (ai = 0; ai < 1; ai++) {
      . . .
      // read from the sensor:
      readings[ai][readIndex] = inputPin[ai];
      // add the reading to the total:
      total[ai] = total[ai] + readings[ai][readIndex];
     . . . 
    }
  }
}

I divided the values by 16 instead of mapping. I will look into shifting of bits (never heard of it).
However, I get errors now after trying to implement the multidimensional array:

Arduino: 1.8.8 (Windows 7), Board: "DOIT ESP32 DEVKIT V1, 80MHz, 921600, None"

test:10:29: error: array bound is not an integer constant before ']' token

uint32_t readings[numSensors][numReadings]; //multi-dimensional readings from analog input

test:11:26: error: array bound is not an integer constant before ']' token

uint32_t total[numSensors] = {0}; // the running total

In function 'void setup()':

test:24:5: error: 'readings' was not declared in this scope

readings[thisReading] = 0;

In function 'void loop()':

test:59:7: error: 'total' was not declared in this scope

total = total - readings[readIndex];

test:59:23: error: 'readings' was not declared in this scope

total = total - readings[readIndex];

exit status 1
array bound is not an integer constant before ']' token

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

#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
// value to determine the size of the readings array.
const int numReadings = 64;
uint8_t numSensors = 2;

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

// delay to process smoothing readings
uint8_t numReadingsInterval = 1;
uint32_t lastEventAtMs = 0 ;

void setup() {
  Serial.begin(115200);
  // initialize all the readings to 0:
  for (uint16_t thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {

  //Voltage divider analog in pins
  // https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
  // set up A:D channels

  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_6, ADC_ATTEN_DB_11); //Pin34

  // Read the sensor
  uint16_t Azimuth =  adc1_get_raw(ADC1_CHANNEL_7);
  uint16_t Elevation = adc1_get_raw(ADC1_CHANNEL_6);

  uint16_t  inputPin[2] = {Azimuth, Elevation};

  uint16_t ai;

  for (ai = 0; ai < 1; ai++) {

    // millis() -->Returns the number of milliseconds passed since the Arduino board began running the current program.
    // This number will overflow (go back to zero), after approximately 50 days.
    // timing resets to 0 when millis() - lastEventAtMS becomes greater than or equal to numReadingsInterval
    // then loop proceeds with remaining functions
    if ( millis() - lastEventAtMs >= numReadingsInterval ) {

      lastEventAtMs = millis();

      // subtract the last reading:
      total = total - readings[readIndex];
      // read from the sensor:
      readings[ai][readIndex] = inputPin[ai];
      // add the reading to the total:
      total[ai] = total[ai] + readings[ai][readIndex];
      // 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;
      }

      // calculate the average:
      average = total / numReadings;

      // reduce results to 0-255
      EspNowAverage = average/16;
    }
    Serial.println(EspNowAverage);
  }
}

Try:
const uint8_t numSensors = 2;

Thanks, I did try that previously.
It seemed like it compiled further into the code.

I still got this compile error:

Arduino: 1.8.8 (Windows 7), Board: "DOIT ESP32 DEVKIT V1, 80MHz, 921600, None"

In function 'void setup()':

test_r1:24:27: error: incompatible types in assignment of 'int' to 'uint32_t [64] {aka unsigned int [64]}'

readings[thisReading] = 0;

In function 'void loop()':

test_r1:59:13: error: incompatible types in assignment of 'int' to 'uint32_t [2] {aka unsigned int [2]}'

total = total - readings[readIndex];

test_r1:74:25: error: invalid operands of types 'uint32_t [2] {aka unsigned int [2]}' and 'const int' to binary 'operator/'

average = total / numReadings;

exit status 1
incompatible types in assignment of 'int' to 'uint32_t [64] {aka unsigned int [64]}'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

I suspected it may have to do with the multidimensional array and the
const int assigned to numReadings and numSensor, but I changed them to:

uint16_t numReadings = 64;
uint8_t numSensors = 2;

However, I still got a compile error.

#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
// value to determine the size of the readings array.
const int numReadings = 64;
const int numSensors = 2;

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

// delay to process smoothing readings
uint8_t numReadingsInterval = 1;
uint32_t lastEventAtMs = 0 ;

void setup() {
  Serial.begin(115200);
  // initialize all the readings to 0:
  for (uint16_t thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {

  //Voltage divider analog in pins
  // https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
  // set up A:D channels

  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_6, ADC_ATTEN_DB_11); //Pin34

  // Read the sensor
  uint16_t Azimuth =  adc1_get_raw(ADC1_CHANNEL_7);
  uint16_t Elevation = adc1_get_raw(ADC1_CHANNEL_6);

  uint16_t  inputPin[2] = {Azimuth, Elevation};

  uint16_t ai;

  for (ai = 0; ai < 1; ai++) {

    // millis() -->Returns the number of milliseconds passed since the Arduino board began running the current program.
    // This number will overflow (go back to zero), after approximately 50 days.
    // timing resets to 0 when millis() - lastEventAtMS becomes greater than or equal to numReadingsInterval
    // then loop proceeds with remaining functions
    if ( millis() - lastEventAtMs >= numReadingsInterval ) {

      lastEventAtMs = millis();

      // subtract the last reading:
      total = total - readings[readIndex];
      // read from the sensor:
      readings[ai][readIndex] = inputPin[ai];
      // add the reading to the total:
      total[ai] = total[ai] + readings[ai][readIndex];
      // 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;
      }

      // calculate the average:
      average = total / numReadings;

      // reduce results to 0-255
      EspNowAverage = average/16;
    }
    Serial.println(EspNowAverage);
  }
}