Детектор перехода через ноль с гальванической развязкой и без неё

Определение пересечения нуля без гальванической развязки

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

Они есть у всех распространенных микроконтроллерах, в том числе и STM32:

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

Собирать тут почти нечего, просто подключаю сетевое напряжение через два резистора:

На осциле почти прямоугольные импульсы, как и при моделировании.

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

Можно ли вообще так делать? Этот способ советует Atmel, также видел такую же реализацию в конструкции встраиваемого регулятора на микроконтроллере Microchip.

Определение пересечения нуля с гальванической развязки

Такая схема широко используется во многих регуляторах и благодаря оптрону мы не имеем непосредственно проводной связи с высоким сетевым напряжением.

На выходе имеем короткие красные импульсы, ну а синяя синусоида отмасштабирована для наглядности.

Собираем простую схему на макетной плате:

Подключаем к сети и смотрим на осциллографе сигнал на выходе:

Так, так. Есть импульсы, а что там с временными промежутками? Между импульсами два квадрата, развертка стоит 5 мс/квадрат, то есть определение перехода через ноль работает правильно (не учитывая возможного сдвига).

Создание проекта

Файл, новый проект: File -> New Project

Выбираем нужный МК: STM32F103C8

Включаем отладчик: System Core -> SYS -> Debug: Serial Wire
Частоту тактирования (по умолчанию 8 МГц) не изменяем.

Нажимаем на любой удобный вывод (у меня это PB12) и выбираем GPIO_EXTI (External Interrupt), для удобства можно обозвать как AC_Zero (ПКМ -> Enter user label):

Настраиваем внешнее прерывание ( GPIO mode -> External Interrupt Mode with Rising edge trigger detection), нам нужно заходить в него по падающему фронту (переход от низкого уровня к высокому) - для схемы с развязкой.
Для схемы без развязки выбираем по обоим фронтам (GPIO mode -> External Interrupt Mode with Rising/Falling edge trigger detection).

Любое название и для Keil:
Project Name: zero_crossing
Toolchain/IDE: MDK-ARM, Min Version: V5.27

Генерируем код и открываем проект: GENERATE CODE -> Open Project

Программирование

Создаем глобальную переменную:

/* USER CODE BEGIN PV */ uint8_t AC_Zero_Crossing = 0; /* USER CODE END PV */

Для гальванически неразвязанного просто добавляем обработчик, в которм переменная инвертируется (значение меняется на противоположенное (0->255->0->255...)) каждый раз при возникновении прерывания (при каждом переходе):

/* USER CODE BEGIN 4 */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == AC_Zero_Pin) { AC_Zero_Crossing = ~AC_Zero_Crossing; } } /* USER CODE END 4 */

Для развязанного с сетью в главном цикле, если на входе ноль присваиваем переменной ноль (задержка добавлена для отладки):

/* USER CODE BEGIN WHILE */ while (1) { if(HAL_GPIO_ReadPin(AC_Zero_GPIO_Port, AC_Zero_Pin) == GPIO_PIN_RESET) { AC_Zero_Crossing = 0; } HAL_Delay(1); /* USER CODE END WHILE */

И функция, вызываемая при каждом импульсе по переднему фронту, в которой присваивается переменной 255:

/* USER CODE BEGIN 4 */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == AC_Zero_Pin) { AC_Zero_Crossing = 255; } } /* USER CODE END 4 */

Проверка

Первая схема

Теперь при каждом переходе через ноль синусиодального переменного напряжения возникает прерывание по переднему и заднему фронту, а в его обработчике инвертируется значение глобальной переменной AC_Zero_Crossing:

Вторая схема

Здесь при каждом импульсе (переход через ноль) в прерывании выставляется переменной  AC_Zero_Crossing равным 255, а в главном цикле это значение сбрасывается в ноль, если на входе ноль с периодом 1 мс.

Отлично, очень похоже, сохраним результат в .csv и проверим временные промежутки между импульсами:

То, что нужно!

Зачем нужно?

Для реализации фазовой регулировки

 ФИМ (по сути ШИМ привязанный во времени) нужно знать когда переменное напряжение пересекает ноль (например), чтобы от этой точки вести отсчет, т.к. период сигнала известен ( f = 50 Гц, T = 20 мс).

Для уменьшения ЭМ помех

Напряжение сети периодично меняется (на то оно и переменное), в амплитуде достигает UA230*√2 = 325 В, то есть включая нагрузку (да ту же лампу выключателем) мы можем попасть в такой временной промежуток, когда напряжение высоко. Но если знать когда напряжение сети почти нулевое, то мы можем включать потребитель вблизи нуля, тем самым предотвращая броски тока.

Готовое решение (детектор нуля и маломощный симистор в одном корпусе)

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

Скачать

https://github.com/Egoruch/Zero-Crossing-Detector-STM32-HAL
(ссылка на GitHub)

Zero-Crossing-Detector-STM32-HAL-master.zip
(прямая ссылка)
Рабочие проект STM32CubeIDE

zero_crossing_circuits.zip  Схемы для моделирования в Microcap 12 (также есть в архиве)

Видео

73
RSS
Нет комментариев. Ваш будет первым!
Загрузка...