В среднем 10 показаний, неверно

Я читаю из ячейки загрузки и вычисляю среднее значение последних 10 показаний. Но когда тензодатчик считывает что-то большее, чем 3800 г, среднее значение становится отрицательным, как? Масса, которую я читаю, не является отрицательными числами. Я пытался найти свою ошибку, но не смог. Какая-нибудь помощь?

#include "HX711.h"

const int numReadings = 10;
const int LOADCELL_DOUT_PIN = 8;
const int LOADCELL_SCK_PIN = 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 mass  =0;
long reading = 0;

HX711 scale;

float a = 0.0088;
float b = 2009.7;


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;
  }
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
}

void loop() {
  if (scale.is_ready()) {
    // read from the sensor:
    reading = scale.read();
    // convert to mass  
    mass = int((a*reading)-b);
    // subtract the last reading:
    total = total - readings[readIndex];
   
    Serial.print(int((a*reading)-b));
    readings[readIndex] = mass;
    // 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.print("   ");
    Serial.print(average);
    Serial.println("");
    delay(1000);        // delay in between reads for stability
  }
  else{
    Serial.print("loadcell not found!");
  }
}

, 👍3

Обсуждение

Это называется "целочисленная оболочка" - " int " может содержать только от -32768 до +32767 на 8-разрядном Arduino., @Majenko

Боже, большое вам спасибо за помощь. Я боролся с этим, @animos_be

совет, если вы знаете, что он должен содержать только положительные числа, объявите его целым числом без знака., @Swedgin


2 ответа


0

Как уже прокомментировал Майенко, проблема в целочисленном охвате. Одним из решений было бы избавиться от этой общей переменной и вычислять каждое новое среднее значение на основе предыдущего среднего и массы, которую вы заменяете в массиве, используя эту формулу:

new_average = old_average + (mass - readings[readIndex]) / numReadings

Таким образом, ваш код будет выглядеть следующим образом:

  if (scale.is_ready()) {
    // считывание с датчика:
    reading = scale.read();
    // преобразовать в массу
    mass = int((a*reading)-b);

    // вычислите новое среднее значение:
    new_average = average + (mass - readings[readIndex]) / numReadings;
   
    Serial.print(int((a*reading)-b));
    readings[readIndex] = mass;

    // переход на следующую позицию в массиве:
    readIndex = readIndex + 1;
  
    // если мы находимся в конце массива...
    if (readIndex >= numReadings) {
      // ...оборачиваемся к началу:
      readIndex = 0;
    }
  
    // установите среднее значение:
    average = new_average;

    // отправьте его на компьютер в виде цифр ASCII
    Serial.print("   ");
    Serial.print(average);
    Serial.println("");
    delay(1000);        // задержка между считываниями для обеспечения стабильности
  }

Просто не забудьте добавить объявление для new_average в начало вашего кода.

,

2

Другим вариантом было бы использовать "длинный" в качестве типа переменной для total. В зависимости от вашего приложения вы также можете изучить экспоненциально взвешенную скользящую среднюю (EWMA); она может уменьшить акцент на более старых точках данных, если это проблема.

,