В рамках данной статьи мы построим систему для измерения веса на базе ESP32, используя тензодатчик консольного (балочного) типа и специализированный модуль аналого-цифрового преобразователя HX711.

На практике возникают задача, связанные с измерением веса, силы натяжения или величины давления. Для этих целей отлично подходит тензометрический сенсор балочного (консольного типа):

Тензометрический датчик балочного (консольного) типа — это устройство, предназначенное для измерения деформаций (прогибов) в строительных конструкциях под воздействием механических нагрузок (контроля прочности и устойчивости), а также для взвешивания различных грузов. Яркими примерами являются: бытовые кухонные весы, контроль несущих конструкций цистерны с водой, проверка нагрузки на крышу склада (для своевременной уборки снега).
Принцип работы тензодатчика
Принцип действия данного устройства основано на тензоэффекте: изменение электрического сопротивления материала при различных деформациях, таких как сжатие, скручивание и растяжение.
Чувствительным элементом рассматриваемого типа сенсора является тензорезистор, который представляет собой гибкую диэлектрическую мембрану, на которой нанесён методом напыления проводящий слой (в виде зигзагообразной дорожки). При деформации данной мембраны её электрическое сопротивление изменяется:

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

Для работы с датчиком необходимо правильно его установить:
— с одной из сторон есть выход сигнального кабеля. Это опорная сторона, которая должна быть жёстко закреплена, поскольку является точкой опоры для рычага, относительно которой балка с тензорезисторами изгибается;
— противоположная сторона является точкой приложения измеряемого веса. Как правило, эта сторона обозначается стрелкой.
Устройство на опорной стороне должно быть жестко закреплено на подставку, которая не будет прогибаться в процессе приложения веса на рычаг.
Когда на тензодатчик воздействует сила, он деформируется (сжимается, растягивается или скручивается). После снятия нагрузки он возвращается в своё первоначальное состояние. Датчик сконструирован так, чтобы максимальная деформация происходила в определённых участках, например, на тонких местах балки, где фиксируется наибольшее напряжение. Тензорезисторы устанавливаются именно на этих участках и соединяются в мостовую схему Уинстона. Если конструкция балки сенсора будет без специальных вырезов, то определить распределение нагрузки окажется неравномерной и нелинейной.
Аналого-цифровой преобразователь HX711
Для работы с тензометрическими сенсорами широкую популярность приобрела микросхема HX711 — это 24-разрядный аналого-цифровой преобразователь (АЦП) со встроенным усилителем, разработанный компанией AVIA Semiconductor. Он широко используется в самодельных и промышленных весах, динамометрах, системах автоматизации и других устройствах, где требуется точное измерение малых изменений напряжения, вызванных деформацией тензометрических сенсоров. Основные параметры представлены в таблице ниже:

В продаже можно встретить множество различных готовых модулей в виде печатных плат, на которых уже распаяна микросхема со всей необходимой обвязкой:
— модуль с металлическим экраном. Некоторые партии таких модулей могут иметь серьёзный изъян, который выражается в разделении цепей GND по питанию микросхемы и по питанию тензодатчика, поэтому необходимо устанавливать перемычку
— двухканальный модуль (каналы А и В)

— одноканальный модуль (канал А) CJMCU-711, который будем использовать в нашем эксперименте

На самом деле на этой платке можно подключиться к второму каналу В, для этого выделены две контактные площадки, к которым можно припаять дополнительный разъём. Но мы воспользуемся каналом А по умолчанию.
Ниже представлена распиновка модуля CJMCU-711:

Для общего понимания ниже представлены цоколёвка микросхемы АЦП и её типичная схема включения по рекомендации производителя:


Экспериментальная установка
В нашем эксперименте применим промышленный тензометрический датчик BCL-10L южнокорейской компании CAS Corporation:


Распиновка сигнального кабеля сенсора BCL-10L:


Параметры тензометрического датчика BCL-10L CAS Corporation:

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


Как подключить тензодатчик к АЦП HX711
Для работы с АЦП будем использовать аппаратный SPI-интерфейс на отладочной плате NodeMCU-32S (38 pin), которая построена на базе модуля ESP-WROOM-32. Для отображения результатов взвешивания воспользуемся TFT-дисплеем на базе контроллера ST7735S. Ниже представлены таблицы подключений АЦП к тензометрическому сенсору BCL-10L и к отладочной плате.
Подключение тензодатчика к АЦП

Подключение АЦП к ESP32

Подключение TFT-дисплея к ESP32

Ниже представлена схема подключений и фотография собранного макета:


Программный код (скетч)
Проект создавался в среде программирования PlatformIO (расширение для Visual Studio Code) с использованием фреймворка Arduino, чтобы обеспечить совместимость с соответствующей IDE.
Для работы с TFT-дисплеем воспользуемся библиотекой tft_eSPI, о настройке и работе с которой подробно описано в статье про джойстик KY-023.
Что касается работы с модулем аналого-цифрового преобразователя, то рекомендую применить библиотеку HX711 by Rob Tiillaart.
Калибровка тензодатчика
Прежде чем производить взвешивание грузов с помощью тензовесов, необходимо выполнить калибровку. Загрузите в микроконтроллер следующий подробно прокомментированный код:
#include "HX711.h" // Подключаем библиотеку HX711
HX711 scale; // Создаём объект scale
#define DT 21 // Указываем номер вывода, к которому подключен вывод DT датчика HX711
#define SCK 22 // Указываем номер вывода, к которому подключен вывод SCK датчика HX711
float weight_of_standard = 350; // Указываем эталонный вес
float units = 0.035274; // Указываем коэффициент для перевода из унций в граммы
float calibration_factor = 0; // Создаём переменную для значения калибровочного коэффициента
void setup()
{
Serial.begin(115200); // Инициируем работу с последовательным портом на скорости 115200 бод
scale.begin(DT, SCK); // Инициируем работу с платой HX711
scale.set_scale(); // Не калибруем полученные значения
scale.tare(); // Обнуляем вес на весах (тарируем)
Serial.println("You have 10 seconds to set your known load"); // Выводим в монитор порта текст
delay(10000); // Ждём 10 секунд
Serial.print("calibration factor: "); // Выводим текст в монитор последовательного порта
calibration_factor = scale.get_units(10) / (weight_of_standard / units); // Считываем значение с тензодатчика
Serial.println(calibration_factor); // Выводим в монитор порта значение корректирующего коэффициента
}
void loop() {}
Обратим внимание, что по умолчанию функция get_units() из библиотеки RobTillaart/HX711 производит измерения в унциях, и для перевода полученных значений в граммы следует использовать коэффициент преобразования 0,035274.
Чтобы произвести калибровку, необходимо выполнить следующие шаги:
1) оставить пустой платформу для взвешивания грузов;
2) подать питание на отладочную плату;
3) система определяет напряжение смещения на ненагруженном сенсоре, обнуляя показания (тарирование);
4) далее у Вас есть 10 секунд (как только появится соответствующее сообщение в мониторе порта), чтобы поставить на платформу груз с заранее известной массой (например, эталонная гиря на 200 грамм или полный 200-граммовый пластиковый стаканчик с водой);
5) по истечению 10 секунд система измерит эталонный груз и произведёт расчёт калибровочного коэффициента, выведя его значение в монитор порта. Это значение нужно зафиксировать.
Измерение веса
Определив калибровочный коэффициент, можно прошить микроконтроллер основным кодом, который представлен ниже. В нем нужно указать коэффициент, который Вы получили при калибровке:
#include "HX711.h" // Библиотека для работы с АЦП HX711
#include <TFT_eSPI.h> // Библиотека для работы с TFT-дисплеем ST7735S
// Создание объектов
HX711 scale; // Объект для работы с тензодатчиком
TFT_eSPI tft = TFT_eSPI(); // Объект для работы с TFT-дисплеем
// Определение пинов подключения
#define DT_PIN 21 // Пин DATA (DT) HX711
#define SCK_PIN 22 // Пин CLOCK (SCK) HX711
#define BUTTON_PIN 0 // Пин кнопки обнуления (GPIO0 - обычно кнопка BOOT на ESP32)
// Калибровочные параметры
float calibration_factor = -14.60; // Калибровочный коэффициент (подбирается экспериментально)
float units; // Переменная для измерений в граммах
float ounces; // Переменная для измерений в унциях
// Функция обнуления весов (тарирование)
void tareScale()
{
tft.fillScreen(TFT_BLACK); // Очистка экрана
tft.setTextColor(TFT_GREEN); // Зеленый цвет для лучшей читаемости
tft.setTextSize(1);
tft.setCursor(10, 10);
tft.println("Taring..."); // Сообщение о процессе тарирования
scale.tare(); // Сброс текущего веса в 0
delay(500); // Задержка для стабилизации
tft.fillScreen(TFT_BLACK); // Очистка экрана
tft.setTextColor(TFT_GREEN); // Зеленый цвет для лучшей читаемости
tft.setTextSize(1);
tft.setCursor(10, 10);
tft.println("Tared!"); // Сообщение о процессе тарирования
delay(1000); // Пауза перед возвратом к измерениям
}
void setup()
{
Serial.begin(115200); // Инициализация последовательного порта для отладки
// Инициализация пина кнопки
pinMode(BUTTON_PIN, INPUT_PULLUP); // Подтяжка к питанию (кнопка замыкает на GND)
// Инициализация TFT-дисплея
tft.init(); // Инициализация дисплея
tft.setRotation(3); // Установка ориентации (3 = 180 градусов)
tft.fillScreen(TFT_BLACK); // Очистка экрана
tft.setTextColor(TFT_GREEN); // Зеленый цвет для лучшей читаемости
tft.setTextSize(1);
tft.setCursor(10, 10);
tft.println("Init..."); // Сообщение о инициализации
// Инициализация весов
scale.begin(DT_PIN, SCK_PIN); // Инициализация HX711 с указанием пинов
scale.set_scale(); // Установка масштаба (без коэффициента)
scale.tare(); // Первоначальное обнуление веса
scale.set_scale(calibration_factor); // Установка калибровочного коэффициента
tft.fillScreen(TFT_BLACK); // Очистка экрана
tft.setTextColor(TFT_GREEN); // Зеленый цвет для лучшей читаемости
tft.setTextSize(1);
tft.setCursor(10, 10);
tft.println("Ready!"); // Сообщение о инициализации
delay(500); // Короткая пауза
}
void loop()
{
// Проверка нажатия кнопки для обнуления
bool reading = digitalRead(BUTTON_PIN); // Чтение текущего состояния кнопки
if (reading == LOW)
{
delay(20);
if (reading == LOW)
{
tareScale(); // Вызов функции обнуления весов
}
}
// Измерение веса с усреднением
units = 0; // Обнуление переменной для накопления значений
for (int i = 0; i < 3; i++) // Цикл из 3 итераций
{
units += scale.get_units(5); // Каждый вызов функции возвращает среднее значение из 5 измерений
}
units = units / 3; // Усреднение значений
// Конвертация в граммы (1 унция = 28.3495 грамм)
ounces = units * 0.035274; // Более точный коэффициент преобразования
// Вывод в Serial Monitor для отладки
Serial.print("Weight: ");
Serial.print(ounces, 2); // Вывод с двумя знаками после запятой
Serial.println(" grams");
// Отображение на TFT-дисплее
tft.fillScreen(TFT_BLACK); // Очистка экрана
tft.setTextColor(TFT_GREEN); // Зеленый цвет для лучшей читаемости
tft.setTextSize(1);
tft.setCursor(10, 10);
tft.println("Weight (grams)");
tft.setTextColor(TFT_YELLOW); // Желтый цвет для значения
tft.setTextSize(3); // Увеличенный размер для значения
tft.setCursor(20, 40);
tft.print(ounces, 2); // Вывод с одним знаком после запятой
}
Для увеличения точности взвешивания можно увеличить количество измерений в функции scale.get_units(), а также увеличивая число циклов для усреднения. Но стоит учитывать, что вместе с точностью увеличится время опроса АЦП, то есть будет ощутимая задержка при обновлении показаний.
В код добавлен функционал производить обнуление показаний по нажатию на встроенную на отладочную плату кнопку (GPIO_0):

Для проверки работы весов используем эталонные гири с массой 200 грамм и 2 килограмма:


Как видим, построенная система производит взвешивание с вполне приемлемой точностью.
Заключение
В этой статье мы познакомились и подробно рассмотрели устройство и принцип работы балочных (консольных) тензометрических сенсоров.
Используя специализированную микросхему аналого-цифрового преобразователя HX711 совместно с тензодатчиками, достаточно просто можно построить качественную систему измерения веса с приемлемой точностью на базе микроконтроллера.
Представленный вариант макета системы демонстрирует хорошую точность и стабильность измерений, что подтверждается проверкой с эталонными грузами.
