Сообщество - Arduino & Pi

Arduino & Pi

1 493 поста 20 825 подписчиков

Популярные теги в сообществе:

40

Двухканальный цифровой вольтметр с графиком и шкалой на Arduino

🧾 Описание проекта

Этот проект представляет собой двухканальный цифровой вольтметр на базе Arduino, предназначенный для одновременного измерения входного и выходного напряжения, а также отображения максимального зафиксированного значения и реального графика изменения напряжения во времени.

Вольтметр отображает:

🟢 Входное напряжение (V In)

🔵 Выходное напряжение (V Out)

🔺 Максимальное выходное напряжение (V Max)

📉 График изменения выходного напряжения

📊 Вертикальную шкалу напряжения справа

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

🔧 Используемые компоненты

⚙️ Схема подключения

🔌 Подключение компонентов

🖥️ OLED-дисплей:

GND → GND

VCC → 5V

SCL → A5

SDA → A4

🎛️ Измерение напряжений:

Arduino измеряет напряжения через аналоговые входы A0 и A1. Но напрямую подавать на них более 5 В опасно. Поэтому используются резистивные делители напряжения.

📥 Делитель для входного напряжения (V In → A0):

Верхний резистор: 40 кОм

Нижний резистор: 10 кОм

Входной сигнал подаётся на верхний резистор

Средняя точка подключается к A0

Позволяет измерять до 25 В

📤 Делитель для выходного напряжения (V Out → A1):

Верхний резистор: 40 кОм

Нижний резистор: 10 кОм

Средняя точка подключается к A1

Такой делитель даёт коэффициент ≈ 1/5, что позволяет измерять до 25 В

⚠️ Подбирайте резисторы с учётом нужного диапазона. Программа изначально рассчитана на вход 0–5 В, поэтому при использовании делителей нужно изменить формулу расчёта напряжения.

⚙️ Как работает программа

Программа построена на основе двух объектов класса VoltMeter, каждый из которых отвечает за измерение напряжения по одному из входов.

А также один экземпляр класса Oscilloscope (осциллограф)

📦 Смотри раздел "Скетч Arduino"

Основные этапы работы:

Измерение напряжений:

Выполняется analogRead() на пинах A0 и A1.

Полученные значения преобразуются в вольты: voltage = raw * (5.0 / 1023.0);

При необходимости можно умножать результат на коэффициент делителя, например voltage *= 2.0;

Отображение данных:

Все показания (V In, V Out, V Max) отображаются в верхней части дисплея крупным текстом.

Используется шрифт TextSize(1) для чёткости и экономии места.

Фиксация максимума:

В каждом измерении программа сравнивает текущее значение с предыдущим максимумом.

При нажатии на кнопку (подключенную к D2) максимум сбрасывается.

График напряжения:

Отдельный класс Oscilloscope сохраняет последние измерения в буфере.

В нижней части дисплея рисуется линия, отображающая изменение напряжения во времени.

График занимает 110 пикселей по горизонтали и не наезжает на шкалу.

Вертикальная шкала справа:

Сегментная шкала (10 делений) показывает текущий уровень выходного напряжения.

Обновляется при каждом цикле измерения.

🧠 Дисплей

Размещение основных блоков отображения на экране OLED дисплея

Отображение на дисплее

Программа строит интерфейс в несколько этапов:

Верхняя часть дисплея — отображает входное и максимальные значения напряжения

Средняя часть — напряжение на выходе блока питания.

Нижняя часть — график напряжения во времени, построенный с использованием массива graphBuffer[], в котором хранятся последние 128 измерений. Этот массив сдвигается каждый раз и отображается как ломаная линия, повторяя форму изменения напряжения.

Правая часть — визуальный уровень напряжения в виде сегментной шкалы, где каждый сегмент активен в зависимости от уровня сигнала.

Такой подход позволяет использовать OLED-дисплей максимально эффективно: информативно и красиво.

📜 Скетч Arduino

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const int inputPin = A0; // Входное напряжение
const int outputPin = A1; // Выходное напряжение
const int resetButtonPin = 2; // Кнопка сброса максимума

#define GRAPH_HEIGHT 20
#define GRAPH_WIDTH 110 // Оставляем место справа под шкалу
uint8_t graphBuffer[GRAPH_WIDTH];

// Класс вольтметра
class VoltMeter {
private:
int pin;
float voltage;
float maxVoltage;

public:
VoltMeter(int analogInputPin) { // Кнструктор класса
pin = analogInputPin;
voltage = 0.0;
maxVoltage = 0.0;
}

void measure() { // Метод -измерение
int raw = analogRead(pin);
voltage = raw * (5.0 / 1023.0);
if (voltage > maxVoltage) {
maxVoltage = voltage;
}
}

void resetMax() { // Метод - сброс максимального значения
maxVoltage = voltage;
}

float getVoltage() { // Метод - получить измеренное напряжение
return voltage;
}

float getMax() { // Метод - получить максимальное напряжение
return maxVoltage;
}
};

// Класс осциллограф
class Oscilloscope {

public:
Oscilloscope() { // Кнструктор класса
// pin = analogInputPin;
}


void updateGraph(float voltage) {
for (int i = 0; i < GRAPH_WIDTH - 1; i++) {
graphBuffer[i] = graphBuffer[i + 1];
}
uint8_t newY = map(voltage * 100, 0, 500, 0, GRAPH_HEIGHT);
graphBuffer[GRAPH_WIDTH - 1] = newY;
}

void drawGraph() {
int baseY = SCREEN_HEIGHT - 1;
for (int x = 0; x < GRAPH_WIDTH - 1; x++) {
display.drawLine(x, baseY - graphBuffer[x], x + 1, baseY - graphBuffer[x + 1], SSD1306_WHITE);
}
}

void drawScale(float value) {
const int segments = 10;
const int startX = SCREEN_WIDTH - 10; // Правая сторона экрана
const int startY = 58;
const int segWidth = 8;
const int segHeight = 4;
const int gap = 2;

int activeSegments = map(value * 100, 0, 500, 0, segments);

for (int i = 0; i < segments; i++) {
int y = startY - i * (segHeight + gap);
if (i < activeSegments) {
display.fillRect(startX, y, segWidth, segHeight, SSD1306_WHITE);
} else {
display.drawRect(startX, y, segWidth, segHeight, SSD1306_WHITE);
}
}
}
};

VoltMeter vinMeter(inputPin); //Экземпляр класса вольтметр V In
VoltMeter voutMeter(outputPin); // Экземпляр класса вольтметр V Out
Oscilloscope oscill; //Экземпляр класса осциллограф

void setup() {
pinMode(resetButtonPin, INPUT_PULLUP);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 28);
display.println("Digital Voltmeter");
display.display();
delay(1500);
}

void loop() {
vinMeter.measure();
voutMeter.measure();

if (digitalRead(resetButtonPin) == LOW) {
vinMeter.resetMax();
voutMeter.resetMax();
delay(300);
}

float vin = vinMeter.getVoltage();
float vout = voutMeter.getVoltage();
float vmax = voutMeter.getMax();

oscill.updateGraph(vout);
display.clearDisplay();

display.setTextSize(1);
display.setCursor(0, 0);
display.print("V In: ");
display.print(vin, 2);
display.println(" V");

display.setCursor(0, 10);
display.print("V Max: ");
display.print(vmax, 2);
display.println(" V");

display.setCursor(0, 20);
display.print("V Out: ");
display.print(vout, 2);
display.println(" V");

oscill.drawGraph();
oscill.drawScale(vout);

display.display();
delay(200);
}

🧠 Советы и доработки

✅ Добавить коэффициент делителя прямо в класс VoltMeter, чтобы учесть масштабирование.

💾 Сохранять максимум в EEPROM, чтобы он не сбрасывался при перезагрузке.

🧲 Добавить третью строку: ток или мощность, если есть токовый шунт.

📈 Изменить масштаб графика для отображения высокого напряжения.

⚡ Применение

Настройка и тестирование лабораторных блоков питания.

Измерение и контроль напряжения в проектах Arduino.

Демонстрация работы стабилизаторов напряжения.

Учебные и демонстрационные стенды.

Показать полностью 3 1
14

Смонтировал лидар на робота, получил какие-то данные с него

Переделал схему питания, чтобы лидар можно было включать отдельно, по своей линии питания. У него потребление ~400мА, больше, чем вся остальная логика, включая Orange PI.

Собрал, включил. На python написал простейший скрптец, чтобы увидеть данные, которые он шлёт. Увидел ))

Следующий этап - подключение лидара к ROS2-ноде и визуализировать данные на RViz.

Больше информации в ТГ: https://t.me/robostroy

И как обычно, дублирую на других площадках:

RuTube: https://rutube.ru/video/ca1bca8be0d3b831236b22a71f80fdfa/

VK: https://vk.com/video-226966878_456239039

Показать полностью
17

Тестирую лидар для робота

Лидар с Алиэкспресса, от робота-пылесоса. Будет основой навигационной системы будущего робота. Целью теста было припаять нужные провода, проверить мотор и логику перед монтажём на платформу.

Подробно процесс стройки освещаю здесь: https://t.me/robostroy

и здесь: https://www.youtube.com/@seko2k19

Подписывайтесь, должно быть интересно!

Показать полностью
18

Строю робота на круглой платформе

Задумал построить нового робота на большой круглой платформе. Пока реализована сама платформа на двух мотор-колёсах, Orange PI Zero 2W, двух Arduino. До этого был опыт построения на базе черырёхколёсной машинки (мини-ровера), но там очень ограничено пространство.

В планах: лидар, камера+машинное зрение, сопряжение с LLM на большом компе.

Процесс стройки буду освещать здесь: https://t.me/robostroy

и здесь: https://www.youtube.com/@seko2k19

Подписывайтесь, должно быть интересно!

Показать полностью
41

Управление реле по UDP: Беспроводное решение с ESP8266, ESP32 и Easy HMI

Вы уже, наверное, в курсе, что Easy HMI получил поддержку беспроводной связи по UDP. Если нет, то ознакомьтесь с новыми возможностями тут. А так как есть беспроводной интерфейс, неплохо было бы сделать удаленное управление реле. Что, в свою очередь, позволит управлять светом, вытяжкой, вентилятором, чайником, кофемашиной, обогревателем и другими устройствами и приборами. Для реализации данной идеи можно использовать готовые модули на базе ESP32 и/или ESP8266. Я уже рассказывал про модуль ESP12F Relay X4 (LC-Relay-ESP12-4R-MV – по даташиту). Сегодня напишем код для управления данным модулем и также посмотрим, как можно управлять по UDP 2, 3, 5, 10 и даже 12 группами реле с одного сенсорного дисплея. Думаете, это невозможно реализовать? Давайте разберемся!

Код для модуля ESP12F Relay X4 (подойдет также для ESP8266, ESP32)

Управление 8–16 реле с сенсорного дисплея в Easy HMI и Arduino, ESP32.

Поддержка UDP в новой Easy HMI 0.1.2.

Показать полностью
21

Действительно умная ферма. Часть 4

И так, настало время для последней перед паузой в какое то время между постами, частью моего рассказа. Расскажу немного про внешний вид, покажу систему в работе, затрону планы на будущее и раскрою некоторые будущие наработки и идеи, ну а так же опыт пользования)

А пока, можете посмотреть видео, в котором я добавил некоторые поясняющие субтитры. Автор не блогер, а только учится и весьма стеснителен в вопросе съемок, так что пока только субтитры, за что прошу простить)

Внешний вид, дизайн, интерфейсы взаимодействия c пользователем.

Внешний вид, я описывал в прошлых статьях, но никак не затронул сенсорный экран который в моем случае резистивный мультитач от Nextion, линейки Intelligence. Оверкилл конечно для фермы, но пока больше мне он никуда не нужен.

Интерфейс собственно там максимально простой, это показания с датчиков и управление реле. Страница системы с кнопкой перезагрузки и статусами подключений к интернету\роутеру и IP адрес веб морды. Мне нужен был базовый интерфейс, поэтому в нём пока нет ключевых функций таких как регуляция PH/EC, температуры, таймеров и так далее. Это совсем не основная задача была и я сейчас в процессе рисования нового интерфейса, который бы удволетворял всем требованиям.

Я использую Lunacy для проектирования интерфейсов. Скриншоты чисто рабочие, тк я в процессе рисования и изучения данной сферы деятельности.

Ничего замысловатого тоже нет. Мне предстоит продумать систему добавления и редактирования конкретных таймеров на дисплее, посадок и регуляции PH/EC. Последнее кстати весьма не сложно как я думаю с точки зрения UX.

Про второй интерфейс взаимодействия, я уже так же рассказывал в прошлых статьях, это WEB интерфейс и MQTT / Apple Home. Там тоже много ньюансов и проблем, но все в процессе, как только я закончу полноценный новый интерфейс, обязательно поделюсь.

Планы на будущее

А вот сейчас самое интересное. В данный момент, я разрабатываю полностью свою плату для умной фермы, что бы не было вот такого:

Лапшичная с дорогими раменами на проводе

Лапшичная с дорогими раменами на проводе

И выглядит это пока вот так:

Новая плата управления фермой

Новая плата управления фермой

На ней я разместил 3 независимых блока питания, 3.3\5 и 12 вольт для питания датчиков, насосов и тд. Но это скорее всего не очень оптимизировано, тк мне думается можно сделать 2 блока, 3.3 вольта и 24 вольта, и через DC-DC на плате уже сформировать нужные мне напряжения для питания всего что необходимо, я в первый раз познаю исскуство проектирования плат, поэтому все может быть тяп ляп, но я в процессе)
На самой плате, уже размещен RTC модуль, коннекторы для экрана, ph/ec сенсоров с необходимыми делителями напряжения, разведена сеть 220V с реле. Возможно стоит предусмотреть возможность перекоммутации напряжений на реле, с 220V на любые другие напряжения которые мне необходимы. Пока не определился. Поэтому заказать плату мне довольно сложно, потому что проект в процессе и пока мне будут ехать платы версии 5.0, я обязательно что то модернизирую и сделаю и 5.1 и 5.2 а то и 6.0...

Новый дизайн, доп функции, расширение.

И вот сегодня, я наконец увидел в голове, как же я вижу уже финальный вид устройство. Как говорят в судостроении, четвертое преведение.. Тоесть по сути переход от эскизного проекта к техническому проекту.

Блокинг концепт

Блокинг концепт

Я понял, что в виде конечного устройства, бак, контейнер, блок с электроникой, все это с кучей кабелей и трубочек - это жуткий геморой для финального пользователя. Поэтому, новый дизайн имеет в себе одновременно и бак и баки для корректоров PH и для удобрений EC, никаких видимых трубочек и кабелей, самое главное, возможность использования различных систем гидропоники. Хотите DWC? пожалуйста. Хотите проточную? Тоже пожалуйста.Частичное затопление? Вас понял, сделано. Капельный полив?Это пока то, что лежит на поверхности и я точно смог бы это реализовать, но конечно впереди много времени проектирования не в блендере. Ну и конечно, аэропоника тут это основной метод, который я предпочитаю.

Дизайн я вижу как у техники SMEG или что то оттуда. Хочется навернуть стиля. Но прежде чем все это делать, я хочу отточить все технологии. Пока идеи и планы такие и я действительно не хочу забрасывать этот проект, так как мне самому очень интересно в этом разбираться.

Всё это, я хочу сделать уже в версиях 5.0 - 6.0 и там же где то, попробовать сунуться в OpenSource сообщество (но с простыми решенями, что бы каждый мог повторить)

Стоит ли писать и рассказывать уже о дальнейшем проектировании? Читали ли бы вы такие посты? С радостью отвечу на ваши вопросы или предложения, выслушаю критику, так как она наверняка должна быть, в этом деле я затрагиваю множество областей в многих из которых я ну совсем профан и могу ошибаться. Вдруг среди читателей есть прошаренные)

Показать полностью 6
50

Действительно умная ферма. Часть 3.2. TDS/EC сенсор. Питание растений

Очередной пост, про мою ферму, да про сенсоры важные. Начну издалека и постараюсь простыми словами.


Зачем вообще мерить EC\TDS и температуру в питательном растворе?

Эти параметры показывают, насколько концентрирован наш раствор. А значит — хватает ли питания растениям или им через чур много и это не усвоится. Почему вообще на гидропонике все быстро растет? Потому что растениям не надо тратить силы и энергию на то, что бы искать все больше и больше ресурсов своей корневой системой и впитывать их из земли, а ещё кислород, его часто не хватает, именно поэтому часто советуют делать всякие подмесы в грунт для его "рыхлости", а в гидропонике мы выдаем все эти ресурсы сразу на блюдечке с голубой каемочкой и вот тут то главное правильно сервировать блюдо!

Нейроарт как вообще в гидропонике то все устроено.

Нейроарт как вообще в гидропонике то все устроено.


Параметр EC.

EC = Electrical Conductivity (Электрическая проводимость)

→ Показывает, насколько хорошо раствор проводит ток. Измеряется в миллисименсах на сантиметр (мСм/см).
Чем больше солей — тем выше проводимость.

Например:

  • Чистая вода: 0.0–0.05 мСм/см

  • Рассада салатов: 0.8–1.2 мСм/см

  • Клубника: 1.6–2.2 мСм/см

  • Помидоры: 2.0–3.5 мСм/см

Более того, на разных стадиях роста, растениям как правило нужна ещё и разная концентрация этих ваших удобрений. Вообщем то как и с любым организмом, в разные этапы жизни - жрут по разному, поэтому этот параметр важен и нужен.


EC - это стандарт индустрии, когда вы видите EC 1.0 или EC 1000, важно обратить на какое расстояние проводится измерение. Измеряют и в миллиметрах и в сантиметрах и в метрах. Это кому как удобнее и простыми арифметическими действиями переводится в нужное вам значение.


Параметр TDS.

TDS = Total Dissolved Solids
→ Количество растворённых солей в ppm (мг/л). Это лишь приблизительный расчёт из EC:

TDS ≈ EC × коэффициент

В гидропонике чаще всего:

  • 500 шкала — используется чаще всего (NaCl - шкала) в основном в США, Европе, Австралии, самая популярная.

  • 700 шкала — другая, менее распространённая (KCl - шкала) в основном в Азиатских регионах, реже в Европе.

В основном используется NaCl шкала, но это нас и приводит к выводу, что в гидропонике эти шкалы нам в принципе не нужны, что то куда то переводить ещё, неудобно. Поэтому все используют одну стандартизированную единицу - EC.

Важно понимать, что оба параметра не показывают чего то конкретного. Они показывают сумму всех солей и удобрений в воде! А тоесть по этому значению мы не можем узнать, что конкретно в воде и в каком количестве. Это гораздо более сложная процедура.


Калибровка

Чем калибруются EC или TDS метры? Да все теми же буферными растворами. Для TDS это как правило 800 ppm, для EC метров - 1413 мк/см и другие (смотри на пределы измерений EC метра). Продаются так же как и для PH метров в порошках или готовом виде.


Как влияет температура?

Температура в этом аспекте, крайне важна. Хотя про неё много кто и забывает. Нет, конечно она не губительна в разумных пределах, но весьма сильно влияет на процесс выращивания растений. Мы не говорим про отрицательные температуры или около нулевые, а так же не берем в расчет температуры в пустыне. Среднестатистические 15-30 градусов для примера нам хватит.

Температура раствора — важнейший фактор в гидропонике. Если раствор слишком холодный или слишком тёплый — корни начинают "забастовку": они просто перестают нормально усваивать питательные вещества. Это как если бы человек ел лёд вместо тёплого супа — вроде есть, но толку мало.

Оптимальная температура для корней большинства растений — 18–22 °C. В этом диапазоне:

  • Кислород хорошо растворён в воде

  • Клетки корней активны

  • Удобрения усваиваются эффективно

Если температура падает ниже 16 °C — корни замедляются, питание поступает плохо. А при 25–28 °C — начинаются проблемы: раствор теряет кислород, возможен корневой гниль, а соли могут вызывать ожоги. И вот тут есть главное преимущество как по мне аэропоники. Раствор разбиваясь на воздушно питательную смесь, вполне себе охлаждает и корни и при этом растения прекрасно усваивают кислород, поэтому фактор насыщения кислородом самого раствора мы можем упустить в моём случае.

Что делать при перегреве раствора? два способа. Снижать концентрацию или понижать его температуру чиллерами или другими способами. Или просто разбавить. Самый простой способ конечно разбавить водой.


Моя система

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

Что стоит в моей системе?

В моей системе в данный момент 2 сенсора TDS. Пока не отключал старый, поэтому расскажу и про него.

Вот такой TDS метр у меня стоит, но более не используется для измерений EC(на это значение опирается вся система) а просто выводит дублирующее показание в PPM, новому сенсору.

Вот такой TDS метр у меня стоит, но более не используется для измерений EC(на это значение опирается вся система) а просто выводит дублирующее показание в PPM, новому сенсору.

С ним всё ок и его даже реально откалибровать. Только один ньюанс. Для гидропоники он не подходит чисто технически. У него потолок измерений 1000 PPM (около 1.0 EC) и даже его он показывает с трудом. За то идеален в обратную сторону, там где надо мерить чистоту. Вот тут у него реально нет аналогов за его стоимость. Он конечно может и 5 EC вам показать, только это будут ненадежные данные, тк его невозможно откалибровать, свыше 1 EC у него уже нелинейная интерполяция, проще говоря он становится генератором рандомных чисел. В дальнейшем я его вытащу и сделаю из него прибор для умного проточного фильтра для питьевой воды. Что бы понимать когда менять кассеты и тд.
А поскольку он не подходил то я приобрел вот такой вот EC метр.

Оверкилл для этой системы. Но работает отлично.

Оверкилл для этой системы. Но работает отлично.

у него уже и питание "взрослое" (от 12 до 24 вольт) и калибровки все на борту имеются и измеряет он по правильному, EC а не PPM. PPM это в свою очередь производная от EC и считается программно. и даже крепление на DIN рейку на корпусе есть, подключать же надо строго через делитель напряжения к пину ESP, что впрочем тоже не сложно, подбирается он индивидуально под ваш контроллер.

Суть измерений ровна такая же как и в контроллерах PH. Мы считываем выдаваемое напряжение и приравниваем его к значениям EC. Подключается так же в любой аналоговый пин способный на АЦП.

Суть кода 1в1 с PH, только не нужна всякая калибровка, совсем сердитые усреднения и тд. Все сильно проще и ограничивается всего двумя функциями:

float readECVoltage_new() {

int newVal = analogRead(EC_PIN);

// Обновление кольцевого буфера

ecSum -= ecBuffer[ecIndex];

ecBuffer[ecIndex] = newVal;

ecSum += newVal;

ecIndex = (ecIndex + 1) % NUM_READ_EC; 

if (ecIndex == 0) ecFilled = true;

// Вычисление среднего значения как float

int validCount = ecFilled ? NUM_READ_EC : ecIndex;

if (validCount == 0) validCount = 1; // защита от деления на 0

float average = static_cast<float>(ecSum) / validCount;


// Перевод в напряжение

float voltage = (average / ADC_RESOLUTION) * ADC_VREF;

return voltage;

}


float readEC_new() {

float voltage = readECVoltage_new();

float realVoltage = voltage * DIVIDER_RATIO;

float ecValue = (realVoltage / MAX_SENSOR_VOLTAGE) * EC_RANGE;


// EMA фильтрация

if (filteredEC == 0.0f) filteredEC = ecValue;

filteredEC = EC_SMOOTHING * ecValue + (1.0f - EC_SMOOTHING) * filteredEC;


// Перевод в mS/cm и округление до 0.1

float ecMilli = filteredEC / 1000.0f;

ecMilli = roundf(ecMilli * 10.0f) / 10.0f;


logf(LOG_DEBUG, "[EC_SENSOR] EC Voltage: %.3f V (real %.3f V) | EC: %.1f mS/cm",

voltage, realVoltage, ecMilli);


return ecMilli;

}

eadECVoltage_new() — измерение напряжения:

  1. Считывает аналоговое значение с EC-датчика (analogRead) → от 0 до 4095

  2. Обновляет кольцевой буфер последних измерений для сглаживания

  3. Вычисляет среднее значение по буферу

  4. Переводит среднее значение в напряжение (вольты) по формуле:
    voltage = (среднее / ADC_RESOLUTION) × VREF

  5. Возвращает полученное напряжение — это ещё не EC, а просто "что пришло с датчика"

readEC_new() — шаги:

  1. Вызывает readECVoltage_new() → получает среднее напряжение

  2. Компенсирует делитель напряжения, чтобы получить реальное напряжение на датчике

  3. Переводит напряжение в значение EC по диапазону датчика

  4. Сглаживает значение EC с помощью EMA-фильтра (плавное обновление)

  5. Округляет EC до десятых (0.1) и переводит из μS в mS/cm

  6. Логирует результат (напряжение и EC) для отладки

  7. Возвращает EC (в мСм/см) — дальше это значение:

    • передаётся в WebSocket (SENSOR_UPDATE)

    • записывается в лог (tds_log.csv)

    • отображается в интерфейсе

Компенсация температуры для TDS метра.

В моем модуле, уже присутствует температурная компенсация,а в OEM китайском, такой функции нет, поэтому финальное значение надо компенсировать ещё и температурой.

TDS Компенсированный = TDS сырой/ (1 + α × (T - T₀))

формула выглядит вот так. И является довольно простой:

Где:

  • TDS сырой — необработанное (сырое) значение TDS

  • T — текущая температура раствора (в °C)

  • T₀ — опорная температура (обычно 25°C)

  • α — температурный коэффициент для солевого раствора (0.02 — то есть +2% на каждый градус)

Например:

  • Температура: 30°C

  • Сырой PPM = 1000 ppm

TDS Компенсированный = 1000 / (1 + 0.02 × (30 - 25))

= 1000 / (1 + 0.10)

= 1000 / 1.10

≈ 909 ppm

То есть фактически в растворе меньше солей, чем показывает прибор — из-за нагрева. Эта же формула подходит и к EC метрам без встроенной температурной компенсации.

Ну и соответственно, как вы понимаете уже, вместо текущей температуры, в ESP/Arduino и любых других системах, можно просто брать температуру с датчика DS18B20 например и подставлять напрямую в формулу и получать корректное значение EC/TDS.


В завершение. Естественно, вы можете вообще не парится, и заваривать раствор единожды с помощью ручного измерителя TDS\EC и будете правы. Это блажь и излишек. Но мне нравится такого рода автоматизации и упрощение своей жизни.

Спасибо за внимание!

Показать полностью 3
21

Управление 8–16 реле с сенсорного дисплея в Easy HMI и Arduino, ESP32

Ранее я уже создавал проекты по управлению реле с использованием сенсорных дисплеев DWIN и Nextion. Реализация этих проектов не представляет большой сложности. Для этого требуется отрисовывать графику, правильно её нарезать и предварительно изучить недружелюбную документацию, в случае DWIN. С помощью программы Easy HMI это можно сделать гораздо быстрее. Создать проект можно минут за 20–30.

Уроки Easy HMI.

Показать полностью
Отличная работа, все прочитано!