- Что такое сигнал ШИМ?
- Программирование PIC для генерации PWM на выводах GPIO
- Принципиальная электрическая схема
- Моделирование
- Настройка оборудования для управления серводвигателем с помощью микроконтроллера PIC
Генерация сигналов ШИМ - жизненно важный инструмент в арсенале каждого встраиваемого инженера, они очень удобны для множества приложений, таких как управление положением серводвигателя, переключение нескольких силовых электронных ИС в преобразователях / инверторах и даже для простого управления яркостью светодиодов. В микроконтроллерах PIC сигналы ШИМ могут быть сгенерированы с помощью модулей сравнения, захвата и ШИМ (CCP) путем установки необходимых регистров, мы уже узнали, как это сделать в учебнике PIC PWM. Но у этого метода есть один существенный недостаток.
PIC16F877A может генерировать ШИМ сигналы только на булавки RC1 и RC2, если мы будем использовать модули КПК. Но мы можем столкнуться с ситуациями, когда нам нужно больше контактов для функциональности ШИМ. Например, в моем случае я хочу управлять 6 серводвигателями RC для моего проекта роботизированной руки, для которого модуль CCP безнадежен. В этих сценариях мы можем запрограммировать контакты GPIO для генерации сигналов ШИМ с использованием модулей таймера. Таким образом, мы можем сгенерировать столько сигналов ШИМ с любым требуемым выводом. Существуют также другие аппаратные хаки, такие как использование ИС мультиплексора, но зачем вкладывать средства в оборудование, если то же самое можно достичь с помощью программирования. Итак, в этом руководстве мы узнаем, как преобразовать вывод PIC GPIO в вывод PWM, и для его тестирования мы смоделируем его на Proteus с помощью цифрового осциллографа, а такжеуправлять положением серводвигателя с помощью сигнала ШИМ и изменять его рабочий цикл, изменяя потенциометр.
Что такое сигнал ШИМ?
Прежде чем мы углубимся в детали, давайте немного расскажем, что такое сигналы ШИМ. Широтно-импульсная модуляция (ШИМ) - это цифровой сигнал, который чаще всего используется в схемах управления. Этот сигнал устанавливается на высокий (5 В) и низкий (0 В) в заранее определенные время и скорость. Время, в течение которого сигнал остается на высоком уровне, называется «временем включения», а время, в течение которого сигнал остается низким, называется «временем выключения». Ниже описаны два важных параметра ШИМ:
Рабочий цикл ШИМ
Процент времени, в течение которого сигнал ШИМ остается ВЫСОКИМ (по времени), называется рабочим циклом. Если сигнал всегда включен, это 100% рабочий цикл, а если он всегда выключен, это 0% рабочего цикла.
Рабочий цикл = время включения / (время включения + время выключения)
Имя переменной |
Относится к |
PWM_Frequency |
Частота сигнала ШИМ |
T_TOTAL |
Общее время, затраченное на один полный цикл ШИМ |
T_ON |
По времени сигнала ШИМ |
T_OFF |
Время выключения сигнала ШИМ |
Duty_cycle |
Рабочий цикл сигнала ШИМ |
Итак, теперь давайте посчитаем.
Это стандартные формулы, в которых частота просто обратна времени. Значение частоты должно быть выбрано и установлено пользователем на основе требований его / ее приложения.
T_TOTAL = (1 / PWM_Frequency)
Когда пользователь изменяет значение рабочего цикла, наша программа должна автоматически регулировать время T_ON и время T_OFF в соответствии с этим. Таким образом, приведенные выше формулы можно использовать для вычисления T_ON на основе значений Duty_Cycle и T_TOTAL.
T_ON = (Duty_Cycle * T_TOTAL) / 100
Поскольку общее время сигнала ШИМ для одного полного цикла будет суммой времени включения и времени выключения. Мы можем рассчитать время выключения T_OFF, как показано выше.
T_OFF = T_TOTAL - T_ON
Имея в виду эти формулы, мы можем приступить к программированию микроконтроллера PIC. Программа включает в себя модуль таймера PIC и модуль PIC ADC для создания сигнала PWM на основе переменного рабочего цикла в соответствии со значением ADC из POT. Если вы новичок в использовании этих модулей, настоятельно рекомендуется прочитать соответствующее руководство, щелкнув гиперссылки.
Программирование PIC для генерации PWM на выводах GPIO
Полная программу для этого урока можно найти в нижней части сайта, как всегда. В этом разделе давайте разберемся, как на самом деле написана программа. Как и все программы, мы начинаем с установки битов конфигурации. Я использовал опцию просмотра памяти, чтобы установить ее для себя.
// CONFIG #pragma config FOSC = HS // Биты выбора осциллятора (генератор HS) #pragma config WDTE = OFF // Бит включения сторожевого таймера (WDT отключен) #pragma config PWRTE = OFF // Бит включения таймера включения (PWRT disabled) #pragma config BOREN = ON // Бит разрешения сброса пониженного напряжения (BOR включен) #pragma config LVP = OFF // Бит разрешения последовательного программирования низкого напряжения (однополярный) (RB3 - это цифровой ввод / вывод), Для программирования необходимо использовать HV на MCLR) #pragma config CPD = OFF // Бит защиты кода памяти EEPROM данных (выключение защиты кода EEPROM данных) #pragma config WRT = OFF // Биты разрешения записи в память Flash-программы (защита от записи выключена; вся программная память может быть записана управлением EECON) #pragma config CP = OFF // Бит защиты кода флэш-памяти программы (защита кода отключена) // Операторы конфигурации #pragma должны предшествовать включению файла проекта. // Используйте перечисления проектов вместо #define для включения и выключения. #включают
Затем мы упоминаем тактовую частоту, используемую в оборудовании, здесь мое оборудование использует кристалл 20 МГц, вы можете ввести значение в зависимости от вашего оборудования. Далее следует значение частоты сигнала ШИМ. Поскольку моя цель здесь - управление серводвигателем RC для хобби, для которого требуется частота ШИМ 50 Гц, я установил 0,05 кГц в качестве значения частоты, вы также можете изменить его в зависимости от требований вашего приложения.
#define _XTAL_FREQ 20000000 #define PWM_Frequency 0,05 // в кГц (50 Гц)
Теперь, когда у нас есть значение Frequency, мы можем вычислить T_TOTAL, используя описанные выше формулы. Результат увеличивается на 10, чтобы получить значение времени в миллисекундах. В моем случае значение T_TOTAL будет 2 миллисекунды.
int T_TOTAL = (1 / PWM_Frequency) / 10; // вычисляем общее время по частоте (в миллисекундах)) // 2 мс
После этого мы инициализируем модули АЦП для считывания положения потенциометра, как описано в нашем руководстве по ADC PIC. Далее у нас есть процедура обслуживания прерывания, которая будет вызываться каждый раз, когда таймер переполнится, мы вернемся к этому позже, а пока давайте проверим основную функцию.
Внутри основной функции мы настраиваем модуль таймера. Здесь я настроил модуль таймера на переполнение каждые 0,1 мс. Значение времени можно рассчитать по формулам ниже.
RegValue = 256 - ((Delay * Fosc) / (Prescalar * 4)) задержка в секундах и Fosc в Гц
В моем случае для задержки в 0,0001 секунды (0,1 мс) с прескаляром 64 и Fosc 20 МГц значение моего регистра (TMR0) должно быть 248. Итак, конфигурация выглядит так.
/ ***** Конфигурация порта для таймера ****** / OPTION_REG = 0b00000101; // Timer0 с внешней частотой и 64 в качестве предскалярного // Также включает PULL UP TMR0 = 248; // Загружаем значение времени для 0,0001 с; delayValue может находиться в диапазоне 0-256 только TMR0IE = 1; // Разрешить бит прерывания таймера в регистре PIE1 GIE = 1; // Разрешить глобальное прерывание PEIE = 1; // Включение периферийного прерывания / *********** ______ *********** /
Затем мы должны установить конфигурацию ввода и вывода. Здесь мы используем вывод AN0 для чтения значения АЦП и выводы PORTD для вывода сигналов ШИМ. Поэтому инициируйте их как выходные контакты и сделайте их низкими, используя приведенные ниже строки кода.
/ ***** Конфигурация порта для ввода / вывода ****** / TRISD = 0x00; // Сообщаем MCU, что все выводы на ПОРТУ D являются выходными PORTD = 0x00; // Инициализируем все выводы на 0 / *********** ______ *********** /
Внутри бесконечного во время цикла, мы должны вычислить значение по времени (T_On) из рабочего цикла. По времени и обязанность цикл изменяется в зависимости от положения ПСТА таким образом, мы делаем его повторно внутри в то время цикла, как показано ниже. 0,0976 - это значение, которое нужно умножить на 1024, чтобы получить 100, и для вычисления T_ON мы умножили его на 10, чтобы получить значение в миллисекундах.
в то время как (1) { POT_val = (ADC_Read (0)); // Считываем значение POT с помощью ADC Duty_cycle = (POT_val * 0.0976); // Сопоставить от 0 до 1024 с 0 до 100 T_ON = ((Duty_cycle * T_TOTAL) * 10/100); // Расчет времени по формулам. Единица измерения в миллисекундах __delay_ms (100); }
Так как таймер настроен на переполнение каждые 0,1 мс, процедура обработки прерывания таймера ISR будет вызываться каждые 0,1 мс. Внутри процедуры обслуживания мы используем переменную count и увеличиваем ее каждые 0,1 мс. Таким образом мы можем отслеживать время. Чтобы узнать больше о прерываниях в микроконтроллере PIC, перейдите по ссылкам
if (TMR0IF == 1) // Флаг таймера сработал из-за переполнения таймера -> устанавливается на переполнение каждые 0,1 мс { TMR0 = 248; // Загрузить значение таймера TMR0IF = 0; // Сброс флага прерывания таймера count ++; // Приращение счета для каждых 0,1 мс -> count / 10 даст значение счетчика в мс }
Наконец, пришло время переключить вывод GPIO в зависимости от значений T_ON и T_OFF. У нас есть переменная count, которая отслеживает время в миллисекундах. Таким образом, мы используем эту переменную, чтобы проверить, меньше ли время, чем вовремя , если да, то мы оставляем вывод GPIO включенным, иначе мы выключаем его и держим выключенным до начала нового цикла. Это можно сделать, сравнив его с общим временем одного цикла ШИМ. Код, который делает то же самое, показан ниже.
if (count <= (T_ON)) // Если время меньше, чем по времени RD1 = 1; // Включаем GPIO else RD1 = 0; // В противном случае отключите GPIO if (count> = (T_TOTAL * 10)) // Держите его выключенным, пока не начнется новый цикл count = 0;
Принципиальная электрическая схема
Принципиальная схема для генерации ШИМ с выводом GPIO микроконтроллера PIC очень проста, просто включите PIC осциллятором и подключите потенциометр к выводу AN0, а серводвигатель к выводу RD1, мы можем использовать вывод GPIO для получения сигнала ШИМ, я выбрал RD1 просто случайно. Потенциометр и серводвигатель питаются от 5 В, которое регулируется от 7805, как показано ниже на принципиальной схеме.
Моделирование
Для моделирования проекта я использовал программу Proteus. Создайте схему, показанную ниже, свяжите код с вашей симуляцией и запустите ее. Вы должны получить сигнал ШИМ на выводе RD1 GPIO в соответствии с нашей программой, а рабочий цикл ШИМ должен контролироваться в зависимости от положения потенциометра. GIF ниже показывает, как сигнал ШИМ и серводвигатель реагируют, когда значение АЦП изменяется с помощью потенциометра.
Настройка оборудования для управления серводвигателем с помощью микроконтроллера PIC
Моя полная настройка оборудования показана ниже. Людям, которые следят за моими обучающими программами, эта плата должна показаться знакомой, это та самая плата, которую я использовал во всех своих обучающих программах. Вы можете обратиться к руководству по мигающим светодиодам, если вам интересно узнать, как я его строю. В противном случае просто следуйте схеме, приведенной выше, и все должно работать нормально.
Загрузите программу и измените потенциометр, и вы должны увидеть, как сервопривод меняет положение в зависимости от положения потенциометра. Полный рабочий проект показан в видео данного в конце этой страницы. Надеюсь, вы поняли проект и вам понравилось строить. Если у вас есть вопросы, не стесняйтесь размещать их на форуме, и я постараюсь ответить.
Я планирую продвинуть этот проект вперед, добавив опции для управления несколькими серводвигателями и, таким образом, построив из него роботизированную руку, похожую на уже созданную нами роботизированную руку Arduino. Так что до встречи !!