Контроль напряжения над блоком питания на STM32: Подход к энергоэффективности и защите
Автономные системы становятся все более востребованными - от портативных приборов до сложных промышленных комплексов - надежное управление напряжением питания превращается в ключевой фактор их долговечности и эффективности. Сердце любой такой системы - аккумулятор, а его безопасность и срок службы, напрямую зависит от контроля напряжения.
В данной статье будет представлен пример контроля напряжения, над блоком питания - внутри которого (никель-металлгидридная аккумуляторная сборка NiMH 14.4В/12 банок по 1.2В(1.4В- при полной зарядке)).
В блоке питания уже есть палата управления над аккумулятором, которая выполняет задачи:
Работа с кнопкой;
Работа со светодиодом;
Работа с пъезоэлектрическим излучателем(звуковая индикация);
Контроль заряда/разряда аккумулятора(дает звуковой сигнал при напряжении менее 9 вольт и более 14).
В процессе анализа и статистики использования оборудования стало очевидно, что многие пользователи часто забывают своевременно отключать блоки питания. В результате аккумуляторные сборки продолжают разряжаться даже при отсутствии необходимости, напряжение падает до критических значений, и аккумулятор быстро теряет свою емкость, становясь непригодным для дальнейшей эксплуатации.
Помимо этого, подключенная система оказывается в неопределенном состоянии, на плату управления и различные датчики по-прежнему подается питание, что приводит к избыточной нагрузке. В качестве этого сокращается ресурс электронных компонентов и снижается надежность всего устройства.
Для решения данной проблемы я продемонстрирую пример системы контроля напряжения блока питания, в качестве микроконтроллера выбран STM32F103С8T6, который выполняет следующие задачи:
Непрерывный мониторинг напряжения аккумуляторной сборки, измерение производится через АЦП с использованием DMA;
Оповещение пользователя о низком заряде, при падении напряжения ниже установленного порога (в данном примере - 9.0В) система активизирует звуковой сигнал, время работы оповещения ограничено - звуковая индикация будет длится 5 минут;
Переход в энергосберегающий режим, если напряжение остается ниже порога и пользователь не предпринял действий в течении заданного времени, микроконтроллер переводит систему в режим сна, это сопровождается отключением тактирования и всей периферии, что минимизирует и предотвращает глубокий разряд аккумулятора.
Схема подключения NiMH АКБ, делителя напряжения к АЦП МК, кнопки вкл/выкл и пъезо-излучателя
Перечень компонентов
Объяснение схемы
Узел[1]
Входной силовой ключ, исток подключен к +12V, сток идет к блоку питания(+12_АКК) через предохранители, а затвор подтянут к земле, применение (защищенная подача напряжения питания с аккумуляторного блока);
Узел[2]
Вторичный силовой ключ, обеспечивает управляемое включение/отключение напряжения питания основной нагрузки системы, управление происходит через МК, сигнал PWR_ON, после включения данного узла, на стоке напряжение питания +12ВК активизируется и передает напряжение другим частям схемы, в моем примере это (узел[4]-Звуковая индикация и узел[5]-lделитель напряжения), но также можно использовать данный узел и на включение преобразователей напряжения;
Узел[3]
Данный узел обеспечивает логику взаимодействия с кнопкой включения/выключения, кнопка sa2, при нажатии формирует управляющий сигнал, диод АD4 и конденсатор С1 обеспечивают фильтрацию и антидребезг;
Узел[4]
Данный узел обеспечивает звуковую индикацию, сигнал BEEP подключается к МК;
Узел[5]
Данный узел является делителем напряжения, делит напряжение до уровня, подходящего для измерения АЦП МК (обычно до 3.3V), подстроечный резистор R8, выставлен на 1.7кОм.
Настройка микроконтроллера STM32F103 в CubeIDE
Конфигурация TIM1(PA11)
Таймер TIM1 выполняет роль генератора для звуковой индикации.
Настройка таймера:
Предделитель (Prescaler) и период (Auto-Reload) выбраны так, чтобы на выходе формировался сигнал с частотой в диапазоне, воспринимаемом слухом (обычно 1–5 кГц);
Режим работы – PWM (широтно-импульсная модуляция);
Коэффициент заполнения (Pulse) определяет громкость и характер звучания.
Принцип работы:
Таймер генерирует ШИМ-сигнал, который подаётся на транзисторный ключ. Транзистор управляет пьезоизлучателем или динамиком. В результате получается слышимый звук.
Преимущества такого решения:
Микроконтроллеру не нужно вручную формировать частоту – этим занимается таймер;
Легко изменять тональность: достаточно переписать значения ARR/PSC;
Можно реализовать разные звуковые эффекты (короткие сигналы, мелодии) простым управлением таймером из программы.
Конфигурация ADC(PA1)
В проекте используется многоканальный режим работы АЦП с двумя каналами в последовательности (Regular conversion sequence).
Rank 1 – внешний канал (ADC Channel 1).
Этот вход подключён к делителю напряжения и используется для измерения напряжения аккумулятора.
Благодаря этому микроконтроллер может в реальном времени контролировать состояние питания устройства.
Rank 2 – внутренний канал (Vrefint).
Это встроенный источник опорного напряжения микроконтроллера. Он служит для автоматической калибровки и компенсации возможных изменений питающего напряжения. С его помощью можно более точно измерять значение внешних сигналов, в том числе напряжение аккумулятора.
Для повышения эффективности задействован DMA: результаты обоих измерений (Rank 1 и Rank 2) автоматически передаются в память, а процессор получает только готовые данные.
Для правильной настройки ADC я воспользовался данной информацией, там подробно расписано как работать с ADC МК-STM32.
Конфигурация пина для работы с кнопкой
Для работы с кнопкой выбран вывод PB11, сконфигурированный в режиме:
GPIO_EXTI – внешний прерывающий вход. Это значит, что нажатие кнопки обрабатывается не опросом в цикле, а через аппаратное прерывание;
Mode - External interrupt, Falling edge trigger – прерывание срабатывает по спаду сигнала (при замыкании кнопки на землю);
Pull-up – включен внутренний подтягивающий резистор, который удерживает вход в состоянии логической «1», пока кнопка не нажата.
Кнопка подключена так, что в обычном состоянии на входе PB11 присутствует логическая «1» благодаря встроенному подтягивающему резистору (Pull-up). При нажатии контакт замыкается на землю, формируется логический «0» и происходит спад сигнала. Этот спад фиксируется модулем EXTI, который вызывает прерывание.
Конфигурация пина для работы с сигналом PWR_ON
Сигнал PWR_ON играет роль электронного «выключателя питания».
В исходном состоянии (Low) нагрузка обесточена.
При активации (перевод вывода в High) силовой MOSFET открывается, и напряжение +12ВК подаётся на остальные узлы системы.
В примере данная линия питает:
узел [4] – звуковую индикацию,
узел [5] – делитель напряжения для мониторинга питания.
Аналогично этот узел можно использовать и для включения DC/DC-преобразователей или других модулей, требующих управляемого питания.
Конфигурация Clock
Реализация программного кода
Ссылка на скачивание исходного кода [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_исходный_код - Adc_VoltageControl_STM32F103C8T6]
Заголовочный файл keys.h (работа с кнопками)
В данном файле определены:
Функции работы с кнопками;
Битовые маски состояний;
константы для различных сценариев нажатий.
keys.h
Реализация модуля keys.c (работа с кнопками)
Данный модуль включает в себя задачи:
Устранение дребезга контактов;
Различие между коротким и долгим нажатием;
Отслеживание событий нажатия, удержания и отпускания.
keysDrv_Handler()
Вызывается постоянно в основном цикле или из системного таймера.
Нажатие кнопки (первичное событие)
2. if(gl_kDrv_key1_blockEvent == 0 && ON_OFFB_state == KEY_PRESS) {
3. gl_kDrv_key1_blockEvent = 1;
4. gl_kDrv_time_key1_press = ms;
5. }
Сохраняется время нажатия, дальнейшие события блокируются до отпускания
Фильтр дребезга
else if(gl_kDrv_key1_blockEvent == 1 &&
&&
gl_kDrv_key1_short_state==0 &&
(ms - gl_kDrv_time_key1_press) > DELAY4TIMER){
//прошло время защиты от дребезга, кнопка нажата
gl_kDrv_key1_short_state=1;
keyState &= ~KEY1Release_Drv;//снимаем бит отпускания кнопки
keyState |= KEY1_Drv;
}
Если прошло больше DELAY4TIMER, считаем кнопку реально нажатой.
Определение удержания
else if(gl_kDrv_key1_blockEvent == 1 &&
ON_OFFB_state==KEY_PRESS &&
gl_kDrv_key1_short_state==1 &&
(ms - gl_kDrv_time_key1_press) > DELAY_HOLD_TIMER){
keyState |= KEY1Hold_Drv;
}
Если прошло больше DELAY_HOLD_TIMER, выставляем бит удержания.
Отпускание кнопки
else if(gl_kDrv_key1_blockEvent == 1 && && gl_kDrv_key1_short_state==1){
gl_kDrv_key1_blockEvent=0;
gl_kDrv_key1_short_state=0;
keyState |= KEY1Release_Drv;
keyState &= ~KEY1_Drv;//снимаем бит нажатия кнопки
keyState &= ~KEY1Hold_Drv;//снимаем бит удержания кнопки
}
При отпускании кнопки сбрасываются флаги удержания и нажатия, выставляется бит отпускания.
getKeyState()
Возвращает текущее состояние кнопок в виде битовой маски
Позволяет определить, была ли кнопка нажата, удержана или отпущена;
После считывания некоторые флаги (например, отпускание) сбрасываются ,чтобы событие не повторялось.
getKeyPinState_AtNow()
Возвращает моментальное состояние ножек GPIO, без учета дребезга
Полезно для отладки или когда нужно мгновенно узнать, нажата ли кнопка прямо сейчас
keys.c
Реализация модуля ADC_Calc.c (работа с АЦП)
Данный модуль реализует контроль напряжения питания через АЦП микроконтроллера STM32F103C8T6, измерения выполняются с использованием:
DMA (циклическая запись данных в буфер);
Встроенного опорного напряжения Vrefint;
Собственного делителя напряжения на входе.
ADC_Calc_Handler() - главный обработчик вычислений
Проверяет, заполнена ли первая или вторая половина DMA-буфера;
Усредняет значения для канала измерения и Vrefint;
Конвертирует результат в напряжение вызовом adc_calcVoltage();
Если напряжение ниже порога critical_stress → возвращает команду отключения питания (FORCE_POWER_OFF);
Производит фильтрацию значений по диапазону 750 < val_input < 2800 (защита от шумов и выбросов).
HAL_ADC_ConvCpltCallback()
Вызывается по прерыванию DMA Transfer Complete → устанавливает флаг adcIRFullDone
HAL_ADC_ConvHalfCpltCallback()
Вызывается по прерыванию DMA Half Transfer Complete → устанавливает флаг adcIRHalfDone
adc_init()
Сброс флагов и буфера.
adc_start()
Запускает АЦП в режиме DMA, далее происходит циклическое заполнение adcDMAbuf без участия процессора
adc_stop()
Останавливает АЦП и DMA;
Сбрасывает флаги готовности
adc_calcVoltage()
Ключевая функция — переводит «сырые» значения АЦП в напряжение
adc_GetVoltage()
Геттер для получения последнего значения рассчитанного напряжения
Общий алгоритм работы:
DMA заполняет буфер парами значений (input, Vrefint);
При заполнении половины буфера → срабатывает прерывание, ставится флаг;
ADC_Calc_Handler считывает данные, фильтрует и усредняет;
Вызывается adc_calcVoltage, которая переводит вольты;
Значение доступно через adc_GetVoltage();
Если напряжение меньше 9 В (по critical_stress) → отрабатывает аварийное выключение.
ADC_Calk.c
Пояснение к функции adc_calcVoltage()
Расчет VDDA, где:
VREFINT_TYP - калибровочное значение 1.20, взято из datasheet, у других МК на заводе производитель прошивает калибровочное значение в ПЗУ при изготовлении, пример получения значения с МК STM32F030CCTx [0x1FFFF7BA];
4095 - когда измеряется источник встроенным АЦП, результат выражается в единицах квантования, максимум которых равен 4095, поэтому в формуле используется множитель 4095 - это нормализация значения, чтобы связать измеренный АЦП с напряжением VDDA.
ADC_vref - значение встроенного источника опорного напряжения
Перевод значения канала в напряжение
ADC_in - напряжение измеренное с делителя напряжения (узел[5])
Коррекция через делитель напряжения
Вход подключен через делитель R1=221кОм и R2 = 27кОм, переводим в Ом,
добавил смещение (-0.5) для подстройки измерений.
Таблица замеров напряжения от 14.5 вольт до 7 вольт.
Прикладываю видео-тестирования прохода по спаду напряжения, а также видео-тестирования, сброс напряжения и уход в сон микроконтроллера при низком напряжении ссылка [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_тестирование_ Adc_VoltageControl]
Реализация модуля proj_main.c (Главный метод)
Данный модуль объединяет несколько подсистем:
Кнопка управления (одиночное и двойное нажатие);
Контроль напряжения питания через АЦП;
Звуковая индикация состояния;
Автоматический переход в сон при низком напряжении.
proj_main.c
Вывод
Данная система контроля над блоком питания реализует:
Обработку кнопок с фильтрацией дребезга, с поддержкой короткого/долгого/двойного нажатия и отпускания;
Мониторинг напряжения через АЦП с защитой от просадок и автоматическим отключением при критическом низком уровне;
Звуковая индикация (короткие, двойные сигналы) для информирования пользователя о событиях;
Энергосбережение переход в режим STOP и пробуждение по прерыванию.
Систему можно использовать как основу для портативных приборов, автономных устройств и встраиваемых систем, где важно одновременно удобное управление и защита электроники.
Если статья показалась Вам интересной, буду рад выпустить для Вас еще множество статей исследований по всевозможным видам устройств, так что, если не хотите их пропустить – буду благодарен за подписку на мой ТГ-канал: https://t.me/ChipCraft.