Сигнал на A0 я смотрел в плоттере, как в осциллографе, и первый час всё шло отлично — пока не понадобилось показать форму крупно: один игольчатый выброс, и вся рабочая кривая сложилась в нитку у нуля. Autoscale честно вместил всё, включая мусор, и полезное стало недоразумением. Второй подвох я нашёл позже: датчик дрожал сотни раз в секунду, а плоттер рисовал гладкие горбы — я печатал реже, чем менялся сигнал, и график дорисовывал недостающее прямыми линиями, как будто так и было.
Здесь плоттер разбирается как измерительный инструмент: сколько кадров в секунду вытянет порт при ваших бодах, как выбросы ломают масштаб и что с этим делать в скетче, как уместить три кривые в одном окне и где график перестаёт быть честным. Базовый формат — пары имя=значение, два ряда, пауза для осмотра — разобран в уроке про Serial Plotter; где в IDE 2 живут вкладки монитора и графика, показывал в уроке про монитор порта. Дальше — только то, что отличает осциллограф от красивой картинки.
Договоримся о словах сразу: настоящий осциллограф смотрит электричество напрямую, тысячи кадров в секунду и с шкалой вольт. Плоттер видит то, что скетч сам напечатал в порт, — и в этом его сила и потолок: вместо щупа — одна строка кода, вместо тысяч кадров — столько, сколько вытянет канал. По моему опыту девять диагностических задач раздела — тренды, шумы, пили, реакции на ручку — ложатся на плоттер целиком, и лишь редкий остаток требует настоящего прибора. Позиционирование важно: сравнение с осциллографом — про привычку смотреть форму, а не про замену железа.
Бюджет скорости: боды против кадров
Каждый байт сериала едет десятью битами — старт, восемь бит значения, стоп — поэтому 9600 бод означают 960 символов в секунду. Строка raw=512 с переводом строки весит восемь символов: потолок — около 120 кадров в секунду. Три ряда с подписями — уже около 20 символов на кадр, и потолок падает до 48. На 115200 бод те же строки тянут 1440 коротких кадров или 576 трёхрядных. АЦП при этом свободен: одиночное чтение занимает сотню микросекунд, о чём я считал биты в уроке про скорость АЦП, — узкое место всегда печать, не преобразователь.
Из арифметики два привычных решения. Первое: меньше символов в строке — короткие имена рядов, а для одиночной кривой голые числа без меток. Второе: печать по таймеру, раз в 20-40 миллисекунд по millis, а не в каждый проход loop: кадры уходят стабильно, период сигнала на графике не плывёт от лишнего текста, и глаз читает форму, а не дрожь темпа. Третье, про запас: если форма сигнала важнее подписей, поднимите скорость порта до 115200 — обе стороны кабеля должны назвать одну цифру, сверка из первого урока про монитор, — и запас кадров вырастет десятикратно.
Масштаб. Autoscale берёт минимум и максимум всего окна и растягивает их на экран: один выброс до 1023 — и рабочая кривая в сотню единиц ложится на дно, как в моей истории с крупным кадром. Лечение в скетче дешевле лечения глазами. Вариант первый: печатать зажатое значение — cap=constrain(raw,0,900): выброс останется на графике полкой у 900, а не иглой до потолка, и масштаб перестанет прыгать. Вариант второй — ряд-линейка: константа известного уровня рядом с сигналом, глаз калибруется по ней без шкалы. Вариант третий для рядов разного масштаба: большое делить на константу — значения 0-1023 и 0-255 живут в одном окне, если меньший ряд печатать с умножением на четыре или больший с делением на два; цена — мелочь на сжатом ряду, и про неё честно помните.
// Потенциометр на A0, кнопка на D2 к GND. Кадр раз в 40 мс по millis:// строка из 20 символов на 115200 бод уезжает за 1,7 мс, запас десятикратный. unsigned long t = 0;int filt = 512; void setup() { pinMode(2, INPUT_PULLUP); Serial.begin(115200);} void loop() { if (millis() - t >= 40) { t = millis(); int raw = analogRead(A0); if (digitalRead(2) == LOW) { raw = raw + 800; // выброс: autoscale сожмёт весь экран } if (raw > 1023) { raw = 1023; } int cap = constrain(raw, 0, 900); // обрезка: выброс виден полкой filt = (filt * 85 + raw * 15) / 100; // экспоненциальный фильтр Serial.print("raw="); Serial.print(raw); Serial.print(" cap="); Serial.print(cap); Serial.print(" filt="); Serial.println(filt); }}Второй ряд в скетче выше — фильтр, и он заслуживает отдельного абзаца. Формула filt = (filt * 85 + raw * 15) / 100 — экспоненциальное сглаживание: восемьдесят пять процентов старого значения и пятнадцать свежего. На графике два ряда рассказывают историю сразу: raw дёргается от ползунка, filt ползёт следом с запаздыванием в несколько кадров — при периоде печати 40 мс задержка на глаз около пятой секунды. Это не дефект, а цена сглаживания: чем сильнее давите шум, тем позже реакция. Правило подбора, к которому я пришёл на датчике наклона дверного замка: если ряд фильтра отстаёт от ручки заметно глазу — коэффициент свежего поднять с пятнадцати до двадцати пяти; если дрожь на фильтре всё ещё видна — наоборот, уменьшить. И помните: фильтр прячет и полезное — иглу выброса он превращает в горб, поэтому для ловли одиночных сбоев фильтрованный ряд не годится, смотрите сырой.
Несколько кривых и их прятки
Одна строка — один кадр: сколько пар имя=значение в кадре, столько рядов поедет на шаг. Практический потолок читаемости — три-четыре ряда, дальше цвета начинают спорить друг с другом, и глаз тратит время на расшифровку вместо наблюдения. Ряды разной природы лучше разводить по разным запускам: температура и её порог живут вместе отлично, добавьте сюда же состояние реле — и график превратится в флаговую лестницу, где кривые не читаются. Имена рядов держите короткими и постоянными от проекта к проекту: два символа и знак равенства — и рука уже не путает кадры между запусками. В свежих сборках IDE 2 у плоттера есть переключатели интерполяции и меток времени: интерполяция рисует прямые между кадрами, её выключение даёт ступеньки честных точек, а метки времени показывают, что кадры идут неравномерно, — полезно, когда печать в loop без таймера. Живой двухрядный пример — график температуры и порога реле в разделе про датчики.
| Симптом на графике | Кто виноват | Что крутить |
|---|---|---|
| Рабочая кривая легла ниткой вниз | один выброс и autoscale на всё окно | обрезка cap= или отдельный ряд для выбросов |
| Синус превратился в горбы | кадры реже периода сигнала: печать не успевает | короче строка, 115200 вместо 9600, таймер 20-40 мс |
| Один ряд спрятал другой | масштабы 0-1023 и 0-255 в одном окне | деление или умножение ряда на константу |
| Цветная каша из шести линий | рядов больше четырёх в одном кадре | разбить на два графика или печатать группами |
Границы честности. Плоттер — осциллограф на секунды и десятки секунд, не на микросекунды: фронты короче интервала печати он рисует ступеньками или пропускает целиком, показывая огибающую вместо формы. Для дребезга, задержек на единицы миллисекунд и фронтов нужен логический анализатор, а плоттер оставьте трендам, шумам, кривым заряда и пилам. Отдельный класс задач — подтверждение результата: вы настроили порог, гистерезис, коэффициент фильтра — и график показывает, что реальность согласна с расчётом, быстрее, чем столбик чисел в мониторе. В диагностике он силён в паре со ступенями из методики отладки: Serial-точки показали, где ветка ломается, — график показал, как именно она себя ведёт рядом с этим местом.
- 1. Скорость 9600 бод, строка raw=512 с переводом строки весит 8 символов. Каков потолок кадров в секунду?
- 2. Один выброс до 1023 на секунду — что покажет autoscale?
- 3. Как напечатать три ряда с подписями для плоттера?
- 4. Кривая выглядит сглаженными горбами вместо зубцов. Главная причина?
- 5. Сигнал меняется каждые 2 мс, печать идёт раз в 40 мс. Что покажет график?
- Бюджет кадров считается от бодов: 9600 — это 960 симв/с, строка из 8 символов — около 120 кадров/с, из 20 — около 48
- Печать по таймеру раз в 20-40 мс на millis: кадры равномерные, период сигнала на графике не плывёт
- Один выброс и autoscale укладывают кривую на дно: обрезка cap=, ряд-линейка или деление ряда на константу
- До трёх-четырёх рядов в кадре читаемо; интерполяция и метки времени в свежих сборках IDE 2 показывают честность точек
- Плоттер — осциллограф секундного масштаба: фронты и дребезг он рисует ступеньками, для быстрых явлений нужен логический анализатор
Частые вопросы по теме урока
- Скорость 9600 бод, строка raw=512 с переводом строки весит 8 символов. Каков потолок кадров в секунду?
- 9600 бод — это 960 символов в секунду, байт едет десятью битами. 960 делим на 8 символов на кадр — получаем около 120 кадров в секунду. около 120
- Один выброс до 1023 на секунду — что покажет autoscale?
- Autoscale растягивает минимум-максимум всего окна на экран: один игольчатый выброс — и полезная кривая ложится на дно. Лечится обрезкой значения в скетче. сожмёт рабочую кривую в нитку у нуля
- Как напечатать три ряда с подписями для плоттера?
- Один кадр — одна строка: пары имя=значение в ней дают подписанные ряды. Числа без имён тоже дадут три ряда, но позиционные — без названий. одна строка с парами имя=значение через пробел и println
- Кривая выглядит сглаженными горбами вместо зубцов. Главная причина?
- Плоттер соединяет кадры прямыми линиями. Редкая выборка превращает быстрый сигнал в горбы: сократите строку, поднимите боды и печатайте по таймеру. кадры приходят реже, чем меняется сигнал, — между точками рисуются прямые
- Сигнал меняется каждые 2 мс, печать идёт раз в 40 мс. Что покажет график?
- Кадры в двадцать раз реже изменений — плоттер рисует огибающую. Для формы таких сигналов нужен логический анализатор; плоттер оставьте трендам и медленным процессам. огибающую вместо формы: фронты пропадут