Sensor data to array (duplicate array value issue)

Hello,

I'm trying to store 10 values of sensor data to an array and for some reason the array is taking the last value and storing it as all 10 values in my array. If someone could help me understand what I'm doing wrong I would be exretemly appreciate.

#include <Wire.h>

int numReads=10;
int cont;
float sensor;
float sum;
float average;

float myArray[10];

const int ACPin = A2;
#define ACTectionRange 20;



#define VREF 3.3

float readACCurrentValue()
{
  float ACCurrtntValue = 0;
  float peakVoltage = 0;  
  float voltageVirtualValue = 0;  //Vrms
  for (int i = 0; i < 5; i++)
  {
    peakVoltage += analogRead(ACPin);   //read peak voltage
    delay(1);
  }
  peakVoltage = peakVoltage / 5;   
  voltageVirtualValue = peakVoltage * 0.707;    //change the peak voltage to the Virtual Value of voltage

  /*The circuit is amplified by 2 times, so it is divided by 2.*/
  voltageVirtualValue = (voltageVirtualValue / 1024 * VREF ) / 2;  

  ACCurrtntValue = voltageVirtualValue * ACTectionRange;

  return ACCurrtntValue;
}


void setup() {
  Serial.begin(9600);
  while(!Serial);
  
  do {

   float ACCurrentValue = readACCurrentValue(); 
  
   Serial.println(ACCurrentValue);
   
   //Serial.println(sum);
   for (int k = 0; k < numReads; k++){
    //sensor2 = 
    sensor = ACCurrentValue;
    myArray[k] = sensor;
    sum += sensor;
   }


   cont++;
  } while(cont < numReads);{ 
   average = sum/(numReads*10);
   Serial.print("Average: "); Serial.print(average);
   Serial.println(" ");
   Serial.print("Print Array Value:");Serial.print(myArray[4]);//Serial.println(" ");
   Serial.println(" ");
   for(int i = 0; i < numReads; i++)
{
  Serial.println(myArray[i]);
      }
   }
}

void loop() {
}

Here's screen shot of the serial monitor data

Try this and tell what is coming out!

got a double loop..
outer do, executes 10 times, the inner for loop puts the same last read value into the array..
if you want each element to be a sample, loose the for and use cont as the index into array..

This

   for (int k = 0; k < numReads; k++){
    //sensor2 = 
    sensor = ACCurrentValue;
    myArray[k] = sensor;
    sum += sensor;
   }

stores ten copies of the one time that this

   float ACCurrentValue = readACCurrentValue(); 

got execute. Try

   for (int k = 0; k < numReads; k++){
    //sensor2 = 
    sensor =  readACCurrentValue(); // read the sensor, Jim!
    myArray[k] = sensor;
    sum += sensor;
   }

HTH

a7

Hi @alto777 ,

Thank you for the tip! I updated the sensor variable and it worked great in the setup section.

I went to incorporate it into a loop, with a min and max array check, and after the 2nd or 3rd loop iteration, the max value freezes and then changes to OVF after awhile. Any chance you could provide me some insight into what I might be doing wrong? I also tried to zero out my array and min/max values at the end of the loop by setting them to zero but that didn't do anything. Your help would be greatly apprecaited.

Also, I removed the 2nd loop as that was totally unnecessary. Thanks for pointing that out @qubits-us !

#include <Wire.h>

int numReads=10;
int cont;
float sensor;
float sum;
float average;

float myArray[10];
float maxVal = myArray[10];
float minVal = myArray[10];
const int ACPin = A2;
#define ACTectionRange 20;



#define VREF 3.3

float readACCurrentValue()
{
  float ACCurrtntValue = 0;
  float peakVoltage = 0;  
  float voltageVirtualValue = 0;  //Vrms
  for (int i = 0; i < 5; i++)
  {
    peakVoltage += analogRead(ACPin);   //read peak voltage
    delay(1);
  }
  peakVoltage = peakVoltage / 5;   
  voltageVirtualValue = peakVoltage * 0.707;    //change the peak voltage to the Virtual Value of voltage

  /*The circuit is amplified by 2 times, so it is divided by 2.*/
  voltageVirtualValue = (voltageVirtualValue / 1024 * VREF ) / 2;  

  ACCurrtntValue = voltageVirtualValue * ACTectionRange;

  return ACCurrtntValue;
}


void setup() {
  Serial.begin(9600);
  while(!Serial);
  


      }


void loop() {
  

   for (int k = 0; k < numReads; k++){
    //sensor2 = 
    sensor = readACCurrentValue(); 
    Serial.print("VAL# ");Serial.println(sensor);
    myArray[k] = sensor;
       
   }
      {
  
       for (int i = 0; i < (sizeof(myArray) / sizeof(myArray[0])); i++) {
      maxVal = max(myArray[i],maxVal);
      minVal = min(myArray[i],minVal);
    } 
  }
{

Serial.print("The maximum value of the array is: ");
Serial.println(maxVal);
Serial.print("The minimum value of the array is: ");
Serial.println(minVal);
Serial.print("Print Array Value:");Serial.print(myArray[9]);//Serial.println(" "); //Just printing this to verify the array value placement is correct.
Serial.println(" ");
float maxVal = 0;
float minVal = 0;
float myArray = 0;
}
}
   

   

Serial com output

@johnwasser any insight you could lend would be amazing. Thanks in advance!

I'm under the umbrella and it's, well, hot. At a glance this code near the bottom of your loop is almost certainly not what you mean:

float maxVal = 0;
float minVal = 0;
float myArray = 0;

Those are three brand-new local variables! Those lines of code are definitions and initialisations.

You make three new floats, set them to zero, then return from loop(). When loop() gets called again, those variables are... gone.

Good thing they amount to the same as not being there at all: myArray is the name you picked for an array of floats. If you meant to set all the elements to 0.0, that will not do it. In fact, fixing those lines

   maxVal = 0;   // zero the one true and real maxVal
   minVal = 0;   // zero the one true and real maxVal
   myArray = 0;  // bzzzt!

would throw an error at compile time, as you cannot assign 0.0 to an array, which in this circumstance is actually a pointer to float.

Besides that, there is no need to zero out the array, if indeed that is what you wanted to do. Since the next thing that happens to every element of the array is

    myArray[k] = sensor;

that it gets overwritten by a new fresh recently read value.

If you did need to zero the array, one way to do that is with a loop over the entire array, zero them one by one.

Or! In the loop you do have, you could zero the element you will, with the vary next statement, fill with a new value

   for (int k = 0; k < numReads; k++){
    //sensor2 = 
      sensor = readACCurrentValue(); 
      Serial.print("VAL# ");Serial.println(sensor);

      myArray[k] = 0.0;
      myArray[k] = sensor;
       
   }

When you see it where I just put it, I think you can see that it is superfluouls. No need to make room for the new value.

While reading your code I made a note to tell you about, or remind you of, the IDE Auto Format tool, found where else but the Tools menu.

Also you have { braces } around some lines of code that are harmless but unecessary and not commonly used. To me, the less ink the better. I use braces, and parentheses too, only where necessary, or commonly done or in the case of some expressions to be clear and to avoid having to look up the rules governing where they must be sometimes to make things happen the way you want. For myself and as a courtesy to those whose first language might not be C or C++, and may face different language design decisions daily.

HTH

a7

Hi @alto777

I've updated my code to align with your suggestions. I can't have maxVal, minVal, or myArray without an identifier (i.e.- integer, float, etc...) or it errors out. The code runs with the below structure (thank you for the autoformat suggestion, totally forget that's there) but the max Val still freezes and displays a float number that's not even in the array. What would that be if the array is refreshing? I've supplied a screen shot of the serial monitor for your reference.

#include <Wire.h>

int numReads = 10;
int cont;
float sensor;
float sum;
float average;
float myArray[10];
float maxVal = 0.0;
float minVal = 0.0;
const int ACPin = A2;
#define ACTectionRange 20;



#define VREF 3.3

float readACCurrentValue()
{
  float ACCurrtntValue = 0;
  float peakVoltage = 0;
  float voltageVirtualValue = 0;  //Vrms
  for (int i = 0; i < 5; i++)
  {
    peakVoltage += analogRead(ACPin);   //read peak voltage
    delay(1);
  }
  peakVoltage = peakVoltage / 5;
  voltageVirtualValue = peakVoltage * 0.707;    //change the peak voltage to the Virtual Value of voltage

  /*The circuit is amplified by 2 times, so it is divided by 2.*/
  voltageVirtualValue = (voltageVirtualValue / 1024 * VREF ) / 2;

  ACCurrtntValue = voltageVirtualValue * ACTectionRange;

  return ACCurrtntValue;
}


void setup() {
  Serial.begin(9600);
  while (!Serial);



}


void loop() {


  for (int k = 0; k < numReads; k++) {
    //sensor2 =
    sensor = readACCurrentValue();
    Serial.print("VAL# "); Serial.println(sensor);
    myArray[k] = sensor;

  }
  {

    for (int i = 0; i < (sizeof(myArray) / sizeof(myArray[0])); i++) {
      maxVal = max(myArray[i], maxVal);
      minVal = min(myArray[i], minVal);
    }
  }
/*  {
    if (maxVal < 2.0) {
      Serial.println("ON");
    }
    else {
      Serial.println("OFF");
    }
  }*/
  {

    Serial.print("The maximum value of the array is: ");
    Serial.println(maxVal);
    Serial.print("The minimum value of the array is: ");
    Serial.println(minVal);
    Serial.print("Print Array Value:"); Serial.print(myArray[9]); //Serial.println(" "); //Just printing this to verify the array value placement is correct.
    Serial.println(" ");
      }
}


Do you expect a consistent peak voltage from five snapshots?
What are you measuring, and with what.

For mains AC it's common to measure continuously for a time of 3/4 of the sine wave,
and store the min and max peak readings in two variables.
Then you can calculate peak/peak by subtracting those two variables.
3/4 of a 50Hz sinewave is a measuring time of 15ms, and about 150 samples (not five).
Leo..

unsigned long startMillis;
int posPeak, negPeak, rawValue;

void loop() {
  startMillis = millis();
  posPeak = 0; // reset
  negPeak = 1023; // reset
  while (millis() - startMillis < 15UL) {
    rawValue = analogRead(A0);
    if (rawValue > posPeak) posPeak = rawValue;
    if (rawValue < negPeak) negPeak = rawValue;
  }
  rawValue = posPeak - negPeak; // peak/peak
}

I was unclear, sry.

You do want and need to zero the previously calculated min and max values.

Where you did tried to do that was correct.

And you are right, there does need to be a declaration and definition of those variables, which you always have had up at the top.

Now I just said zero the min and max, but that's not quite right, at least when the ten readings are all above zero… so where to put min and max before they are compared and replaced by newer smaller or larger numbers?

At the very end of the loop, where you had those pointless declarations, reset the min and max like this

    maxVal = -25000.0;
    minVal = 25000.0;

where I have arbitrary decided your real numbers will be between -25000 and 25000… presetting the minVal to the largest number you expect, and presetting maxVal to the other end of the range guarantees that the very first tests against a real number will replace both min and max with that value, myArray[0] in this case, on the first iteration of the loop.

The rest of the tests might move the min or max, of course.

I can see in your printout that at some point a high water mark of 1.76 was established, and the minimum of 0.0 is spurious as it probably just the initial value and no number less than zero ever came along.

The idea of presetting min and max at the opposite ends of a range is old. In some cases, like integers, the extreme numbers are known, like -32768 to 32767 in the case of a 16 bit integer. With floats, I don't know what ppl do, I just put some ridiculous and implausible impossible numbers in there.

HTH

a7

@alto777 I'm glad I wasn't thinking too far outside the box with resetting the min/max levels at the end of my previous code. Plugging the values in you suggested worked perfectly. I would have never guessed that would have been the solution. Thank you so much for your help and insight!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.