Предотвращение сброса нулевого веса при использовании HX711 с тензодатчиком
Здравствуйте,
Я использую модуль HX711 и тензодатчик с Arduino Uno для измерения силы.
Я использую эту библиотеку.
Сначала я использую пример кода "Calibration" для калибровки с вес 200 г. Затем я сохраняю константу калибровки в eeprom (выбирая «да» на последовательном мониторе). Тогда тензодатчик сможет точно измерять вес.
После этого я убираю груз с тензодатчика и запускаю этот код после раскомментирования последней строки этой части приведенного выше кода:
LoadCell.begin();
//LoadCell.setReverseOutput();
float calibrationValue;
calibrationValue = 696.0;
#if defined(ESP8266)|| defined(ESP32)
//EEPROM.begin(512);
#endif
EEPROM.get(calVal_eepromAdress, calibrationValue); // я раскомментировал это
Вес измеряется точно.
Но когда перед включением Arduino я держу вес на тензодатчике, этот вес принимается равным 0.
Для этого я внес в код следующие изменения:
boolean _tare = false;
Но я получаю следующий вывод на последовательном мониторе (Примечание: следующий вывод получается при запуске, когда на тензодатчике есть/отсутствует груз):
Вопросы: Какая польза от следующей строки:
calibrationValue = 696.0; // раскомментируйте это, если вы хотите установить значение калибровки в скетче
Это бесполезно для кода, который я использую выше? Потому что я использую значение калибровки из eeprom.
В2) Почему в качестве выходного значения отображается -39000? И как это исправить?
Альтернативное утверждение: Другими словами, я хочу использовать модуль HX711 с Arduino и тензодатчиком. Сначала я откалибрую его с известным весом и сохраню значение калибровки. Перед включением Arduino я буду держать груз на тензодатчике. После включения значение веса должно быть абсолютным значением, а не нулевым значением веса.
EDIT1: Я включаю изменения, предложенные в ответах @Edgar Bonet, а также на всякий случай делаю проблему более ясной. По предложениям я внес соответствующие изменения в калибровочный код. Затем я запускаю это, и значения сохраняются в eeprom. Изменения кода:
const int calVal_eepromAdress = 0;
const int tare_eepromAdress = sizeof(float);
и
#endif
EEPROM.put(calVal_eepromAdress, newCalibrationValue);
EEPROM.put(tare_eepromAdress, LoadCell.getTareOffset());
#if defined(ESP8266)|| defined(ESP32)
EEPROM.commit();
Теперь я хочу запустить второй скрипт и для этого отображать правильные веса. Это должно работать во всех случаях, независимо от того, был ли сохранен груз на датчике нагрузки или он был сохранен, и не должен зависеть от сохраненного веса. В этот скрипт я внес следующие изменения:
const int calVal_eepromAdress = 0;
const int tare_eepromAdress = sizeof(float);
и
// Внутри void setup()
void setup() {
Serial.begin(57600); delay(10);
Serial.println();
Serial.println("Starting...");
LoadCell.begin();
//LoadCell.setReverseOutput(); // раскомментируйте, чтобы преобразовать отрицательное выходное значение в положительное
float calibrationValue; // значение калибровки (см. пример файла «Calibration.ino»)
float tareValue;
calibrationValue = 696.0; // раскомментируйте это, если вы хотите установить значение калибровки в скетче
tareValue = 0;
#if defined(ESP8266)|| defined(ESP32)
//EEPROM.begin(512); // раскомментируйте это, если вы используете ESP8266/ESP32 и хотите получить значение калибровки из eeprom
#endif
EEPROM.get(calVal_eepromAdress, calibrationValue); // раскомментируйте это, если хотите получить значение калибровки из eeprom
EEPROM.get(tare_eepromAdress, tareValue);
unsigned long stabilizingtime = 2000; // точность сразу после включения питания можно улучшить, добавив несколько секунд времени стабилизации
boolean _tare = true; // установите значение false, если вы не хотите, чтобы тарирование выполнялось на следующем шаге
LoadCell.start(stabilizingtime, _tare);
if (LoadCell.getTareTimeoutFlag()) {
Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
while (1);
}
else {
LoadCell.setCalFactor(calibrationValue); // устанавливаем калибровочное значение (с плавающей запятой)
LoadCell.setTareOffset(tareValue);
Serial.println("Startup is complete");
}
}
EDIT2:
#if defined(ESP8266)|| defined(ESP32)
EEPROM.begin(512);
#endif
EEPROM.put(calVal_eepromAdress, newCalibrationValue);
EEPROM.put(tare_eepromAdress, LoadCell.getTareOffset());
Serial.println(newCalibrationValue);
Serial.println(LoadCell.getTareOffset());
Вывод:
-206.90
8368790
Во втором скрипте:
-206.90
8368790
Вывод:
-206.90
0.00
На всякий случай я загружаю свои коды на Github. Их можно найти здесь.
В) Что здесь происходит?
EDIT3: Следующие изменения заставляют его работать как шарм: В разделе «Калибровка» скрипт:
#if defined(ESP8266)|| defined(ESP32)
//EEPROM.begin(512); // uncomment this if you use ESP8266/ESP32 and want to fetch the calibration value from eeprom
#endif
EEPROM.get(calVal_eepromAdress, calibrationValue); // uncomment this if you want to fetch the calibration value from eeprom
EEPROM.get(tare_eepromAdress, tareValue);
Serial.println(calibrationValue);
Serial.println(tareValue);
Аналогично во втором скрипте:
-206.90
0.00
@Atharva, 👍3
Обсуждение1 ответ
Лучший ответ:
Чтобы преобразовать необработанные показания АЦП в вес, библиотеке необходимо два коэффициента:
- «смещение тары», то есть необработанное показание, когда на масштаб
- коэффициент усиления или «коэффициент калибровки», представляющий собой отношение изменения АЦП считывает соответствующее изменение веса.
Примеры, поставляемые с библиотекой, используют EPPROM для хранения и получить коэффициент калибровки, но не смещение тары. Это делает в том смысле, что при обычном использовании весы всегда обнуляются при включении питания, или сразу после включения. Обычно это желательно, поскольку часто поместите на весы пустую емкость, которая не должна влиять на отображаемый вес.
Если вы не хотите обнулять шкалу при включении питания, вам понадобится
скетч для запоминания смещения тары в дополнение к калибровке
фактор. Для этого вы можете использовать методы LoadCell
:
// Получаем смещение тары (вывод исходного значения данных без
// шкала "calFactor").
long getTareOffset();
// Установить новое смещение тары (ввод исходных данных без
// шкала "calFactor").
void setTareOffset(long newoffset);
Теперь более конкретные вопросы:
Какой смысл в следующей строке:
calibrationValue = 696.0;
Нет. Это просто пример. Вы должны либо заменить это
номер с вашим измеренным калибровочным коэффициентом, или удалите эту строку и
прочитать калибровка_значения
из EEPROM.
Почему в качестве выходного значения отображается -39000?
Поскольку смещение тары не было задано, предположительно по умолчанию ноль.
ОБНОВЛЕНИЕ: ответы на дополнительные вопросы в комментарии.
Нужно ли сохранять это значение в EEPROM при запуске сценарий калибровки?
Вы можете сохранить его в любое удобное для вас время. Калибровка сценарий кажется хорошим местом.
Я не могу вставить это в код. Я читаю исходные файлы, но я не знаете, какие изменения внести.
Что вы можете попробовать (не проверено):
сразу после строки
const int calVal_eepromAdress = 0;
добавьте это:
const int tare_eepromAdress = sizeof(float);
Сразу после этого:
EEPROM.put(calVal_eepromAdress, newCalibrationValue);
добавьте это:
EEPROM.put(tare_eepromAdress, LoadCell.getTareOffset());
Спасибо, это имеет смысл. Нужно ли сохранять это значение в eeprom при запуске сценария калибровки? Я не могу получить это в коде. Я прочитал исходные файлы, но не уверен, какие изменения нужно внести в [калибровку](https://github.com/olkal/HX711_ADC/blob/master/examples/Calibration/Calibration.ino) и во [второй скрипт]. (https://github.com/olkal/HX711_ADC/blob/master/examples/Read_1x_load_cell/Read_1x_load_cell.ino). Любая помощь приветствуется., @Atharva
Я внес предложенные вами изменения, а также добавил изменения во второй сценарий. Я уточняю изменения в исходном вопросе. Пожалуйста, посмотрите, @Atharva
Что касается ваших изменений, вам, вероятно, следует установить _tare
в false, чтобы избежать двойной установки смещения тары. Вы также можете избавиться от части if (LoadCell.getTareTimeoutFlag())
и безоговорочно установить как коэффициент калибровки, так и смещение тары., @Edgar Bonet
Это все еще не работает. Я получаю -40000 на последовательном мониторе. Я показываю изменения и результаты [здесь](https://imgur.com/a/uwj8GJp)., @Atharva
Хорошо, кажется, что правильное значение не сохраняется для значения тары. Я показываю это в EDIT2 в своем посте., @Atharva
@Atharva: Re «_EDIT2_»: метод getTareOffset()
возвращает long
, и это то, что вы сохраняете в EEPROM. В LoadCell\_Read.ino вы EEPROM.get()
это значение преобразуете в float
. Это в основном переосмысление битового шаблона «long», как если бы это было «поплавок». Полученное значение составляет около 1,17e-38, что печатается как «0,00»., @Edgar Bonet
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Проверяли ли вы, какое значение имеет значение калибровки перед записью в EEPROM и после чтения из EEPROM? Просто чтобы проверить, правильно ли работает хранилище значения. И вам нужно запустить EEPROM, чтобы он работал правильно., @chrisl
@chrisl да, это читается правильно., @Atharva
см. файл примера библиотеки
Persistent_zero_offset.ino
., @olkal