2

How to fill array with values from analogRead on arduino. every second arduino reads value from analog0 and i want to put these readings to array.

botero
  • 598
  • 2
  • 11
  • 23

1 Answers1

6

Let's say you want to read up to 100 values, do this:

1. Poor technique (uses blocking code with delay()):

//let's say you want to read up to 100 values
const unsigned int numReadings = 100;
unsigned int analogVals[numReadings];
unsigned int i = 0;

void setup()
{
}

void loop()
{
  analogVals[i] = analogRead(A0);
  i++;
  if (i>=numReadings)
  {
    i=0; //reset to beginning of array, so you don't try to save readings outside of the bounds of the array
  }
  delay(1000); //wait 1 sec
}

Note: you cannot make the number in brackets too large. Ex: analogVals[2000] will not work because it takes up too much RAM.

PS. This is pretty basic stuff that Arduino covers in their help on the website. Please reference here from now on for questions like this, and give it a shot yourself first: http://arduino.cc/en/Reference/HomePage --> click on "array" under "Data Types."

2. Alternate method (also a poor technique, since it uses blocking code with delay()):

//let's say you want to read up to 100 values
const unsigned int numReadings = 100;
unsigned int analogVals[numReadings];

void setup()
{
}

void loop()
{
  //take numReadings # of readings and store into array
  for (unsigned int i=0; i<numReadings; i++)
  {
    analogVals[i] = analogRead(A0);
    delay(1000); //wait 1 sec
  }
}

UPDATE: 6 Oct. 2018

3. Best technique (non-blocking method--no delay!):

//let's say you want to read up to 100 values
const unsigned int numReadings = 100;
unsigned int analogVals[numReadings];
unsigned int i = 0;

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

void loop()
{
  static uint32_t tStart = millis(); // ms; start time
  const uint32_t DESIRED_PERIOD = 1000; // ms
  uint32_t tNow = millis(); // ms; time now
  if (tNow - tStart >= DESIRED_PERIOD)
  {
    tStart += DESIRED_PERIOD; // update start time to ensure consistent and near-exact period

    Serial.println("taking sample");
    analogVals[i] = analogRead(A0);
    i++;
    if (i>=numReadings)
    {
      i = 0; //reset to beginning of array, so you don't try to save readings outside of the bounds of the array
    }
  }
}

4. Professional-type approach (non-blocking method, avoids global variables by passing around pointers instead, uses C stdint types, and uses static variables to store local, persistent data):

// Function prototypes
// - specify default values here
bool takeAnalogReadings(uint16_t* p_numReadings = nullptr, uint16_t** p_analogVals = nullptr);

void setup()
{
  Serial.begin(115200);
  Serial.println("\nBegin\n");
}

void loop()
{
  // This is one way to just take readings
  // takeAnalogReadings();

  // This is a way to both take readings *and* read out the values when the buffer is full
  uint16_t numReadings;
  uint16_t* analogVals;
  bool readingsDone = takeAnalogReadings(&numReadings, &analogVals);
  if (readingsDone)
  {
    // Let's print them all out!
    Serial.print("numReadings = "); Serial.println(numReadings);
    Serial.print("analogVals = [");
    for (uint16_t i=0; i<numReadings; i++)
    {
      if (i!=0)
      {
        Serial.print(", ");
      }
       Serial.print(analogVals[i]);
    }
    Serial.println("]");
  }
}

// Function definitions:

//---------------------------------------------------------------------------------------------------------------------
// Take analog readings to fill up a buffer.
// Once the buffer is full, return true so that the caller can read out the data.
// Optionally pass in a pointer to get access to the internal buffer in order to read out the data from outside
// this function.
//---------------------------------------------------------------------------------------------------------------------
bool takeAnalogReadings(uint16_t* p_numReadings, uint16_t** p_analogVals)
{
  static const uint16_t NUM_READINGS = 10;
  static uint16_t i = 0; // index
  static uint16_t analogVals[NUM_READINGS];

  const uint32_t SAMPLE_PD = 1000; // ms; sample period (how often to take a new sample)
  static uint32_t tStart = millis(); // ms; start time
  bool bufferIsFull = false; // set to true each time NUM_READINGS have been taken

  // Only take a reading once per SAMPLE_PD
  uint32_t tNow = millis(); // ms; time now
  if (tNow - tStart >= SAMPLE_PD)
  {
    Serial.print("taking sample num "); Serial.println(i + 1);
    tStart += SAMPLE_PD; // reset start time to take next sample at exactly the correct pd
    analogVals[i] = analogRead(A0);
    i++;
    if (i >= NUM_READINGS)
    {
      bufferIsFull = true;
      i = 0; // reset to beginning of array, so you don't try to save readings outside of the bounds of the array
    }
  }

  // Assign the user-passed-in pointers so that the user can retrieve the data if they so desire to do it this way
  if (p_numReadings != nullptr)
  {
    *p_numReadings = NUM_READINGS;
  }
  if (p_analogVals != nullptr)
  {
    *p_analogVals = analogVals;
  }

  return bufferIsFull;
}

Sample Serial Monitor output from the last code just above:

Begin  

taking sample num 1  
taking sample num 2  
taking sample num 3  
taking sample num 4  
taking sample num 5  
taking sample num 6  
taking sample num 7  
taking sample num 8  
taking sample num 9  
taking sample num 10  
numReadings = 10  
analogVals = [1023, 1023, 1023, 1023, 1023, 687, 0, 0, 0, 0]  
taking sample num 1  
taking sample num 2  
taking sample num 3  
taking sample num 4  
taking sample num 5  
taking sample num 6  
taking sample num 7  
taking sample num 8  
taking sample num 9  
taking sample num 10  
numReadings = 10  
analogVals = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]  

More reading/study:

  1. My thorough answer on how to do time-stamp-based bare-metal cooperative multi-tasking: Best way to read from a sensor that doesn't have interrupt pin and requires some time before the measurement is ready
  2. Arduino's very basic but extremely useful "Blink Without Delay" tutorial: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
  • How can analogRead return either an int or an unsigned int? – CatsLoveJazz Aug 14 '16 at 12:05
  • According to the [source code on line 38 here](https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/wiring_analog.c) `analogRead()` returns an `int`. However, since the range is only 0-1023, it would make the most sense to store it into a `uint16_t`, which is the equivalent of `unsigned int` on ATmega328-based Arduinos. The compiler will automatically cast types as required to make them get stored into alternate types (ex: `unsigned int` <--> `int`), with loss of data only if you are outside the valid bounds of the new type. In this case it is safe. – Gabriel Staples Oct 06 '18 at 20:09
  • It is safe because `analogRead` returns 0-1023, and `unsigned int` can store values from 0 to 65,535 (see https://www.arduino.cc/reference/en/language/variables/data-types/unsignedint/), while `int` can store values from -32,768 to 32,767 (see https://www.arduino.cc/reference/en/language/variables/data-types/int/). As you can see, both can easily store values in the 0-1023 range. – Gabriel Staples Oct 06 '18 at 20:12