Я неделю собирал ночной лог кладовки: скетч печатал в монитор порта пары «24.10 / 45.00» раз в две секунды, за ночь набегало около семисот строк. Утром я листал эту простыню и не мог ответить на простой вопрос — когда включался обогреватель и на сколько прыгала температура. Цифры скроллятся быстрее, чем их успеваешь читать. Потом я ещё раз перелистал те же семьсот строк, чтобы найти, в котором часу закрыли форточку, и сдался на середине. График я построил позже, вручную перегнав столбцы в электронную таблицу, — и провал в три часа ночи был виден с первого взгляда.
Обидно то, что график был у меня под рукой всё время. Serial Plotter встроен в Arduino IDE начиная с версии 1.6.6, лежит в меню Инструменты и рисует всё, что скетч печатает в порт. Ни библиотек, ни кода рисования: тот же Serial.print, только каждое напечатанное число превращается в точку на графике, а строка — в кадр. Версия IDE роли не играет: и старая 1.8, и новая 2.x рисуют одинаково, различия разве что в кнопке масштаба.
В этом уроке договоримся, какой формат строк понимает плоттер, поймаем фантомный ряд, который он рисует из невинной стартовой строки, разберём спор двух рядов за общую шкалу и честную частоту точек DHT. База про сам инструмент — в уроке про Serial Plotter, а здесь всё применяется к датчику температуры и влажности.
Плоттер ест числа, а не текст
Правило у плоттера одно: строка из Serial — один кадр графика. Голое число вроде 23.50 ложится в первый ряд, два числа через пробел — в два безымянных ряда, а пара с меткой t=23.50 попадает в ряд с именем t. Метка — слово перед знаком равенства или двоеточия; плоттер собирает одноимённые точки в одну линию и подписывает её. Поэтому в чужом скетче я первым делом смотрю, чем заканчивается печать: точка без println — половина кадров склеилась.
Поэтому я печатаю парами в одну строку: Serial.print("t="), затем число, пробел, Serial.print("h="), число, и Serial.println в конце — одна строка «t=23.50 h=45.00» даёт один кадр с двумя точками. Пары на отдельных строках тоже встречаются, но однострочный вариант самый переносимый: он одинаково живёт и в старой IDE, и в новой, и в веб-симуляторе. Договорились — и дальше в этой книге все графики печатаются именно так.
Из этой же привычки вырастает двойная выгода: человек в мониторе читает метки и не путается, плоттер получает имена рядов. Одна печать обслуживает двух потребителей сразу — это то самое умение, которое мы завели ещё в первом скетче с парами t и h.
Два уточнения снизу, на уровне порта. Первое: кадр заканчивает println — без него числа приклеиваются к следующей порции, и плоттер вместо аккуратной пары получает слипшуюся строку без границ кадров. Второе: скорость порта роли не играет, плоттер ест строки и на 9600, и на 115200, а передача строки в 16 символов при 9600 бод занимает около 16 миллисекунд — на кадре раз в две секунды незаметно. И помните: монитор и плоттер сидят на одном порту, два окна одновременно не открыть.
#include "DHT.h" #define DHTPIN 2#define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); void setup() { Serial.begin(9600); dht.begin(); delay(1500); // прогрев сенсора до первого чтения} void loop() { float t = dht.readTemperature(); float h = dht.readHumidity(); Serial.print("t="); Serial.print(t); Serial.print(" h="); Serial.println(h); // println завершает кадр delay(2000); // DHT22 отвечает раз в две секунды}| Строка из Serial | Что нарисует плоттер |
|---|---|
| 23.50 | один безымянный ряд (подпись 1) |
| 23.50 45.00 | два безымянных ряда (1 и 2) |
| t=23.50 h=45.00 | два именованных ряда: t и h |
| start: опрос раз в 2 секунды | фантомный ряд из единственного числа 2 |
Два ряда — два масштаба
Первый совместный график t и h у меня выглядел как диагноз: кривая влажности волнами через весь экран, температура — плоская черта у самого дна. Шкала общая: влажность живёт в диапазоне 0–100, температура за сутки гуляет на один-два градуса — это один процент высоты полотна. Никакой поломки, чистая арифметика общих осей.
Числа для наглядности. За мои сутки в кладовке температура делала от 20,5 до 24,0 — три с половиной градуса, то есть три-четыре процента высоты экрана, если шкалу растянула влажность от 38 до 72 %. Автошкала плоттера тянется на самый широкий ряд — удобно и неудобно одновременно: влажность видна идеально, температура превращается в почти прямую у дна. Чем больше разница масштабов, тем честнее заранее решить, какой ряд сейчас главный.
Приёмы, в порядке моего предпочтения. Для комнаты я смотрю оба ряда как есть — сюжет обычно именно во влажности, а температура пусть лежит чертой, но видна. Когда важна температура — обогреватель, инкубатор, проверка обогрева сушки — печатаю масштабированный ряд t10 = t * 10 со значением вроде 235 и помню про множитель, либо временно убираю влажность из печати и смотрю чистый ряд. Третий путь — печатать дельту от точки старта, если интересует только ход процесса.
И про дрожь линии. Последние цифры у DHT22 плавают на ±0,1–0,2 °C, у DHT11 шаг целый градус и половина градуса влажности — это паспортная погрешность, а не сломанный датчик. В симуляторе она воспроизведена честно: линия дрожит даже при неподвижных ползунках. Если линия прыгает сильнее, чем на полградуса у DHT22, — ищите провод, а не читайте график. Мой рекорд — линия, дрожавшая на полтора градуса: виноват оказался провод данных, прижатый ножкой макетки, а не погода.
Частота точек упирается в сенсор, а не в плоттер. DHT11 отдаёт данные раз в секунду, DHT22 — раз в две, и ускорить это нечем: при более частом опросе приходят nan или повторы. Плоттер рисует точку за точкой, его развёртка — секунды, не миллисекунды; для быстрых процессов вроде прогрева паяльника DHT не годится в принципе, там нужны термисторы и термопары.
Кстати, о ёмкости канала. Одна пара t= и h= при 9600 бод занимает около 20 миллисекунд эфира раз в две секунды — порт простаивает 99 % времени. Поэтому не бойтесь печатать в тот же порт отладочные строки без цифр: кадры они не тронут, а журнал сделают человечнее. Бояться стоит только цифр без меток — их плоттер примет за данные, о чём уже был note выше.
Чтение графика — отдельное умение, и оно проще, чем кажется. Ровная линия — процесс стабильный, для кладовки это успех. Пила с периодом в минуты — где-то работает терморегулятор с узким гистерезисом, обычно обогреватель с собственным термостатом. Ступенька — событие: открыли дверь, включили прибор, зашёл человек с кружкой. Через неделю с плоттером вы начнёте читать комнату как открытую книгу, и возвращаться к простыням цифр уже не захочется.
Плоттер хранит скользящее окно и историю не хранит вовсе: закрыли окно — потеряли ночь. Когда встанет задача вести лог сутками, печатайте те же пары в файл — как в уроке про таблицу данных, или пишите на SD-карту из урока про логирование: формат строк один и тот же, меняется только потребитель.
- 1. Что для Serial Plotter означает одна строка из Serial?
- 2. Плоттер получил строку «t=23.50». Что он нарисует?
- 3. Скетч печатает «start: опрос раз в 2 секунды» в начале работы. Что окажется на графике?
- 4. Почему на общем графике температура выглядит плоской чертой у дна?
- 5. С какой честной частотой плоттер получит точки от DHT11?
- Serial Plotter встроен в IDE с версии 1.6.6: рисует всё, что скетч печатает в порт, без библиотек и кода графики.
- Одна строка — один кадр; метки t=23.50 дают именованные ряды, голые числа — безымянные.
- Печатайте пары в одну строку и не сыпьте в порт служебных строк с цифрами — плоттер заведёт фантомный ряд.
- Общая шкала прижимает узкий диапазон ко дну: множитель, дельта или одиночный ряд на время эксперимента.
- DHT11 — точка в секунду, DHT22 — раз в две; историю хранит не плоттер, а файл или SD-карта.
График превращает датчик в прибор, на котором видно процесс, а не последнее число. Дальше два пути: связать пороги с индикацией комфорта светодиодами, чтобы отклонение было видно и без экрана, или копнуть функции чтения глубже — в разборе кода чтения разобраны Фаренгейт, округление и кэш библиотеки, из-за которого два вызова подряд возвращают одно число. Если ваша линия на графике живёт не в мониторе, а на SD-карте, урок про таблицу данных поможет разложить столбцы.
И маленький ритуал напоследок: оставьте плоттер открытым на вечер с этим же скетчем. Один раз увидев, как комната дышит на живой линии — провал, когда открыли дверь, горка, когда зашёл человек с чайником, — вы больше не спутаете график с украшением. Прибор начинает говорить с вами на одном языке, и это стоит тех пятнадцати минут, что вы тут провели.
Частые вопросы по теме урока
- Что для Serial Plotter означает одна строка из Serial?
- Плоттер разбирает строку на числа и рисует кадр: одно число — одна точка, пара чисел — две точки одного кадра. Границу кадра задаёт перевод строки — println. Один кадр графика со всеми числами строки
- Плоттер получил строку «t=23.50». Что он нарисует?
- Слово перед знаком равенства становится именем ряда. Одноимённые точки соединяются в подписанную линию. Точку в ряду с именем t
- Скетч печатает «start: опрос раз в 2 секунды» в начале работы. Что окажется на графике?
- Плоттер вытащит из строки число 2 и заведёт лишний ряд. Служебные строки печатайте без цифр: start: ok. Точно так же ломает график подпись с датой вроде 12.03. Фантомный ряд с точкой 2
- Почему на общем графике температура выглядит плоской чертой у дна?
- Влажность занимает 0–100, температура гуляет на пару градусов — один процент высоты полотна. Лечат множителем, дельтой или одиночным рядом. Шкала общая, а диапазон температуры на порядок уже диапазона влажности
- С какой честной частотой плоттер получит точки от DHT11?
- DHT11 пересчитывает показания раз в секунду. Более частый опрос даёт nan или повторы, плотнее график не станет — частоту задаёт сенсор. Раз в секунду