- Kaj je signal PWM?
- Programiranje PIC za generiranje PWM na GPIO zatičih
- Shema vezja
- Simulacija
- Nastavitev strojne opreme za nadzor servo motorja s pomočjo mikrokrmilnika PIC
Ustvarjanje PWM signala je bistveno orodje v vsakem vgrajenem arzenalu inženirjev. Zelo priročni so za številne aplikacije, kot so nadzor položaja servo motorja, preklapljanje nekaj močnostnih elektronskih integriranih vezij v pretvornikih / pretvornikih in celo za preprost nadzor svetlosti LED. V mikrokrmilnikih PIC lahko PWM signale generiramo z uporabo modulov Primerjava, zajemanje in PWM (CCP) z nastavitvijo zahtevanih registrov. To smo že izvedeli v vaji PIC PWM. Toda pri tej metodi obstaja ena pomembna pomanjkljivost.
PIC16F877A lahko ustvarjajo PWM signale samo na nožici RC1 in RC2, če bomo uporabili module CCP. Lahko pa naletimo na situacije, ko potrebujemo več nožic, da imamo funkcionalnost PWM. Na primer, v mojem primeru želim nadzorovati 6 RC servo motorjev za svoj projekt robotske roke, pri katerem je modul CCP brezupen. V teh scenarijih lahko programiramo zatiče GPIO za izdelavo signalov PWM z uporabo časovnih modulov. Na ta način lahko s katerim koli zahtevanim zatičem ustvarimo čim več PWM signalov. Obstajajo tudi drugi vdori v strojno opremo, kot je uporaba IC za multipleksor, toda zakaj bi vlagali v strojno opremo, če pa je to mogoče doseči s programiranjem. Torej, v tej vadnici bomo izvedeli, kako pretvoriti pin PIC GPIO v pin PWM in ga preizkusili, simulirali na proteusu z digitalnim osciloskopom in tudinadzorujete položaj servo motorja z uporabo signala PWM in spreminjate njegov obratovalni cikel s spreminjanjem potenciometra.
Kaj je signal PWM?
Preden se spustimo v podrobnosti, si nekoliko razjasnimo, kaj so PWM signali. Modulacija širine impulza (PWM) je digitalni signal, ki se najpogosteje uporablja v krmilnih vezjih. Ta signal je nastavljen na visoko (5v) in nizko (0v) v vnaprej določenem času in hitrosti. Čas, v katerem signal ostane visok, se imenuje "on time", čas, v katerem signal ostane nizek, pa "off time". Kot sta opisana spodaj, obstajata dva pomembna parametra za PWM:
Delovni cikel PWM
Odstotek časa, v katerem signal PWM ostane VISOK (pravočasno), se imenuje delovni cikel. Če je signal vedno vklopljen, je v 100% obratovalnem ciklu in če je vedno izklopljen, je 0% obratovalni cikel.
Delovni cikel = čas vklopa / (čas vklopa + čas izklopa)
Ime spremenljivke |
Se nanaša na |
PWM_frekvenca |
Pogostost signala PWM |
SKUPAJ |
Skupni čas, potreben za en celoten cikel PWM |
T_ON |
Ob času PWM signala |
T_OFF |
Čas izklopa signala PWM |
Delovni_cikel |
Delovni cikel signala PWM |
Torej, zdaj izračunajmo.
To so standardne formule, pri katerih je frekvenca preprosto recipročna vrednost časa. Vrednost frekvence mora uporabnik določiti in nastaviti na podlagi njegove zahteve.
T_TOTAL = (1 / frekvenca PWM)
Ko uporabnik spremeni vrednost delovnega cikla, mora naš program samodejno prilagoditi čas T_ON in čas T_OFF glede na to. Tako lahko zgornje formule uporabimo za izračun T_ON na podlagi vrednosti Duty_Cycle in T_TOTAL.
T_ON = (Duty_Cycle * T_TOTAL) / 100
Ker bo skupni čas signala PWM za en celoten cikel vsota časa in izklopa. Mi lahko izračunamo časovno off T_OFF kot je prikazano zgoraj.
T_OFF = T_TOTAL - T_ON
S temi formulami v mislih lahko začnemo s programiranjem mikrokrmilnika PIC. Program vključuje modul PIC timer in modul PIC ADC, da ustvari signal PWM, ki temelji na različnem delovnem ciklu v skladu z vrednostjo ADC iz POT. Če teh modulov ne uporabljate, je priporočljivo, da preberete ustrezno vadnico s klikom na hiperpovezave.
Programiranje PIC za generiranje PWM na GPIO zatičih
Celoten program za tem tečaju je mogoče najti na dnu spletne strani, kot vedno. V tem razdelku naj razumemo, kako je program dejansko napisan. Kot vsi programi tudi mi začnemo z nastavitvijo bitov konfiguracije. Uporabil sem možnost pogledov pomnilnika, da sem jo nastavil namesto mene.
// CONFIG #pragma config FOSC = HS // Bit za izbiro oscilatorja (HS oscilator) #pragma config WDTE = OFF // Bit Watchg Enable bit (WDT disabled) #pragma config PWRTE = OFF // Bit za omogočanje časovnika vklopa (PWRT onemogočeno) #pragma config BOREN = ON // bit za omogočanje ponastavitve Brown-out (omogočen BOR) #pragma config LVP = OFF // bit za omogočanje nizkonapetostnega (enojnega napajanja) serijskega programiranja v krogu (RB3 je digitalni I / O, Za programiranje je treba uporabiti HV na MCLR) #pragma config CPD = OFF // Bit zaščite pomnilniške kode EEPROM podatkov (zaščita kode EEPROM podatkov izključena) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write off off; ves programski pomnilnik se lahko zapiše s pomočjo EECON) #pragma config CP = OFF // Bit programa za zaščito pomnilniške kode Flash programa (zaščita kode izklopljena) // izjave o konfiguraciji #pragma morajo biti pred vključeno datoteko projekta. // Za vključevanje in izklapljanje namesto #define uporabite namesto #define. #include
Nato omenimo taktno frekvenco, ki se uporablja v strojni opremi. Tu moja strojna oprema uporablja kristal 20MHz, vrednost lahko vnesete glede na vašo strojno opremo. Sledi vrednost frekvence signala PWM. Ker je moj cilj tukaj nadzorovati hobi RC servo motor, ki zahteva frekvenco PWM 50Hz, sem kot vrednost frekvence določil 0,05KHz, kar lahko spremenite tudi glede na vaše zahteve.
#define _XTAL_FREQ 20000000 #define PWM_Frequency 0,05 // v KHz (50Hz)
Zdaj, ko imamo vrednost Frekvence, lahko izračunamo T_TOTAL z uporabo zgoraj opisanih formul. Rezultat se potopi za 10, da dobimo vrednost časa v mili sekundah. V mojem primeru bo vrednost T_TOTAL 2 mili sekundi.
int T_TOTAL = (1 / frekvenca PWM) / 10; // izračun skupnega časa iz frekvence (v milli sek)) // 2msec
Sledi temu, inicializiramo module ADC za branje položaja potenciometra, kot je razloženo v naši vadnici ADC PIC. Nato imamo servisno rutino Interrupt, ki jo bomo poklicali vsakič, čas se bo prelival, na to se bomo vrnili kasneje, za zdaj preverimo glavno funkcijo.
Znotraj glavne funkcije konfiguriramo modul časovnika. Tukaj sem konfiguriral modul Timer za prelivanje za vsakih 0,1 ms. Vrednost časa lahko izračunamo s spodnjimi formulami
RegValue = 256 - ((Zakasnitev * Fosc) / (Prescalar * 4)) zakasnitev v sekundah in Fosc v hz
V mojem primeru za zakasnitev 0,0001 sekunde (0,1 ms) s preskalarjem 64 in Fosc 20MHz mora biti vrednost mojega registra (TMR0) 248. Torej je konfiguracija videti tako
/ ***** Konfiguracija vrat za časovnik ****** / OPTION_REG = 0b00000101; // Timer0 z zunanjo frekvenco in 64 kot predkalarjem // Omogoča tudi PULL UPs TMR0 = 248; // Naloži časovno vrednost za 0,0001s; delayValue je lahko med 0-256 samo TMR0IE = 1; // Omogoči bit prekinitve časovnika v registru PIE1 GIE = 1; // Omogoči globalno prekinitev PEIE = 1; // Omogoči periferno prekinitev / *********** ______ *********** /
Nato moramo nastaviti vhodno in izhodno konfiguracijo. Tu uporabljamo pin AN0 za branje vrednosti ADC in zatiči PORTD za izhod signalov PWM. Zato jih sprožite kot izhodne nožice in jih z uporabo spodnjih vrstic kode znižajte.
/ ***** Konfiguracija vrat za V / I ****** / TRISD = 0x00; // MCU naročite, da so vsi zatiči na PORT D izhodni PORTD = 0x00; // Inicializirajte vse nožice na 0 / *********** ______ *********** /
Znotraj neskončne zanke while moramo iz delovnega cikla izračunati vrednost časa (T_ON). Čas vklopa in obratovalni cikel se razlikujeta glede na položaj POT-a, zato to ponavljamo večkrat v zanki while, kot je prikazano spodaj. 0,0976 je vrednost, ki jo je treba pomnožiti z 1024, da dobimo 100, za izračun T_ON pa smo jo pomnožili z 10, da dobimo vrednost v mili sekundah.
medtem ko (1) { POT_val = (ADC_Read (0)); // odčitamo vrednost POT z uporabo ADC Duty_cycle = (POT_val * 0.0976); // Zemljevid 0 do 1024 do 0 do 100 T_ON = ((Duty_cycle * T_TOTAL) * 10/100); // Izračunaj čas uporabe z uporabo enote formul v mili sekundah __delay_ms (100); }
Ker je časovnik nastavljen na pretok za vsakih 0,1 ms, bo za vsakih 0,1 ms poklicana rutina ISR storitve prekinitve časovnika. V servisni rutini uporabljamo spremenljivko, imenovano count, in jo povečujemo za vsakih 0,1 ms. Tako lahko spremljamo čas. Če želite izvedeti več o prekinitvah v mikrokrmilniku PIC, sledite povezavam
če je (TMR0IF == 1) // zastavica časovnika sprožena zaradi prelivanja časovnika -> nastavljena na preliv za vsakih 0,1 ms { TMR0 = 248; // Naloži časovnik Vrednost TMR0IF = 0; // Počisti število zastavic prekinitve časovnika ++; // Štetje prirastkov za vsakih 0,1 ms -> count / 10 bo dalo vrednost štetja v ms }
Končno je čas, da preklopite zatič GPIO glede na vrednost T_ON in T_OFF. Imamo spremenljivko štetja, ki beleži čas v mili sekundah. Torej s to spremenljivko preverimo, ali je čas krajši od pravočasnega , če je odgovor pritrdilen, ostane GPIO vklopljen, sicer ga izklopimo in izklopimo, dokler se nov cikel ne začne. To lahko storite tako, da ga primerjate s celotnim časom enega cikla PWM. Koda, ki stori enako, je prikazana spodaj
if (count <= (T_ON)) // Če je čas krajši kot pravočasno RD1 = 1; // Vklop GPIO sicer RD1 = 0; // V nasprotnem primeru izklopite GPIO, če (count> = (T_TOTAL * 10)) // Naj bo izklopljen, dokler se nov cikel ne začne count = 0;
Shema vezja
Shema vezja za generiranje PWM z GPIO zatičem mikrokrmilnika PIC je res preprosta, samo napajajte PIC z oscilatorjem in potenciometer priključite na pin AN0 in servo motor na pin RD1, lahko uporabimo GPIO pin, da dobimo signal PWM, izbral sem RD1 čisto naključno. Tako potenciometer kot servo motor napajata 5V, ki je reguliran od 7805, kot je prikazano spodaj v vezju.
Simulacija
Za simulacijo projekta sem uporabil svojo programsko opremo proteus. Zgradite spodnje vezje, povežite kodo s svojo simulacijo in jo zaženite. Na pin RD1 GPIO bi morali dobiti signal PWM v skladu z našim programom, delovni cikel PWM pa bi moral biti nadzorovan glede na položaj potenciometra. Spodnji GIF prikazuje, kako se signal PWM in servo motor odzivata, ko se vrednost ADC spremeni s pomočjo potenciometra.
Nastavitev strojne opreme za nadzor servo motorja s pomočjo mikrokrmilnika PIC
Moja celotna nastavitev strojne opreme je prikazana spodaj, za ljudi, ki sledijo mojim vajam, naj bi bila ta plošča videti znana, to je ista plošča, ki sem jo uporabljal v vseh svojih vajah do zdaj. Če vas zanima, kako ga sestavim, si lahko ogledate vadnico za utripajoče LED. V nasprotnem primeru preprosto sledite zgornji shemi in vse bi moralo dobro delovati.
Naložite program in spremenite potenciometer in videli bi, kako servo spreminja položaj glede na položaj potenciometra. Popolno delovanje projekta je prikazan v videu dani na koncu te strani. Upam, da ste projekt razumeli in ste uživali pri gradnji, če jih imate, jih lahko objavite na forumu in se bom potrudil, da odgovorim.
Ta projekt nameravam nadaljevati z dodajanjem možnosti za upravljanje več servo motorjev in tako iz njega zgraditi robotsko roko, podobno kot smo že izdelali robotsko roko Arduino. Torej do takrat se vidimo !!