- Ce este un semnal PWM?
- Programarea PIC pentru a genera PWM pe pinii GPIO
- Diagrama circuitului
- Simulare
- Configurare hardware pentru controlul servomotorului utilizând microcontrolerul PIC
Generarea semnalului PWM este un instrument vital în fiecare arsenal de ingineri încorporați, acestea sunt foarte utile pentru multe aplicații, cum ar fi controlul poziției servomotorului, comutarea câtorva IC-uri electronice de putere în convertoare / invertoare și chiar pentru un control simplu al luminozității LED-urilor. În microcontrolerele PIC, semnalele PWM pot fi generate utilizând modulele Comparare, Capturare și PWM (CCP) prin setarea registrelor necesare, am învățat deja cum să facem acest lucru în tutorialul PIC PWM. Dar există un dezavantaj considerabil al acestei metode.
PIC16F877A poate genera semnale PWM numai pe pinii RC1 și RC2, dacă folosim modulele PCC. Dar s-ar putea să întâlnim situații în care avem nevoie de mai mulți pini pentru a avea funcționalitate PWM. De exemplu, în cazul meu, vreau să controlez 6 servo-motoare RC pentru proiectul meu de braț robotizat pentru care modulul CCP este fără speranță. În aceste scenarii putem programa pinii GPIO pentru a produce semnale PWM folosind module de temporizare. Astfel putem genera cât mai multe semnale PWM cu orice pin necesar. Există, de asemenea, alte hack-uri hardware, cum ar fi utilizarea unui IC multiplexor, dar de ce să investim în hardware atunci când același lucru poate fi realizat prin programare. Deci, în acest tutorial vom învăța cum să convertim un pin PIC GPIO într-un pin PWM și, pentru a-l testa, îl vom simula pe proteus cu osciloscop digital și, de asemenea,controlați poziția servomotorului utilizând semnalul PWM și variați ciclul său de funcționare prin variația unui potențiometru.
Ce este un semnal PWM?
Înainte de a intra în detalii, permiteți-ne să analizăm puțin ce sunt semnale PWM. Modularea lățimii pulsului (PWM) este un semnal digital care este cel mai frecvent utilizat în circuitele de control. Acest semnal este setat ridicat (5v) și scăzut (0v) într-un timp și viteză predefiniți. Timpul în care semnalul rămâne ridicat se numește „timp activ”, iar timpul în care semnalul rămâne scăzut se numește „timp oprit”. Există doi parametri importanți pentru un PWM, așa cum este discutat mai jos:
Ciclul de funcționare al PWM
Procentul de timp în care semnalul PWM rămâne HIGH (la timp) este numit ciclu de funcționare. Dacă semnalul este întotdeauna PORNIT, este în ciclu de funcționare 100% și dacă este întotdeauna oprit, este ciclu de funcționare de 0%.
Ciclul de funcționare = Timp de pornire / (Timp de pornire + Timp de oprire)
Numele variabilei |
Se refera la |
PWM_Frequency |
Frecvența semnalului PWM |
T_TOTAL |
Timpul total necesar pentru un ciclu complet de PWM |
TONĂ |
La momentul semnalului PWM |
T_OFF |
Timp de oprire a semnalului PWM |
Duty_cycle |
Ciclul de funcționare al semnalului PWM |
Deci, acum, să facem calculele.
Aceasta este formulele standard în care frecvența este pur și simplu reciprocă a timpului. Valoarea frecvenței trebuie să fie stabilită și stabilită de utilizator în funcție de cerința aplicației sale.
T_TOTAL = (1 / PWM_Frequency)
Când utilizatorul modifică valoarea ciclului de funcționare, programul nostru ar trebui să regleze automat timpul T_ON și timpul T_OFF în funcție de aceasta. Deci, formulele de mai sus pot fi folosite pentru a calcula T_ON pe baza valorii Duty_Cycle și T_TOTAL.
T_ON = (Duty_Cycle * T_TOTAL) / 100
Deoarece timpul total al semnalului PWM pentru un ciclu complet va fi suma timpului de oprire și de oprire. Putem calcula timpul de oprire T_OFF așa cum se arată mai sus.
T_OFF = T_TOTAL - T_ON
Având în vedere aceste formule, putem începe programarea microcontrolerului PIC. Programul implică modulul PIC Timer și modulul PIC ADC pentru a crea un semnal PWM bazat pe un ciclu de funcționare diferit în funcție de valoarea ADC din POT. Dacă nu sunteți nou în utilizarea acestor module, atunci vă recomandăm să citiți tutorialul corespunzător făcând clic pe hyperlinkuri.
Programarea PIC pentru a genera PWM pe pinii GPIO
Programul complet pentru acest tutorial poate fi găsit în partea de jos a site-ului web ca întotdeauna. În această secțiune să înțelegem cum este scris programul. Ca toate programele, începem prin setarea biților de configurație. Am folosit opțiunea de vizualizare a memoriei pentru a o seta.
// CONFIG #pragma config FOSC = HS // Oscillator Selection bits (HS oscilator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT dezactivat) #pragma config BOREN = ON // Brown-out Reset Enable bit (BOR activat) #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is I / O digital, HV pe MCLR trebuie folosit pentru programare) #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Protection protection off; toată memoria programului poate fi scrisă de către controlul EECON) #pragma config CP = OFF // Programul Flash Memorie Bit de protecție cod (Protecție cod dezactivată) // Instrucțiunile #pragma config ar trebui să preceadă fișierul proiectului include. // Utilizați enumere de proiect în loc de #define pentru ON și OFF. #include
Apoi menționăm frecvența de ceas utilizată în hardware, aici hardware-ul meu folosește cristal de 20 MHz, puteți introduce valoarea pe baza hardware-ului dvs. Urmată de aceasta este valoarea frecvenței semnalului PWM. Din moment ce îmi doresc aici să controlez un servomotor RC hobby care necesită o frecvență PWM de 50Hz, am setat 0,05 KHz ca valoare de frecvență, puteți schimba acest lucru și în funcție de cerințele aplicației dumneavoastră.
#define _XTAL_FREQ 20000000 #define PWM_Frequency 0.05 // în KHz (50Hz)
Acum, că avem valoarea Frecvenței, putem calcula T_TOTAL folosind formulele discutate mai sus. Rezultatul este scufundat cu 10 pentru a obține valoarea timpului în mili secunde. În cazul meu, valoarea lui T_TOTAL va fi de 2 mili secunde.
int T_TOTAL = (1 / PWM_Frequency) / 10; // calculați timpul total din frecvență (în milisecunde)) // 2msec
Urmată de aceasta, inițializăm modulele ADC pentru citirea poziției potențiometrului așa cum este discutat în tutorialul nostru ADC PIC. Apoi avem rutina de servicii de întrerupere, care va fi apelată de fiecare dată, temporizatorul se revarsă, vom reveni la acest lucru mai târziu, deocamdată să verificăm funcția principală.
În interiorul funcției principale configurăm modulul timer. Aici am configurat modulul Timer pentru a revărsa pentru fiecare 0.1ms. Valoarea timpului poate fi calculată utilizând formulele de mai jos
RegValue = 256 - ((Întârziere * Fosc) / (Prescalar * 4)) întârziere în sec și Fosc în hz
În cazul meu pentru o întârziere de 0,0001 secunde (0,1 ms) cu prescalar de 64 și Fosc de 20MHz valoarea registrului meu (TMR0) ar trebui să fie 248. Deci, configurația arată astfel
/ ***** Port Configuration for Timer ****** / OPTION_REG = 0b00000101; // Timer0 cu frecvență externă și 64 ca prescalar // Activează și PULL UP TMR0 = 248; // Încărcați valoarea timpului pentru 0.0001s; delayValue poate fi între 0-256 numai TMR0IE = 1; // Activați bitul de întrerupere a temporizatorului în registrul PIE1 GIE = 1; // Activați Global Interrupt PEIE = 1; // Activați întreruperea periferică / *********** ______ *********** /
Apoi, trebuie să setăm configurația de intrare și ieșire. Aici folosim pinul AN0 pentru citirea valorii ADC și a pinilor PORTD pentru a transmite semnalele PWM. Deci, inițiați-le ca pini de ieșire și reduceți-le folosind liniile de cod de mai jos.
/ ***** Configurare port pentru I / O ****** / TRISD = 0x00; // Instruiți MCU-ul că toți pinii de pe PORT D au ieșire PORTD = 0x00; // Inițializați toți pinii la 0 / *********** ______ *********** /
În interiorul buclei de timp infinit, trebuie să calculăm valoarea timpului (T_ON) din ciclul de funcționare. La timp și datoria ciclu variază în funcție de poziția POT astfel încât să o facem în mod repetat, în interiorul în timp ce bucla așa cum se arată mai jos. 0.0976 este valoarea care trebuie să fie înmulțită cu 1024 pentru a obține 100 și pentru a calcula T_ON l-am înmulțit cu 10 pentru a obține valoare în milli secunde.
while (1) { POT_val = (ADC_Read (0)); // Citiți valoarea POT folosind ADC Duty_cycle = (POT_val * 0.0976); // Harta de la 0 la 1024 la 0 la 100 T_ON = ((Duty_cycle * T_TOTAL) * 10/100); // Calculați la timp folosind unitatea de formule în mili secunde __delay_ms (100); }
Deoarece temporizatorul este setat la un debit excesiv pentru fiecare 0,1 ms, ISR de rutină de întrerupere a temporizatorului va fi apelat pentru fiecare 0,1 ms. În cadrul rutinei de service folosim o variabilă numită count și o incrementăm pentru fiecare 0.1ms. Astfel putem urmări timpul. Pentru a afla mai multe despre întreruperile în microcontrolerul PIC, urmați linkurile
dacă (TMR0IF == 1) // Semnalizatorul temporizator a fost declanșat din cauza depășirii temporizatorului -> setat la depășire pentru fiecare 0,1 ms { TMR0 = 248; // Încărcați temporizatorul Valoare TMR0IF = 0; // Ștergeți numărul de semnal de întrerupere a temporizatorului ++; // Incremente de numărare pentru fiecare 0,1 ms -> numărare / 10 va da valoarea numărării în ms }
În cele din urmă, este timpul să comutați pinul GPIO pe baza valorilor T_ON și T_OFF. Avem variabila de numărare care ține evidența timpului în milli secunde. Deci, folosim acea variabilă pentru a verifica dacă timpul este mai mic decât la timp , dacă da, atunci ținem pinul GPIO pornit altfel îl oprim și îl ținem oprit până când începe noul ciclu. Acest lucru se poate face comparându-l cu timpul total al unui ciclu PWM. Codul pentru a face același lucru este prezentat mai jos
if (count <= (T_ON)) // Dacă timpul este mai mic decât la timp RD1 = 1; // Porniți GPIO else RD1 = 0; // Altfel opriți GPIO dacă (număr> = (T_TOTAL * 10)) // Păstrați-l oprit până când un nou ciclu începe numărătoarea = 0;
Diagrama circuitului
Diagrama circuitului pentru generarea PWM cu pinul GPIO al microcontrolerului PIC este foarte simplă, doar alimentați PIC cu oscilatorul și conectați potențiometrul la pinul AN0 și Servo Motor la pinul RD1, putem folosi pinul GPIO pentru a obține semnalul PWM, am selectat RD1 tocmai din întâmplare. Atât potențiometrul, cât și motorul servo sunt alimentate de 5V, care este reglat de la 7805, așa cum se arată mai jos în schema circuitului.
Simulare
Pentru a simula proiectul am folosit software-ul meu proteus. Construiți circuitul prezentat mai jos și conectați codul la simularea dvs. și rulați-l. Ar trebui să obțineți un semnal PWM pe pinul RD1 GPIO conform programului nostru, iar ciclul de funcționare al PWM ar trebui să fie controlat în funcție de poziția potențiometrului. GIF-ul de mai jos arată cum reacționează semnalul PWM și servomotorul atunci când valoarea ADC este schimbată prin potențiometru.
Configurare hardware pentru controlul servomotorului utilizând microcontrolerul PIC
Setarea completă a hardware-ului meu este prezentată mai jos, pentru persoanele care îmi urmăresc tutorialele, această placă ar trebui să pară familiară, este aceeași placă pe care am folosit-o în toate tutorialele mele până acum. Puteți consulta tutorialul LED intermitent dacă sunteți interesat să știți cum îl construiesc. În caz contrar, urmați schema de circuit de mai sus și toate ar trebui să funcționeze bine.
Încărcați programul și modificați potențiometrul și ar trebui să vedeți servo schimbând poziția pe baza poziției potențiometrului. Lucrarea completă a proiectului este prezentată în videoclipul prezentat la sfârșitul acestei pagini. Sper că ați înțeles proiectul și v-a plăcut să construiți, dacă aveți întrebări, nu ezitați să le postați pe forum și voi încerca tot posibilul să răspund.
Plănuiesc să duc acest proiect înainte prin adăugarea de opțiuni pentru a controla mai multe servo-motoare și construind astfel un braț robotizat din acesta, similar cu brațul robot Arduino pe care l-am construit deja. Deci până atunci ne vedem !!