使用阵列获取传感器平均值

Getting Sensor Average using Arrays?

本文关键字:传感器 平均值 获取 阵列      更新时间:2023-10-16

首先,让我明确一点:我是一个彻头彻尾的傻瓜,我几乎没有编程经验,我知道我不在我的行列中,但我想学习和理解。问题来了。以下代码用于使用4个继电器控制加热垫,这些继电器根据4个lm35温度传感器检测到的温度而关闭/打开。因为这些传感器有时会跳动,我想从50个读数中获得平均温度,并让代码检查数据,而不是原始温度读数。我有arduino的代码(我写了一些代码,其他论坛上的人把它修改了,使它更短(这有点让我迷失了方向,但代码有效)然后我搜索了平滑数据,得到了一段代码,它完全符合我的要求:制作一个数组,计算平均温度,并不断删除和添加新数据。

我试着把这两个代码连接在一起,结果出现了各种各样的错误,哈哈我来了。

没有平均数据的代码是这样的:

const byte tempPin[] = {A1, A2, A3, A4};
const byte relayPin[] = {6, 7, 8, 9};
// hysteresis = upperLimit - lowerLimit
const byte lowerLimit = 24;
const byte upperLimit = 31;
float tempC[4];
word reading[4];

word printInterval = 1000; // 1 second
unsigned long printCheck = 0, lastPrintTime = 0;
void setup()
{
analogReference(INTERNAL);
Serial.begin(115200);
for (int i = 0; i < 4; i++) {
pinMode(relayPin[i], INPUT_PULLUP);
pinMode(relayPin[i], OUTPUT); // defaults HIGH, relay OFF
}
}
void loop()
{
// readings and control
for (int i = 0; i < 4; i++) {
reading[i] = analogRead(tempPin[i]);
tempC[i] = reading[i] / 9.31;

if (tempC[i] < lowerLimit) {
digitalWrite(relayPin[i], LOW);   //relay OFF
}
else if (tempC[i] > upperLimit) {
digitalWrite(relayPin[i], HIGH);  // relay ON
}
}
printCheck = millis() - lastPrintTime;
if (printCheck >= printInterval) {
for (int i = 0; i < 4; i++) {
Serial.print("tempC");
Serial.print(i + 1);
Serial.print(" ");
Serial.println(tempC[i]);
}
Serial.println();
lastPrintTime = millis(); // reset print timer
}
}

我从Arduino学习中心得到的平均代码是这样的:

/*
Smoothing
Reads repeatedly from an analog input, calculating a running average
and printing it to the computer.  Keeps ten readings in an array and
continually averages them.
The circuit:
* Analog sensor (potentiometer will do) attached to analog input 0
Created 22 April 2007
By David A. Mellis  <dam@mellis.org>
modified 9 Apr 2012
by Tom Igoe
http://www.arduino.cc/en/Tutorial/Smoothing
This example code is in the public domain.

*/

// 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
// use this value to determine the size of the readings array.
const int numReadings = 10;
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
int inputPin = A0;
void setup() {
// initialize serial communication with computer:
Serial.begin(9600);
// initialize all the readings to 0:
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
}
}
void loop() {
// subtract the last reading:
total = total - readings[readIndex];
// read from the sensor:
readings[readIndex] = analogRead(inputPin);
// 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(1);        // delay in between reads for stability
}

我创建的加入两个代码的怪物是这样的:

const byte tempPin[] = {A1, A2, A3, A4};
const byte relayPin[] = {6, 7, 8, 9};
// hysteresis = upperLimit - lowerLimit
const byte lowerLimit = 24;
const byte upperLimit = 31;
float tempC[4];
word reading[4];
const int numReadings = 50;
int readings[numReadings];
int readIndex = 0;
int total = 0;
float average[4];

word printInterval = 1000; // 1 second
unsigned long printCheck = 0, lastPrintTime = 0;
void setup()
{
analogReference(INTERNAL);
Serial.begin(115200);
for (int i = 0; i < 4; i++) {
pinMode(relayPin[i], INPUT_PULLUP);
pinMode(relayPin[i], OUTPUT); // defaults HIGH, relay OFF
}
for (int thisReading = 0; thisReading < numReadings; thisReading++){
readings[thisReading] = 0;
}
}
void loop()
{
// readings and control
for (int i = 0; i < 4; i++) {
reading[i] = analogRead(tempPin[i]);
tempC[i] = reading[i] / 9.31;
total[i] = total[i] - readings[readIndex];
readings[readIndex] = tempC[i]
total[i] = total[i] + readings[readIndex]
readIndex[i] = readIndex[i] + 1 ;
if (readIntex[i] >= numReadings) {
readIndex = 0;
}
average[i] = total[i] / numReadings;
if (average[i] < lowerLimit) {
digitalWrite(relayPin[i], LOW);   //relay OFF
}
else if (average[i] > upperLimit) {
digitalWrite(relayPin[i], HIGH);  // relay ON
}
}
printCheck = millis() - lastPrintTime;
if (printCheck >= printInterval) {
for (int i = 0; i < 4; i++) {
Serial.print("tempC");
Serial.print(i + 1);
Serial.print(" ");
Serial.println(tempC[i]);
}
Serial.println();
lastPrintTime = millis(); // reset print timer
}
}

这些是我得到的错误:

Arduino: 1.6.8 (Windows 7), Board: "Arduino/Genuino Uno"
temprelayfinal2.ino: In function 'void loop()':
temprelayfinal2:40: error: invalid types 'int[int]' for array subscript
total[i] = total[i] - readings[readIndex];
^
temprelayfinal2:40: error: invalid types 'int[int]' for array subscript
total[i] = total[i] - readings[readIndex];
^
temprelayfinal2:42: error: expected ';' before 'total'
total[i] = total[i] + readings[readIndex]
^
temprelayfinal2:44: error: 'readIntex' was not declared in this scope
if (readIntex[i] >= numReadings) {
^
temprelayfinal2:47: error: invalid types 'int[int]' for array subscript
average[i] = total[i] / numReadings;
^
exit status 1
invalid types 'int[int]' for array subscript
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

注释:其他人已经在问题的注释中指出了您的代码没有编译的原因。

更详细地说,您声明无论是total还是readIndex都不是数组,在44行有一个打字错误(readIntex而不是readIndex)和两个missing半列

但是,在仔细阅读您的代码后,我认为即使应用这些语法修复,您也无法获得一段符合您要求的代码。

因此,我将在这里根据您的问题和尝试的描述,提供我对所需源代码的解释

我可以验证它是否编译,但是-因为我缺少硬件-我无法测试它。

(免责声明:我对Arduino风格指南很反感所以我提前为采用个人代码样式道歉。)


#include<Arduino.h>
#define NUM_SENSORS  4
#define NUM_READINGS 5
#define LOWER_LIMIT 24
#define UPPER_LIMIT 31
#define PRINT_PERIOD 1000
#define TEMPERATURE_FACTOR 9.31
/* global variables */
const byte tempPin[] = {A1, A2, A3, A4};
const byte relayPin[] = {6, 7, 8, 9};
word readings[NUM_SENSORS][NUM_READINGS] = {};
word totals[NUM_SENSORS] = {};
float averages[NUM_SENSORS] = {};
unsigned long time_elapsed = 0;
word num_readings = 0;
word j = 0;
/* setup */
void setup()
{
analogReference(INTERNAL);
Serial.begin(115200);
for (int i = 0; i < 4; i++)
{
pinMode(relayPin[i], INPUT_PULLUP);
pinMode(relayPin[i], OUTPUT); // defaults HIGH, relay OFF
}
}
/* main loop */
void loop()
{
// keep track of actual readings:
// (prevents under-estimation of initial values
// due to a too large smoothing window)
if (num_readings < NUM_READINGS)
{
num_readings++;
}
for (int i = 0; i < NUM_SENSORS; i++)
{
// subtract the last reading:
totals[i] = totals[i] - readings[i][j];
// read from the sensor:
readings[i][j] = analogRead(tempPin[i]);
// add the reading to the total:
totals[i] = totals[i] + readings[i][j];
// update average
averages[i] = ((float) totals[i] / TEMPERATURE_FACTOR) / (float) num_readings;
// uncomment to optionally delay action on relays
// up until when the smooth window has been filled up
// if (num_readings == NUM_READINGS) {
if (averages[i] < LOWER_LIMIT)
{
digitalWrite(relayPin[i], LOW);   // relay OFF
} else if (averages[i] > UPPER_LIMIT) {
digitalWrite(relayPin[i], HIGH);  // relay ON
}
// }
}
// advance the reading index:
j = (j + 1) % NUM_READINGS;
unsigned long curr_time = millis();
static unsigned long start_time = curr_time; // initialized only once
if ((curr_time - start_time) >= PRINT_PERIOD)
{
for (int i = 0; i < 4; i++)
{
Serial.print("tempC");
Serial.print(i + 1);
Serial.print(" ");
Serial.println(averages[i]);
}
Serial.println();
start_time = curr_time; // not really best solution, but
// i don't want to bloat the code
}
delay(1); // waste some time
}

注意:我保留了单词类型的总计读数,以避免浮点操作的典型障碍。


附加说明

  1. 有一个50读数的平滑窗口对我来说听起来非常可疑,根据我的经验,最后3-5个读数应该足够了,也许其间有更大的延迟

  2. 既然你还在学习,我建议你在上分享你的工作(小)项目https://codereview.stackexchange.com/以便获得一些非常好的反馈。(: