Сглаживание показаний hx711 с помощью atmega328
Я делаю весы на 50 кг, используя АЦП HX711. Мой проект включает Atmega328 вместе с 74HC595 для управления 5 7-сегментными дисплеями (мультиплексорными). Я использую функцию scale.get_units()
для получения данных, и значения очень хорошо отображаются в 7 сегментах. Проблема, с которой я столкнулся, заключается в том, что показания 5-й цифры (самые правые единицы) нестабильны. Теперь, если я использую scale.read_average(5)
, сканирование дисплея замедляется. Мне было интересно, есть ли способ усреднить показания в цикле, как это делается обычным способом. Я попробовал, но безуспешно! Он продолжает показывать случайные добавленные числа. Любая помощь будет высоко оценена. Ниже приведен код внутри цикла. Дайте мне знать, если нужен полный код. Заранее спасибо!
if (scale.is_ready()) {
weight = scale.get_units();
finalWeight = weight * 1000;
}
for (int i = 0; i < 10 ;i++) {
sum += finalWeight;
}
average = sum / 10;
if (average < 0) {
break_number(0);
} else {
break_number(average);
}
display_number();
delay(1);
@spdif, 👍2
1 ответ
Прежде всего, этот код:
for (int i = 0; i < 10 ;i++) {
sum += finalWeight;
}
average = sum / 10;
не усредняет несколько показаний. Вместо этого требуется одно чтение
хранится в finalWeight
, умножает его на десять (посредством последовательных
сложения), а затем делит его на десять, чтобы получить то же значение.
Если вы хотите уменьшить шум, вам придется снять несколько показаний и усредните их. Таким образом, код чтения должен находиться внутри цикла. А простой вариант может быть таким:
void loop() {
sum = 0;
for (int i = 0; i < 10; i++) {
while (!scale.is_ready()) {} // ждем, пока весы будут готовы
sum += scale.get_units();
}
weight = sum / 10; // вычисляем среднее значение
display(weight); // и отображаем его
}
Обратите внимание, что я немного упростил задачу, убрав масштабирование. факторы. Вы можете воспринимать это как простое вдохновение и адаптироваться к своим конкретные потребности.
Однако у приведенного выше кода есть одна проблема: поскольку код блокируется во время ждем готовности весов, дисплей не обновляется. Ты можно исправить это, явно обновив дисплей во время ожидания цикл:
void loop() {
sum = 0;
for (int i = 0; i < 10; i++) {
while (!scale.is_ready()) { // подождем...
display(weight); // ...при обновлении дисплея
}
sum += scale.get_units();
}
weight = sum / 10;
display(weight);
}
Это должно сработать, но вместо этого я бы предложил третий подход: написать неблокирующий код. Это код, который никогда не блокируется: вместо этого, если что-то можно сделать прямо сейчас, оно это делает. Если нет, он движется дальше:
void loop() {
if (scale.is_ready()) { // можно ли сделать что-то полезное СЕЙЧАС:
sum += scale.get_units();
count++;
if (count >= 10) {
weight = sum / count; // обновляем отображаемое значение
sum = 0; // сбрасываем переменные усреднения
count = 0;
}
}
display(weight); // безусловно обновляем дисплей
}
Таким образом, ваш loop()
всегда работает быстро, и вы можете добавить код, который будет
не быть заблокированным тем, что вы написали ранее.
Обновлено. Как предположил Крисл в комментарии, скользящее среднее может лучше удовлетворить ваши потребности. Я бы попробовал экспоненциально взвешенную версию, поскольку он легче и проще в реализации. Возможно, вы захотите изучить этот путь.
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Кроме того: здесь хорошим выбором может быть скользящее среднее, как во втором ответе на [этот вопрос](https://stackoverflow.com/questions/67208086/how-can-i-calculate-a-moving-average- в ардуино), @chrisl
Большое спасибо!! Я попробую., @spdif