- Що таке ШІМ-сигнал?
- Програмування PIC для генерації ШІМ на шпильках GPIO
- Кругова діаграма
- Моделювання
- Налаштування обладнання для управління сервомотором за допомогою мікроконтролера PIC
Генерація ШІМ-сигналу є життєво важливим інструментом в арсеналі вбудованих інженерів, вони дуже корисні для багатьох застосувань, таких як контроль положення серводвигуна, перемикання декількох електронних ІС в перетворювачах / інверторах і навіть для простого регулювання яскравості світлодіодів. У мікроконтролерах PIC сигнали ШІМ можуть генеруватися за допомогою модулів Порівняння, Захоплення та ШІМ (CCP) шляхом встановлення необхідних Регістрів. Ми вже дізналися, як це зробити в підручнику з ШІМ PIC. Але у цього методу є один суттєвий недолік.
PIC16F877A може генерувати ШІМ сигнали тільки на шпильки RC1 і RC2, якщо ми будемо використовувати модулі КПК. Але ми можемо зіткнутися з ситуаціями, коли нам потрібно більше контактів, щоб мати функціональність ШІМ. Наприклад, у моєму випадку я хочу керувати 6 сервомоторами RC для мого проекту роботизованої руки, для якого модуль CCP безнадійний. У цих сценаріях ми можемо запрограмувати штифти GPIO для отримання сигналів ШІМ за допомогою модулів таймера. Таким чином ми можемо генерувати якомога більше сигналів ШІМ за допомогою будь-якого необхідного виводу. Існують також інші апаратні хаки, наприклад використання мультиплексора ІС, але навіщо інвестувати в апаратне забезпечення, коли того ж можна досягти за допомогою програмування. Отже, у цьому підручнику ми дізнаємось, як перетворити пік PIC GPIO у ШІМ-штир, і для його тестування ми змоделюємо його на протеї за допомогою цифрового осцилографа, а такожконтролюйте положення сервомотора за допомогою ШІМ-сигналу та варіюйте його робочий цикл, змінюючи потенціометр.
Що таке ШІМ-сигнал?
Перш ніж вдаватися до деталей, давайте трохи розберемося, що таке ШІМ-сигнали. Широтно-імпульсна модуляція (ШІМ) - це цифровий сигнал, який найчастіше використовується в схемі управління. Цей сигнал встановлюється високим (5v) і низьким (0v) заздалегідь визначеним часом і швидкістю. Час, протягом якого сигнал залишається високим, називається "вчасно", а час, протягом якого сигнал залишається низьким, називається "часом вимкнення". Існує два важливі параметри ШІМ, про які йдеться нижче:
Робочий цикл ШІМ
Відсоток часу, протягом якого сигнал ШІМ залишається ВИСОКИМ (у часі), називається робочим циклом. Якщо сигнал завжди ввімкнений, він знаходиться у 100% робочому циклі, а якщо він завжди вимкнений, це 0% робочого циклу.
Цикл роботи = час включення / (час включення + час вимкнення)
Назва змінної |
Відноситься до |
ШІМ_частота |
Частота ШІМ-сигналу |
T_TOTAL |
Загальний час, витрачений на один повний цикл ШІМ |
T_ON |
За часом подання ШІМ-сигналу |
T_OFF |
Час вимкнення ШІМ-сигналу |
Робочий цикл |
Черговий цикл ШІМ-сигналу |
Тож давайте підрахуємо.
Це стандартні формули, де частота - це просто взаємність часу. Значення частоти повинен визначати та встановлювати користувач на основі його / її вимоги до програми.
T_TOTAL = (1 / ШІМ_частота)
Коли користувач змінює значення робочого циклу, наша програма повинна автоматично регулювати час 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 та модуль ADC PIC для створення сигналу ШІМ на основі різного робочого циклу відповідно до значення АЦП від POT. Якщо ви новачок у використанні цих модулів, настійно рекомендуємо прочитати відповідний посібник, натиснувши гіперпосилання.
Програмування PIC для генерації ШІМ на шпильках GPIO
Повна програму для цього уроку можна знайти в нижній частині сайту, як завжди. У цьому розділі давайте розберемося, як насправді написана програма. Як і всі програми, ми починаємо з встановлення бітів конфігурації. Я використав опцію переглядів пам'яті, щоб встановити її для себе.
// CONFIG #pragma config FOSC = HS // Біти вибору осцилятора (HS oscillator) #pragma config WDTE = OFF // Біт включення сторожового таймера (WDT вимкнено) #pragma config PWRTE = OFF // Біт активації таймера включення (PWRT вимкнено) #pragma config BOREN = ON // Біт увімкнення скидання коригування (BOR увімкнено) #pragma config LVP = OFF // Біт ввімкнення послідовного програмування в ланцюзі низької напруги (одне живлення) (RB3 - цифровий ввід / вивід, HV на MCLR потрібно використовувати для програмування) #pragma config CPD = OFF // Біт захисту коду пам'яті EEPROM (захист коду EEPROM даних вимкнений) #pragma config WRT = OFF // Flash Program Memory Ввімкнути біти (Захист від запису; вся пам'ять програми може бути записана в систему управління EECON) #pragma config CP = OFF // Біт захисту коду пам'яті Flash-програми (захист коду вимкнено) // #pragma-інструкції конфігурації повинні передувати включенню файлу проекту. // Використовуйте перелічення проектів замість #define для ON і OFF. #включати
Потім ми згадуємо тактову частоту, яка використовується в апаратному забезпеченні; тут моє обладнання використовує кристал 20 МГц, ви можете ввести значення, засноване на вашому обладнанні. Далі йде значення частоти сигналу ШІМ. Оскільки моя мета тут - керувати сервоприводом RC для хобі, для якого потрібна частота ШІМ 50 Гц, я встановив 0,05 кГц як значення частоти, і ви також можете змінити це відповідно до вимог програми.
#define _XTAL_FREQ 20000000 #define PWM_Frequency 0,05 // в кГц (50 Гц)
Тепер, маючи значення Частоти, ми можемо обчислити T_TOTAL, використовуючи вищеописані формули. Результат занурюється на 10, щоб отримати значення часу в мілі секундах. У моєму випадку значення T_TOTAL становитиме 2 мілі секунди.
int T_TOTAL = (1 / ШІМ_частота) / 10; // обчислити загальний час за частотою (в мілісекундах)) // 2 мсек
Після цього ми ініціалізуємо модулі АЦП для зчитування положення потенціометра, як обговорювалося в нашому посібнику з АЦП ПІК. Далі ми маємо процедуру переривання служби, яка буде викликатися кожного разу, таймер переповнюється, ми повернемось до цього пізніше, а тепер перевіримо основну функцію.
Всередині основної функції ми налаштовуємо модуль таймера. Тут я налаштував модуль таймера на переповнення кожні 0,1 мс. Значення часу можна розрахувати, використовуючи наведені нижче формули
RegValue = 256 - ((Затримка * Fosc) / (Прескаляр * 4)) затримка в сек і Fosc в Гц
У моєму випадку для затримки 0,0001 секунди (0,1 мс) з прескаляром 64 та Fosc 20 МГц значення мого реєстру (TMR0) має бути 248. Тож конфігурація виглядає так
/ ***** Конфігурація порту для таймера ****** / OPTION_REG = 0b00000101; // Таймер0 із зовнішнім частотним значенням і 64 як прескаляром // Також включає функцію PULL UPs TMR0 = 248; // Завантажуємо значення часу для 0,0001с; delayValue може бути в межах від 0-256 TMR0IE = 1; // Увімкнути біт переривання таймера в регістрі PIE1 GIE = 1; // Увімкнути глобальне переривання PEIE = 1; // Увімкнути периферійне переривання / *********** ______ *********** /
Потім ми повинні встановити вхідну та вихідну конфігурацію. Тут ми використовуємо штифт AN0 для зчитування значення АЦП і штифтів PORTD для виведення сигналів ШІМ. Тож ініціюйте їх як вихідні штифти і зробіть їх низькими, використовуючи наведені нижче рядки коду.
/ ***** Конфігурація порту для вводу / виводу ****** / TRISD = 0x00; // Вказати MCU, що всі штифти на PORT D виводяться PORTD = 0x00; // Ініціалізуємо всі шпильки до 0 / *********** ______ *********** /
Усередині нескінченного у час циклу, ми повинні обчислити значення за часом (T_On) з робочого циклу. За часом і обов'язок цикл змінюється в залежності від положення ПСТА таким чином, ми робимо його повторно всередині в той час циклу, як показано нижче. 0,0976 - це значення, яке потрібно помножити на 1024, щоб отримати 100, і для обчислення T_ON ми помножили його на 10, щоб отримати значення в мілі секундах.
while (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; // Очистити кількість прапорів переривання таймера ++; // Приріст рахунку за кожні 0,1 мс -> count / 10 дасть значення підрахунку в мс }
Нарешті, настав час переключити штифт GPIO на основі значень T_ON і T_OFF. У нас є змінна count, яка відстежує час у мілі секундах. Отже, ми використовуємо цю змінну, щоб перевірити, чи менше часу , ніж час , якщо так, то ми залишаємо включений штифт GPIO, інакше ми його вимикаємо і залишаємо вимкненим до початку нового циклу. Це можна зробити, порівнявши його із загальним часом одного ШІМ-циклу. Код, щоб зробити те ж саме, показано нижче
if (count <= (T_ON)) // Якщо час менше, ніж за часом RD1 = 1; // Увімкнути GPIO ще RD1 = 0; // В іншому випадку вимкніть GPIO, якщо (count> = (T_TOTAL * 10)) // Тримайте його вимкненим, поки не почнеться новий цикл count = 0;
Кругова діаграма
Схема генерації ШІМ за допомогою виводу GPIO мікроконтролера PIC дуже проста, просто підключіть PIC до генератора і підключіть потенціометр до виводу AN0 та сервомотора до виводу RD1, ми можемо використовувати вивід GPIO для отримання сигналу ШІМ, я вибрав RD1 просто випадковий. І потенціометр, і серводвигун живляться від напруги 5 В, що регулюється від 7805, як показано нижче на схемі.
Моделювання
Для імітації проекту я використав своє програмне забезпечення proteus. Створіть схему, показану нижче, і зв’яжіть код із вашим моделюванням та запустіть його. Ви повинні отримати сигнал ШІМ на штифт RD1 GPIO відповідно до нашої програми, а робочий цикл ШІМ повинен контролюватися залежно від положення потенціометра. Наведений нижче GIF показує, як реагують сигнал ШІМ та серводвигун, коли значення АЦП змінюється через потенціометр.
Налаштування обладнання для управління сервомотором за допомогою мікроконтролера PIC
Моє повне налаштування апаратного забезпечення показано нижче, для людей, які стежать за моїми підручниками, ця дошка повинна виглядати знайомою, це та сама дошка, яку я використовував у всіх своїх підручниках до цього часу. Ви можете звернутися до підручника з блимаючим світлодіодом, якщо вам цікаво знати, як я його будую. В іншому випадку просто дотримуйтесь схеми вище, і все повинно працювати нормально.
Завантажте програму та варіюйте потенціометр, і ви побачите, як сервопривід змінює положення залежно від положення потенціометра. Повний робочий проект показаний в відео даного в кінці цієї сторінки. Сподіваюся, ви зрозуміли проект і вам сподобалось будувати, якщо у вас є побажання, сміливо публікуйте їх на форумі, і я постараюся з усіх сил відповісти.
Я планую продовжити цей проект, додавши опції для управління кількома серводвигунами і, таким чином, будуючи з нього робототехнічний кронштейн, подібний до Arduino Robotic Arm, який ми вже створили. Тож до тих пір до зустрічі !!