Контроллер нижнего подогревателя печатных плат на PY32F002A

В прошлой статье я описывал свои попытки разобраться с почти самым дешевым из достойных или почти самым достойным из дешевых — микроконтроллером PY32F002A за цену около 10 центов на Али.
Комментарии были самые разные — зачем все это, когда 21 век на дворе? Зачем тратить время на ерунду, мое время такое дорогое? Ага, такое дорогое, что не ем и в туалет не хожу, чтобы его напрасно не тратить.
Тем не менее я продолжаю тему. И идя на встречу пожеланиям трудящихся — все выложено на GitHub. Я не берусь прогнозировать, когда к нему закроют доступ, но пусть все будет, как вы хотели.
Будем делать контроллер нагревателя нижнего подогрева на базе PTC нагревателей, которых на Али пруд пруди. Но они рассчитаны на определенную температуру, которую держат весьма нестабильно.
Не то, чтобы мне нужен был подогреватель — их у меня штук 5 или больше самых разных.

Но — вы увидите много примеров, как программировать разные периферийные блоки этого микроконтроллера. Да, порог вхождения повыше, чем у ардуино — но если пенсионер смог сделать систему программирования этого контроллера, то молодым и здоровым это тем более по плечу.
SDK для Keil uVision можно найти на прямо на сайте Puya или Keil при желании, но проект все-таки любительский и будем пользоваться бесплатным GCC ARM toolchain (arm-none-eabi-gcc). Прошивку будем заливать через последовательный интерфейс, утилиту на Python я разработал на базе найденной на GitHub, но по какой-то причине она мне не понравилась.
Все определения использованы от PY32F030, он от отличается только корпусом и спецификацией, где занижены размер памяти, убрано упоминание о имеющихся в наличии периферийных устройствах.

Редактировать очень удобно в Visual Studio Code с установленным плагином Platformio — все плюшки для контроля кода в вашем распоряжении.

Ну а компиляция — кондовым make. Думаю, напечатать 4 буквы пальцы не отвалятся.

Итак, используем нагреватель на 400 Вт 230 Вольт, сам по себе он отключается при температуре 260 градусов. Регулировать мощность на нем будем схемой на симисторе — у меня завалялся такой модуль, который определяет момент пересечение фазой нуля и там же симистор с опторазвязкой.

Для серьезного регулирования желательно иметь регулятор с более-менее линейной зависимостью выходной мощности от управляющего сигнала. Посему понадобится немножко математики — пишем скрипт, который построит массив углов равной мощности. Как ни странно, готового массива я не нашел. А тот единственный, что нашелся, был так далеко от идеала, что это было видно невооруженным взглядом. Этот скрипт вы найдете в проекте среди прочих питоновских файлов.

С измерением температуры тоже не все тривиально. Можно было конечно вычислять по готовой формуле каждый раз прямо в программе — но ресурсов это бы отъело немало. Проще и почти не требует ресурсов, если взять таблицу, в ней в соответствие температуре с шагом 5 градусов поставить код АЦП. А все промежуточные значения вычислять линейной аппроксимацией. Ну и куда тут без Питона — скриптик позволит подобрать к тому NTC, что у вас оказался под рукой, подтягивающий резистор и линеаризовать принципиально нелинейный NTC. Но без автомата — подставляете сопротивление своего резистора в исходный код и смотрите, что получилось.

Когда все заработало, надо подобрать коэффициенты для ПИД-регулятора. Наверно, это жлобство, готовых программ отображения графиков в реальном времени хватает, но тем не менее соответствующий скрипт в проекте вы найдете.


Дисплей я описывал давным-давно — тоже за копейки когда-то купил пучок алфавитно-цифровых дисплеев 4 строки по десять символов, их используют в Сименсовских контроллерах «LOGO!». Из особенностей программного обеспечения — 2 и 3-я строки используются для отображения больших цифр из пользовательских символов.

И кнопки там есть готовые — резинки-нажималки для них можно вырезать из любого пульта дистанционного управления, который вы забыли вовремя выбросить. Если ставить по диагонали — там шаг как раз 10 мм, очень распространенный. Мне одного такого пульта хватило на 3 самоделки с такими дисплеями.

Корпус какой-никакой тоже не помешает, OpenScad файлы тоже найдете в проекте.

Но вот вроде и все, писать особо нечего — все лежит на GitHub, пользуйтесь на доброе здоровье.


Следующая безумная идея — расковырять дешевый китайский bluetooth/zigbee контроллер, готовая плата с которым продается в районе доллара — PHY6252. Получится или нет — не знаю. Прельстил он поддержкой Bluetooth Angle of Arrival (AoA) — по крайней мере для передачи. А мне как раз не помешало бы десяток маяков, чтобы поиграться с позиционирование внутри помещений. Вернее, снаружи, для газонокосилки. Хотя никто и не документирует, но похоже в газонокосилке Ecovacs Goat (то бишь коза) именно такая система используется для навигации. Только за маяк просят больше сотни баксов. Готовых проектов-самоделок пока не видно, маяк передатчик-то сделать не особо сложно, а вот приемник…
Там нужна прецизионная антенная решетка, высокочастотные переключатели — героев осилить такое пока не наблюдается. Но они не могут не появиться — идея-то явно интересная и стоящая. А может, герои и есть, но широкой публике не видны, если я что-то пропустил — подскажите.
+30 |
1220
35
|
+82 |
4337
152
|
+84 |
3238
122
|
Плата разработки ESP32-C3 Плата разработки ESP32 SuperMini Плата разработки ESP32 WiFi Bluetooth
https://aliexpress.com/item/1005006241076128.html 132 рэ с доставкой (в мобильном еще дешевле).
Ammo1 в феврале разбирал их у себя в блоге:
Память: 400 КБ SRAM, 4 МБ Flash;
Беспроводные коммуникации: Wi-Fi 2.4 ГГц 802.11b/g/n/mc (до 150 Мбит/c), Bluetooth 5;
До 13 цифровых Входов/выходов и до 6 аналоговых входов (цифровые и аналоговые сигналы могут подключаться к одним и тем же выводам платы);
Аппаратные протоколы: UART, SPI, I2C, I2S, BLE, Wi-Fi;
Питание: 3.3V (встроенный стабилизатор с питанием от Type C);
Размер: 24x18 мм. (с ноготок мизинца)
Синий светодиод подключен к GPIO8, кнопка BOOT к GPIO9, соответственно и светодиод и кнопку можно использовать в своих проектах.
Архитектура ядра Arm Cortex-M0+ RISC-V 32-bit (RV32IMC)
Тактовая частота До 48 МГц До 160 МГц
ОЗУ (SRAM) 2 КБ 400 КБ
Flash 16 КБ 4 МБ (внешняя, обычно SPI Flash)
Беспроводные интерфейсы Нет Wi-Fi 2.4 ГГц, Bluetooth 5.0 LE
Проводные интерфейсы UART, I2C, SPI, GPIO UART, I2C, SPI, PWM, ADC, GPIO
Потребление в спящем режиме < 1 мкА (STOP mode) ~5 мкА (deep sleep)
Питание (VDD) 1.8–3.6 В 3.0–3.6 В
Корпуса SOP8, TSSOP20 QFN, модуль
Стоимость MCU ~$0.10–0.20 ~$1.20–2.00
Разработка / SDK Keil, IAR, bare-metal ESP-IDF, Arduino, PlatformIO, Zephyr
Назначение Ультра-дешёвые логические контроллеры Умные IoT-устройства с беспроводной связью
Примеры применения Кнопки, светодиоды, питание, простые таймеры Умные розетки, датчики, устройства управления по Wi-Fi
Документация и сообщество Минимальные ресурсы, слабо известен Огромное коммьюнити, отличная документация
Чай тоже не лаптем щи хлебаем.
mysku.club/blog/china-stores/87263.html
Но тут работа была сделана ради удовольствия
Я свое дипломное устройство допаивал утром в день защиты. В итоге я только на следующий вечер после защиты увидел, что на табуретке возле моего стола на подставочке стоит себе спокойно включенный паяльник. Больше суток он простоял после ответственной пайки).
Удивительно как его за это время кошка на ковер не свалила.
А так, проект интересный. Всегда приятно сделать что-то самому даже если можно купить. От покупки навыки не растут и нет чувства удовлетворения. Хотя и без покупок тоже никуда.
Vscode вполне нормальная среда для ардуиноподобной фигни. Можно отлаживать. А если сравнить с родной средой, то они отличаютя как небо и земля. Вы же предлагаете писать в текстовых редакторах. Мне так неудобно.
Не убедительно. Даже если время ничего не стоит в денежном выражении, то все равно его не имеет смысла тратить на изучение ненужных микроконтроллеров. Если можно взять любой знакомый, а время потратить на творчество, придумывание чего-то своего. Другое дело, если просто хочется. Но данное желание весьма странное.
Если с детектором перехода через ноль, значит нагревателем можно управлять только в режиме on/off. В этом случае будет неприятно мигать свет в квартире в такт с включением. Проходил это при изготовлении управления феном. Пришлось перейти на фазовое управление и использовать MOC3021 без привязки к нулю.
Это так называемая "формула диммера". Не так много попадалось информации на эту тему. Насколько я понимаю, аналитическую зависимость угла от мощности найти нельзя, можно лишь находить таблично.
Действительно, при очень нелинейной зависимости сопротивления NTC от температуры, можно подобрать второй резистор в делителе так, что в интересующем диапазоне температур напряжение на делителе будет меняться практически линейно. Только не всегда это согласуется с диапазоном входных напряжений АЦП.
Схема детектора нуля — тоже узел, в который можно вкладывать много мыслей. Чтобы получить минимальную зависимость угла срабатывания от колебаний сетевого напряжения.
Еще одна точка приложения мозговых усилий — это реализация собственно фазового управления. Самый тупой метод — по прерыванию от детектора перехода через ноль запускать таймер и отсчитывать постоянную задержку для заданной мощности. Но частота сети немного гуляет, но самое главное, сетевое напряжение имеет кучу помех. Поэтому возможны ложные срабатывания детектора. Делал цифровую PLL, когда один из таймеров был привязан к сетевому напряжению с точностью до фазы, один из каналов стравнения использовался для управления симистором, а на вход захвата поступали импульсы с детектора. Но не скажу, что остался полностью доволен. Сетевая частота довольно низкая, чтобы эффективно фильтровать помехи, приходится увеличивать постоянную времени петлевого фильтра. А тогда недопустимо долго происходит захват. Надо делать что-то адаптивное.
Смотрю исходник, тут тоже фазовое управление реализовано нетривиально, использованы целых 3 таймера и внешнее прерывание. И в этом жирный минус обзору: про самое интересное, программные алгоритмы — ни слова.
А кому хочется — тот и в исходники заглянет, я вас уверяю — там достаточно интересного. Хотя меня интересовал только сам микроконтроллер и как его программировать, остальное — вторично.
Я первично — у меня котейка тяжело болела и за день до публикации этой статьи умерла. Так что мне было абсолютно не до технических деталей.
Но самый трэш в модуле scr_power.c, это самая сложная реализация диммера, которую доводилось видеть. Понял слабо, без пояснений не обойтись. Как мне показалось, по спаду Zero Cross Detector возникает EXTI2, в обработчике дальнейшие EXTI запрещаются, читается TIM16 и вычисляется период возникновения прерываний. Обнуляется TIM17, загружается в него период 0.7 мс и разрешается его прерывание. Потом вычисляется период для TIM1 — если измеренный период вписывается в рамки MIN и MAX, то он добавляется в массив для медианной фильтрации. Затем идет FIR-фильтр с коэффициентом 0.25, затем новое значение используется для вычисления нужной задержки импульса и грузится в TIM1.
Через 0.7 мс произойдет прерывание TIM17, где обнуляется TIM1 (с этого момента он начинает отсчет задержки выходного импульса), а в TIM17 загружается задержка 2.3 мс. Через 2.3 мс возникет второе прерывание, где снова разрешаются EXTI, а дальнейшие прерывания TIM17 запрещаются. Не совсем понял, почему выбраны такие времена.
Допустим, появилась помеха, ZCD сработал где попало. При этом измеренный период не впишется в MIN и MAX, пересчета периода TIM1 не будет. Но ведь TIM17 запустится, и он в прерывании сбросит TIM1 в непонятно какой момент, выходной импульс сформируется в ответ на это ложное срабатывание ZCD. Это так?
А в случае если так как тут, включать на определенных углах фазы, не мигает свет?
scr_power.c — на самом деле прост и туп. Один таймер — коррекция времени перехода через нуль, импульс приходит раньше, чем фактический переход.
Кроме того, система не кварцована, а разброс частоты внутреннего генератора довольно большой, еще один таймер подстраивается под эту частоту.
Нормальной фазовой подстройки нет, В принципе ложное срабатывание возможно. В электровозах на переменном токе такое не пройдет :) — там при рекуперации от синусоиды остается только воспоминание.
в pid куча настроек на превышение температуры, когда нужно полностью выключить нагрев. Терморезистор приклеен сбоку, и прогревается не моментально. Законы остывания и нагрева сильно отличаются, приходится сбрасывать интеграл. По началу у меня при целевой температуре 140 градусов происходили перегревы на 50 градусов. Линеаризация малых мощностей сильно помогла, возможно, сейчас и без всего этого будет работать. Коэффициент — от балды, он не нужен, но коэффициенты ПИД становятся какими-то сильно маленькими.
Со вторым согласен, а вот с первым не соглашусь. Использовать столько таймеров — зачем? Если один из таймеров подстраивается под сеть, то захват этого таймера по ZCD сразу даст текущую ошибку фазы. А канал сравнения этого таймера сможет сформировать выходной импульс. Необходимую коррекцию задержки ZCD можно добавить к коду сравнения, коррекция возможна как в плюс, так и в минус. В итоге — всего 1 таймер, никаких внешних прерываний, лишь одно прерывание по захвату, где делается подстройка таймера и загрузка нового кода сравнения.
Раз есть таймер, который подстроен к сети, он может давать правильный выходной импульс, даже когда импульса ZCD нет, или он пришел не вовремя. В такой ситуации таймер не подстраивается, это реализовано. Но зачем всё испорчено тем, что даже при плохом измеренном периоде TIM1 сбрасывается?
Не могу понять алгоритма. Когда устанавливается флаг перегрева, PID не выполняется. Для чего тогда снижение интеграла, как это используется?
Какое отношение имеет коэффициент для расчета предсказанной температуры к коэффициентам PID? Вы точно автор программы?
трансформатортупо оптрон через резистор и ADC. Т.к. будет попытка плавного старта для мощного компрессора, то по любому буду использовать «вычисленный ноль».А так то идея та-же — за много периодов усреднить и синхронизировать с таймером, благо это не бензогенератор и частота не ускачет. Тем более, что компрессор разгоняется всего за ~15 периодов. От ZC ещё отказался, потому что не хватило ножек на всё. Сначала просто хотел заменить стартовое реле, а в нём отключение идёт по порогу напряжения — оттуда и оптрон с резистором.
Это можно сделать с помощью цифровой петли PLL. Только вопрос с петлевым фильтром. С одной стороны, хочется подольше усреднять для более стабильной работы. С другой — нежелательно иметь долгий процесс захвата. Кроме обычного LPF понадобится еще и нелинейная фильтрация. Учитывая случайный характер помех, мгновенная фаза может иметь большие выбросы, тут к месту будет медианный фильтр, как у donBaton. Еще можно в состоянии захвата реагировать на переход через ноль только в узком окне.
Мне немного стыдно, но спросил у ИИ, он тоже с большим сомнением отнёсся усложнению и тем более FFT — максимум предложил фильтр Калмана или медианный фильтр. Но это я и так по умолчанию почти всегда делаю для ADC благо сигналы медленные.
ps
Оффтоп, но раз уж начал…
В процессе обсуждение возник вопрос — как ловить обороты. Двигатель асинхронный, с фазосдвигающей. И вот тут производя измерения потребляемого тока — заметил на осциллографе подключенному к трансформатору тока помимо 50Hz ещё и некие девиации с частотой сильно меньшей. На вскидку это результат «скольжения асинхронника» что можно интерпретировать как обороты. Для этого и FFT.
Хотя для учебных целей в программировании-реализации такого рода устройств материал интересный.