Arduino:用来自analogRead()的值填充数组

问题描述 投票:0回答:1

如何在 Arduino 上使用

analogRead()
的值填充数组?

以每秒一次的固定间隔,我想通过

A0
)从模拟输入引脚
analogRead(A0
读取一个值,并将这些值存储到一个数组中。

理想情况下,其他代码也能够在测量之间运行。

arrays arduino multitasking
1个回答
6
投票

假设您想要读取最多 100 个值,请执行以下操作:

1。技术不佳(使用带有

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
}

注意:括号中的数字不能太大。例如:

analogVals[2000]
将无法工作,因为它占用了太多 RAM。

PS。这是 Arduino 在网站帮助中介绍的非常基本的内容。对于此类问题,请从现在开始参考这里,并先自己尝试一下:http://arduino.cc/en/Reference/HomePage --> 单击“数据类型”下的“数组”。

2。替代方法(也是一种糟糕的技术,因为它使用带有

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
  }
}

更新:2018 年 10 月 6 日

3.最佳技术(非阻塞方法——不

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。专业类型方法(非阻塞方法,通过传递指针来避免全局变量,使用C stdint类型,并使用静态变量来存储本地持久数据):

// 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;
}

上面最后一个代码的串行监视器输出示例:

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]  

更多阅读/研究:

  1. 我对如何做基于时间戳的裸机协作多任务的彻底回答:从没有中断引脚且在测量准备好之前需要一些时间的传感器读取数据的最佳方法
  2. Arduino 非常基础但非常有用“无延迟闪烁”教程:https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
© www.soinside.com 2019 - 2024. All rights reserved.