- Какво е ШИМ сигнал?
- Програмиране на PIC за генериране на ШИМ на GPIO пинове
- Електрическа схема
- Симулация
- Хардуерна настройка за управление на сервомотора с помощта на PIC микроконтролер
Генерирането на PWM сигнал е жизненоважен инструмент във всеки вграден арсенал от инженери, те са много полезни за много приложения като контролиране на позицията на серво мотора, превключване на няколко мощни електронни интегрални схеми в преобразуватели / инвертори и дори за прост контрол на яркостта на LED. В PIC микроконтролерите PWM сигнали могат да се генерират с помощта на модулите Compare, Capture и PWM (CCP) чрез задаване на необходимите регистри, ние вече научихме как да направим това в PIC PWM урока. Но има един съществен недостатък при този метод.
В PIC16F877A може да генерира PWM сигнали само на щифтове RC1 и RC2, ако използваме модулите на ККП. Но може да срещнем ситуации, при които се нуждаем от повече щифтове, за да имаме ШИМ функционалност. Например в моя случай искам да контролирам 6 RC серво мотора за моя проект за роботизирана ръка, за който модулът CCP е безнадежден. В тези сценарии можем да програмираме GPIO щифтовете да произвеждат ШИМ сигнали, използвайки таймерни модули. По този начин можем да генерираме колкото се може повече ШИМ сигнали с всеки необходим пин. Има и други хардуерни хакове като използването на мултиплексор IC, но защо да се инвестира в хардуер, когато същото може да се постигне чрез програмиране. Така че в този урок ще научим как да конвертираме PIC GPIO пин в PWM пин и за да го тестваме ще го симулираме на протеус с цифров осцилоскоп и същоконтролирайте позицията на серво мотора с помощта на ШИМ сигнала и променяйте неговия работен цикъл, като променяте потенциометър.
Какво е ШИМ сигнал?
Преди да влезем в детайлите, нека разгледаме малко какво представляват ШИМ сигналите. Модулацията на широчината на импулса (PWM) е цифров сигнал, който се използва най-често в схемите за управление. Този сигнал се задава високо (5v) и ниско (0v) за предварително зададено време и скорост. Времето, през което сигналът остава висок, се нарича „on time“, а времето, през което сигналът остава нисък, се нарича „off time“. Има два важни параметъра за ШИМ, както е обсъдено по-долу:
Работен цикъл на ШИМ
Процентът от времето, през което ШИМ сигналът остава ВИСОКИ (навреме) се нарича работен цикъл. Ако сигналът винаги е включен, той е в 100% работен цикъл и ако винаги е изключен, това е 0% работен цикъл.
Работен цикъл = Време за включване / (Време за включване + Време за изключване)
Име на променлива |
Отнася се до |
ШИМ_честота |
Честота на ШИМ сигнала |
ОБЩО |
Общо време, необходимо за един пълен цикъл на ШИМ |
T_ON |
По време на PWM сигнала |
T_OFF |
Време на изключване на ШИМ сигнала |
Duty_cycle |
Работен цикъл на ШИМ сигнала |
И така, нека да направим математиката.
Това са стандартните формули, при които честотата е просто реципрочна на времето. Стойността на честотата трябва да бъде определена и зададена от потребителя въз основа на неговите изисквания за кандидатстване.
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 таймерен модул и PIC ADC модул, за да създаде PWM сигнал, базиран на променлив работен цикъл, според стойността на ADC от POT. Ако за първи път използвате тези модули, препоръчително е да прочетете съответния урок, като щракнете върху хипервръзките.
Програмиране на PIC за генериране на ШИМ на GPIO пинове
Най- пълната програма за този урок може да бъде намерена на дъното на сайта както винаги. В този раздел нека разберем как всъщност е написана програмата. Както всички програми, ние започваме с задаване на битове за конфигурации. Използвал съм опцията за изгледи на паметта, за да я настроя за мен.
// CONFIG #pragma config FOSC = HS // Битове за избор на осцилатор (HS осцилатор) #pragma config WDTE = OFF // Бит за активиране на Watchdog Timer (WDT деактивиран) #pragma config PWRTE = OFF // Бит за активиране на таймера за включване (PWRT деактивиран) #pragma config BOREN = ON // Bright-out Reset Enable bit (BOR enabled) #pragma config LVP = OFF // Нисковолтово (единично захранване) битово разрешено последователно програмиране (RB3 е цифров вход / изход), HV на MCLR трябва да се използва за програмиране) #pragma config CPD = OFF // бит за защита на кода на паметта на EEPROM (защита на EEPROM код за данни изключена) #pragma config WRT = OFF // битове за активиране на паметта на Flash програма (изключена защита; цялата памет на програмата може да бъде записана от контрола на EECON) #pragma config CP = OFF // Бит за защита на кода на паметта на Flash програмата (защитата на кода е изключена) // #pragma config инструкциите трябва да предшестват включването на файла на проекта. // Използвайте преброяване на проекти вместо #define за ON и OFF. #include
След това споменаваме тактовата честота, използвана в хардуера, тук моят хардуер използва кристал 20MHz, можете да въведете стойността, базирана на вашия хардуер. Следва стойността на честотата на ШИМ сигнала. Тъй като целта ми тук е да контролирам хоби RC серво мотор, който изисква PWM честота от 50Hz, зададох 0,05KHz като стойност на честотата, можете също да промените това въз основа на вашите изисквания за приложение.
#define _XTAL_FREQ 20000000 #define PWM_Frequency 0,05 // в KHz (50Hz)
Сега, след като имаме стойността на честотата, можем да изчислим T_TOTAL, използвайки горните обсъдени формули. Резултатът се потапя с 10, за да се получи стойността на времето в мили секунди. В моя случай стойността на T_TOTAL ще бъде 2 мили секунди.
int T_TOTAL = (1 / PWM_Frequency) / 10; // изчисляване на общото време от честотата (в милисекунди)) // 2msec
Следвайки това, ние инициализираме ADC модулите за отчитане на позицията на потенциометъра, както е обсъдено в нашия урок ADC PIC. След това имаме рутинната услуга за прекъсване, която ще се извиква всеки път, таймерът препълва, ще се върнем към това по-късно, засега нека проверим основната функция.
Вътре в основната функция конфигурираме таймерния модул. Тук конфигурирах модула Timer да прелива за всеки 0.1ms. Стойността за времето може да бъде изчислена с помощта на формулите по-долу
RegValue = 256 - ((Забавяне * Fosc) / (Прескалар * 4)) закъснение в сек и Fosc в hz
В моя случай за закъснение от 0,0001 секунди (0,1ms) с прескалар от 64 и Fosc от 20MHz стойността на моя регистър (TMR0) трябва да бъде 248. Така че конфигурацията изглежда така
/ ***** Конфигурация на порт за таймер ****** / OPTION_REG = 0b00000101; // Timer0 с външна честота и 64 като прескаларна // Също така позволява PULL UPs TMR0 = 248; // Зареждане на времевата стойност за 0,0001s; delayValue може да бъде между 0-256 само TMR0IE = 1; // Активиране на бит за прекъсване на таймера в регистър PIE1 GIE = 1; // Активиране на глобално прекъсване PEIE = 1; // Активиране на периферното прекъсване / *********** ______ *********** /
След това трябва да зададем конфигурацията за вход и изход. Тук използваме пина AN0 за четене на стойността на ADC и пина PORTD за извеждане на PWM сигнали. Така че инициирайте ги като изходни щифтове и ги намалете, като използвате долните редове код.
/ ***** Конфигурация на порт за I / O ****** / TRISD = 0x00; // Инструктирайте MCU, че всички изводи на PORT D се извеждат PORTD = 0x00; // Инициализирайте всички щифтове на 0 / *********** ______ *********** /
Вътре в безкрайния цикъл while трябва да изчислим стойността на времето (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 ms, рутинната услуга за прекъсване на таймера ISR ще бъде извикана на всеки 0,1 ms. Вътре в рутинната услуга използваме променлива, наречена count, и я увеличаваме на всеки 0,1 ms. По този начин можем да следим времето. За да научите повече за прекъсванията в PIC микроконтролера, следвайте връзките
ако (TMR0IF == 1) // Знамето на таймера е задействано поради препълване на таймера -> зададено за препълване на всеки 0,1 ms { TMR0 = 248; // Зареждане на стойността на таймера TMR0IF = 0; // Изчистване на броя на флаговете за прекъсване на таймера ++; // Брой стъпки за всеки 0.1ms -> count / 10 ще даде стойност на броя в ms }
Накрая е време да превключите GPIO щифта въз основа на стойността на T_ON и T_OFF. Имаме променлива count, която отчита времето в мили секунди. Така че ние използваме тази променлива, за да проверим дали времето е по-малко от навреме , ако да, тогава поддържаме включен GPIO щифт, иначе го изключваме и го държим изключен, докато новият цикъл започне. Това може да стане чрез сравняването му с общото време на един ШИМ цикъл. Кодът, който прави същото, е показан по-долу
if (count <= (T_ON)) // Ако времето е по-малко от времето RD1 = 1; // Включване на GPIO else RD1 = 0; // В противен случай изключете GPIO, ако (count> = (T_TOTAL * 10)) // Дръжте го изключен, докато не започне нов цикъл count = 0;
Електрическа схема
Схемата на схемата за генериране на ШИМ с GPIO пин на микроконтролера PIC е наистина проста, просто захранвайте PIC с осцилатор и свържете потенциометъра към щифт AN0 и серво мотора към пин RD1, можем да използваме GPIO щифт за получаване на PWM сигнал, избрах RD1 просто случайно. И потенциометърът, и серво моторът се захранват от 5V, което се регулира от 7805, както е показано по-долу в схемата.
Симулация
За да симулирам проекта използвах моя софтуер на proteus. Изградете схемата, показана по-долу, и свържете кода с вашата симулация и го стартирайте. Трябва да получите PWM сигнал на RD1 GPIO щифт съгласно нашата програма и работният цикъл на PWM трябва да се контролира въз основа на позицията на потенциометъра. По-долу GIF показва как ШИМ сигналът и серво моторът реагират, когато стойността на ADC се промени чрез потенциометъра.
Хардуерна настройка за управление на сервомотора с помощта на PIC микроконтролер
Цялата ми хардуерна настройка е показана по-долу, за хората, които следват моите уроци, тази дъска трябва да изглежда позната, това е същата дъска, която използвах във всичките си уроци досега. Можете да се обърнете към мигащия светодиоден урок, ако се интересувате от това как да го изградя. В противен случай просто следвайте схемата по-горе и всички трябва да работят добре.
Качете програмата и променяйте потенциометъра и трябва да видите как серво променя позицията въз основа на позицията на потенциометъра. В пълно функциониране на проекта е показано във видеото даден в края на тази страница. Надявам се, че сте разбрали проекта и сте се насладили на изграждането, ако имате желания, не се колебайте да ги публикувате във форума и аз ще се опитам да отговоря.
Планирам да продължа този проект напред, като добавя опции за управление на множество серво мотори и по този начин изграждам роботизирана ръка от него, подобна на Arduino Robotic Arm, която вече изградихме. Така че до тогава ще се видим !!