- Wat is een PWM-signaal?
- PWM met PIC16F877A:
- PIC programmeren om PWM-signalen te genereren:
- Schema's en testen:
- Werken aan hardware:
Dit is onze 10e tutorial over het leren van PIC-microcontrollers met MPLAB en XC8. Tot nu toe hebben we veel basale tutorials behandeld, zoals LED knipperen met PIC, Timers in PIC, interfacing LCD, interfacing 7-segment, ADC met PIC enz. Als je een absolute beginner bent, bezoek dan de volledige lijst met PIC-tutorials hier en Begin met leren.
In deze tutorial zullen we leren hoe we PWM-signalen kunnen genereren met PIC PIC16F877A. Onze PIC MCU heeft een speciale module genaamd Compare Capture module (CCP) die kan worden gebruikt om PWM-signalen te genereren. Hier genereren we een PWM van 5 kHz met een variabele duty cycle van 0% tot 100%. Om de inschakelduur te variëren, gebruiken we een potentiometer, daarom wordt het aanbevolen om de ADC-zelfstudie te leren voordat u met PWM begint. De PWM-module gebruikt ook timers om de frequentie in te stellen, dus leer hier vooraf hoe u timers kunt gebruiken. Verder zullen we in deze tutorial een RC-circuit en een LED gebruiken om de PWM-waarden om te zetten naar analoge spanning en deze gebruiken voor het dimmen van het LED-licht.
Wat is een PWM-signaal?
Pulsbreedtemodulatie (PWM) is een digitaal signaal dat het meest wordt gebruikt in regelcircuits. Dit signaal wordt hoog (5v) en laag (0v) ingesteld in een vooraf gedefinieerde tijd en snelheid. De tijd dat het signaal hoog blijft, wordt de "aan-tijd" genoemd en de tijd dat het signaal laag blijft, wordt de "uit-tijd" genoemd. Er zijn twee belangrijke parameters voor een PWM, zoals hieronder besproken:
Inschakelduur van de PWM:
Het percentage van de tijd waarin het PWM-signaal HOOG (op tijd) blijft, wordt de duty-cycle genoemd. Als het signaal altijd AAN is, is het in 100% inschakelduur en als het altijd uit is, is het 0% inschakelduur.
Duty Cycle = Inschakeltijd / (Inschakeltijd + Uitschakeltijd)
Frequentie van een PWM:
De frequentie van een PWM-signaal bepaalt hoe snel een PWM een periode voltooit. Eén periode is volledig AAN en UIT van een PWM-signaal zoals weergegeven in de bovenstaande afbeelding. In onze tutorial zullen we een frequentie van 5KHz instellen.
PWM met PIC16F877A:
PWM-signalen kunnen worden gegenereerd in onze PIC-microcontroller met behulp van de CCP- module (Compare Capture PWM). De resolutie van ons PWM-signaal is 10-bit, dat wil zeggen voor een waarde van 0 is er een duty-cycle van 0% en voor een waarde van 1024 (2 ^ 10) is er een duty-cycle van 100%. Er zijn twee CCP-modules in onze PIC MCU (CCP1 en CCP2), dit betekent dat we twee PWM-signalen tegelijkertijd op twee verschillende pinnen (pin 17 en 16) kunnen genereren, in onze tutorial gebruiken we CCP1 om PWM-signalen op pin 17 te genereren.
De volgende registers worden gebruikt om PWM-signalen te genereren met behulp van onze PIC MCU:
- CCP1CON (CCP1-besturingsregister)
- T2CON (Timer 2 besturingsregister)
- PR2 (Timer 2 modules Period Register)
- CCPR1L (CCP Register 1 Low)
PIC programmeren om PWM-signalen te genereren:
In ons programma zullen we een analoge spanning van 0-5v van een potentiometer aflezen en deze met behulp van onze ADC-module naar 0-1024 toewijzen. Vervolgens genereren we een PWM-signaal met een frequentie van 5000Hz en variëren we de duty-cycle op basis van de analoge ingangsspanning. Dat wil zeggen 0-1024 wordt omgezet naar 0% -100% inschakelduur. Deze tutorial gaat ervan uit dat je al hebt geleerd ADC te gebruiken in PIC, zo niet, lees het dan vanaf hier, want we zullen de details erover overslaan in deze tutorial.
Dus zodra de configuratiebits zijn ingesteld en het programma is geschreven om een analoge waarde te lezen, kunnen we doorgaan met PWM.
De volgende stappen moeten worden genomen bij het configureren van de CCP-module voor PWM-werking:
- Stel de PWM-periode in door naar het PR2-register te schrijven.
- Stel de PWM-duty-cycle in door te schrijven naar het CCPR1L-register en CCP1CON <5: 4> bits.
- Maak van de CCP1-pin een output door de TRISC <2> -bit te wissen.
- Stel de TMR2-voorschaalwaarde in en schakel Timer2 in door naar T2CON te schrijven.
- Configureer de CCP1-module voor PWM-werking.
Er zijn twee belangrijke functies in dit programma om PWM-signalen te genereren. Een daarvan is de functie PWM_Initialize () die de registers initialiseert die nodig zijn om de PWM-module in te stellen en vervolgens de frequentie instelt waarop de PWM moet werken, de andere functie is de functie PWM_Duty () die de duty-cycle van het PWM-signaal in de vereiste registers.
PWM_Initialize () {PR2 = (_XTAL_FREQ / (PWM_freq * 4 * TMR2PRESCALE)) - 1; // De PR2-formules instellen met behulp van Datasheet // Maakt de PWM in 5KHZ CCP1M3 = 1; CCP1M2 = 1; // Configureer de CCP1-module T2CKPS0 = 1; T2CKPS1 = 0; TMR2ON = 1; // Configureer de timermodule TRISC2 = 0; // maak poortpin op C als uitvoer}
De bovenstaande functie is de PWM-initialisatiefunctie, in deze functie is de CCP1-module ingesteld om PWM te gebruiken door de bit CCP1M3 en CCP1M2 zo hoog te maken.
De voorschrijver van de timermodule wordt ingesteld door de bit T2CKPS0 zo hoog te maken en T2CKPS1 zo laag dat de bit TMR2ON wordt ingesteld om de timer te starten.
Nu moeten we de frequentie van het PWM-signaal instellen. De waarde van de frequentie moet naar het PR2-register worden geschreven. De gewenste frequentie kan worden ingesteld met behulp van onderstaande formules
PWM-periode = * 4 * TOSC * (TMR2-voorschaalwaarde)
Het herschikken van deze formules om PR2 te krijgen, geeft
PR2 = (Period / (4 * Tosc * TMR2 Prescale)) - 1
We weten dat Period = (1 / PWM_freq) en Tosc = (1 / _XTAL_FREQ). Daarom…..
PR2 = (_XTAL_FREQ / (PWM_freq * 4 * TMR2PRESCALE)) - 1;
Als de frequentie eenmaal is ingesteld, hoeft deze functie niet opnieuw te worden aangeroepen, tenzij en totdat we de frequentie opnieuw moeten wijzigen. In onze tutorial heb ik PWM_freq = 5000 toegewezen ; zodat we een werkfrequentie van 5 kHz voor ons PWM-signaal kunnen krijgen.
Laten we nu de duty-cycle van de PWM instellen met behulp van de onderstaande functie
PWM_Duty (unsigned int duty) {if (duty <1023) {duty = ((float) duty / 1023) * (_ XTAL_FREQ / (PWM_freq * TMR2PRESCALE)); // Over verminderen // duty = (((float) duty / 1023) * (1 / PWM_freq)) / ((1 / _XTAL_FREQ) * TMR2PRESCALE); CCP1X = plicht & 1; // Sla het eerste bit CCP1Y = duty & 2; // Bewaar de 0e bit CCPR1L = duty >> 2; // Bewaar de resterende 8 bit}}
Ons PWM-signaal heeft een resolutie van 10 bits en daarom kan deze waarde niet in een enkel register worden opgeslagen, aangezien onze PIC slechts 8-bits datalijnen heeft. We moeten dus twee andere bits van CCP1CON <5: 4> (CCP1X en CCP1Y) gebruiken om de laatste twee LSB's op te slaan en vervolgens de resterende 8 bits in het CCPR1L-register.
De PWM-duty cycle-tijd kan worden berekend met behulp van de onderstaande formules:
PWM Duty Cycle = (CCPRIL: CCP1CON <5: 4>) * Tosc * (TMR2 Voorschaalwaarde)
Het herschikken van deze formules om de waarde van CCPR1L en CCP1CON te krijgen, geeft:
CCPRIL: CCP1Con <5: 4> = PWM Duty Cycle / (Tosc * TMR2 Prescale Value)
De waarde van onze ADC is 0-1024, we hebben deze nodig in 0% -100%, dus PWM Duty Cycle = duty / 1023. Om deze duty cycle om te rekenen naar een tijdsperiode moeten we deze vermenigvuldigen met de periode (1 / PWM_freq)
We weten ook dat Tosc = (1 / PWM_freq), dus..
Duty = (((float) duty / 1023) * (1 / PWM_freq)) / ((1 / _XTAL_FREQ) * TMR2PRESCALE);
Het oplossen van de bovenstaande vergelijking geeft ons:
Duty = ((float) duty / 1023) * (_XTAL_FREQ / (PWM_freq * TMR2PRESCALE));
U kunt het volledige programma bekijken in de sectie Code hieronder, samen met de gedetailleerde video.
Schema's en testen:
Laten we zoals gewoonlijk de uitvoer verifiëren met behulp van Proteus-simulatie. Het schakelschema wordt hieronder weergegeven.
Sluit een potentiometer aan op de 7e pin om een spanning van 0-5 in te voeren. CCP1-module is met pin 17 (RC2), hier wordt de PWM gegenereerd die kan worden geverifieerd met de digitale oscilloscoop. Om dit om te zetten in een variabele spanning hebben we een RC-filter en een LED gebruikt om de output te verifiëren zonder scope.
Wat is een RC-filter?
Een RC-filter of een laagdoorlaatfilter is een eenvoudig circuit met twee passieve elementen namelijk de weerstand en de condensator. Deze twee componenten worden gebruikt om de frequentie van ons PWM-signaal te filteren en er een variabele gelijkspanning van te maken.
Als we het circuit onderzoeken en een variabele spanning wordt toegepast op de ingang van R, begint de condensator C op te laden. Nu gebaseerd op de waarde van de condensator, zal de condensator enige tijd nodig hebben om volledig opgeladen te zijn, eenmaal opgeladen blokkeert hij de gelijkstroom (onthoud dat condensatoren gelijkstroom blokkeren maar AC toestaan), vandaar dat de gelijkstroom-ingangsspanning over de uitgang zal verschijnen. Het hoogfrequente PWM (AC-signaal) wordt geaard via de condensator. Zo wordt een zuivere DC verkregen over de condensator. Een waarde van 1000 Ohm en 1uf bleek geschikt te zijn voor dit project. Het berekenen van de waarden van R en C omvat circuitanalyse met behulp van de overdrachtsfunctie, die buiten het bestek van deze zelfstudie valt.
De output van het programma kan worden geverifieerd met behulp van de digitale oscilloscoop zoals hieronder weergegeven, de potentiometer variëren en de duty-cycle van de PWM moet veranderen. We kunnen ook de uitgangsspanning van het RC-circuit zien met behulp van de voltmeter. Als alles naar verwachting werkt, kunnen we doorgaan met onze hardware. Bekijk de video aan het einde verder voor het volledige proces.
Werken aan hardware:
De hardware-installatie van het project is heel eenvoudig, we gaan gewoon ons PIC Perf-bord hergebruiken dat hieronder wordt weergegeven.
We hebben ook een potentiometer nodig om de analoge spanning in te voeren, ik heb enkele vrouwelijke einddraden aan mijn pot bevestigd (zie hieronder) zodat we ze rechtstreeks op het PIC Perf-bord kunnen aansluiten.
Eindelijk naar de uitgang we een RC-circuit en een LED moeten controleren om te zien hoe het PWM signaal werken, ik heb gewoon een kleine perf board gebruikt en gesoldeerd de RC circuit en de LED (om de helderheid controle) aan zoals hieronder afgebeeld
We kunnen eenvoudige vrouw-naar-vrouw-verbindingsdraden gebruiken en deze aansluiten volgens het hierboven getoonde schema. Zodra de verbinding is gemaakt, uploadt u het programma naar de PIC met behulp van onze pickit3 en zou u een variabele spanning moeten kunnen krijgen op basis van de invoer van uw potentiometer. De variabele uitgang wordt hier gebruikt om de helderheid van de LED te regelen.
Ik heb mijn multimeter gebruikt om de variabele uitgangen te meten, we kunnen ook zien dat de helderheid van de LED verandert voor verschillende spanningsniveaus.
Dat is het wat we hebben geprogrammeerd om de analoge spanning van de POT te lezen en om te zetten in PWM-signalen die op hun beurt zijn omgezet in variabele spanning met behulp van een RC-filter en het resultaat wordt geverifieerd met behulp van onze hardware. Als je twijfelt of ergens vastloopt, gebruik dan de commentaarsectie hieronder, we helpen je graag verder. Het volledige werk is aan het werk in de video.
Bekijk ook onze andere PWM-tutorials over andere microcontrollers:
- Raspberry Pi PWM-zelfstudie
- PWM met Arduino Due
- Arduino-gebaseerde LED-dimmer met PWM
- Power LED Dimmer met ATmega32 Microcontroller