- Co je signál PWM?
- Programování PIC pro generování PWM na pinech GPIO
- Kruhový diagram
- Simulace
- Nastavení hardwaru pro ovládání servomotoru pomocí mikrokontroléru PIC
Generování signálu PWM je důležitým nástrojem v každém arzenálu vestavěných inženýrů, jsou velmi užitečné pro mnoho aplikací, jako je ovládání polohy servomotoru, přepínání několika výkonových elektronických integrovaných obvodů v měničích / invertorech a dokonce i pro jednoduché ovládání jasu LED. V mikrokontrolérech PIC lze signály PWM generovat pomocí modulů Porovnat, Zachytit a PWM (CCP) nastavením požadovaných Registrů, již jsme se naučili, jak to udělat v tutoriálu PIC PWM. Existuje však jedna významná nevýhoda této metody.
PIC16F877A může generovat PWM signál pouze na pinech RC1 a RC2, pokud budeme používat moduly CCP. Mohli bychom se však setkat se situacemi, kdy potřebujeme více pinů, abychom měli funkčnost PWM. Například v mém případě chci ovládat 6 RC servomotorů pro svůj projekt robotického ramene, pro které je modul CCP beznadějný. V těchto scénářích můžeme naprogramovat piny GPIO na produkci signálů PWM pomocí časovacích modulů. Tímto způsobem můžeme generovat tolik signálů PWM s libovolným požadovaným kolíkem. Existují také další hardwarové hackery, jako je použití multiplexeru IC, ale proč investovat do hardwaru, když je to možné dosáhnout programováním. V tomto tutoriálu se tedy naučíme, jak převést pin PIC GPIO na pin PWM a abychom jej otestovali, simulujeme jej na proteus pomocí digitálního osciloskopu a takéovládat polohu servomotoru pomocí signálu PWM a měnit jeho pracovní cyklus změnou potenciometru.
Co je signál PWM?
Než se dostaneme do podrobností, pojďme si trochu oprášit to, co jsou PWM signály. Pulse Width Modulation (PWM) je digitální signál, který se nejčastěji používá v řídicích obvodech. Tento signál je nastaven na vysokou (5v) a nízkou (0v) v předdefinovaném čase a rychlosti. Čas, během kterého signál zůstane vysoký, se nazývá „čas zapnutí“ a čas, během kterého signál zůstane nízký, se nazývá „čas vypnutí“. Níže jsou popsány dva důležité parametry PWM:
Pracovní cyklus PWM
Procento času, ve kterém signál PWM zůstává VYSOKÝ (v čase), se nazývá pracovní cyklus. Pokud je signál vždy zapnutý, je ve 100% pracovním cyklu a pokud je vždy vypnutý, je to 0% pracovní cyklus.
Pracovní cyklus = čas zapnutí / (čas zapnutí + čas vypnutí)
Název proměnné |
Odkazuje na |
PWM_Frequency |
Frekvence signálu PWM |
T_TOTAL |
Celková doba potřebná pro jeden kompletní cyklus PWM |
TÓN |
V době signálu PWM |
HEJSEK |
Čas vypnutí signálu PWM |
Duty_cycle |
Pracovní cyklus signálu PWM |
Pojďme tedy na matematiku.
Jedná se o standardní vzorce, kde frekvence je jednoduše převrácená doba. Hodnotu frekvence musí určit a nastavit uživatel na základě svého požadavku na aplikaci.
T_TOTAL = (1 / PWM_Frequency)
Když uživatel změní hodnotu pracovního cyklu, náš program by měl podle toho automaticky upravit čas T_ON a čas T_OFF. Výše uvedené vzorce lze tedy použít k výpočtu T_ON na základě hodnoty Duty_Cycle a T_TOTAL.
T_ON = (Duty_Cycle * T_TOTAL) / 100
Protože celková doba signálu PWM pro jeden celý cyklus bude součtem doby zapnutí a vypnutí. Můžeme vypočítat čas vypnutí T_OFF, jak je uvedeno výše.
T_OFF = T_TOTAL - T_ON
S ohledem na tyto vzorce můžeme začít programovat mikrokontrolér PIC. Program zahrnuje modul časovače PIC a modul PIC ADC k vytvoření signálu PWM založeného na měnícím se pracovním cyklu podle hodnoty ADC z POT. Pokud jste v používání těchto modulů nováčkem, důrazně doporučujeme přečíst si příslušný návod kliknutím na hypertextové odkazy.
Programování PIC pro generování PWM na pinech GPIO
Kompletní program pro tento kurz lze nalézt na spodní části webové stránky, jako vždy. V této části pochopíme, jak je program ve skutečnosti napsán. Stejně jako všechny programy začneme nastavením bitů konfigurace. Použil jsem možnost zobrazení paměti, abych ji nastavil pro mě.
// KONFIGURACE #pragma config FOSC = HS // Bity pro výběr oscilátoru (HS oscilátor) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT deaktivováno) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT deaktivováno) #pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled) #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 je digitální I / O, K programování je nutné použít HV na MCLR) #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 (Write write off; veškerá programová paměť může být zapsána ovládáním EECON) #pragma config CP = OFF // Bit kódu ochrany kódu paměti programu (ochrana kódu vypnuta) // #pragma config příkazy by měly předcházet zahrnutí souboru projektu. // Použít enums projektu místo #define pro ZAPNUTO a VYPNUTO. #zahrnout
Pak zmíníme taktovací frekvenci použitou v hardwaru, kde můj hardware používá 20MHz krystal, můžete zadat hodnotu na základě vašeho hardwaru. Poté následuje hodnota frekvence signálu PWM. Vzhledem k tomu, že se zde snažím ovládat hobby RC servomotor, který vyžaduje PWM frekvenci 50 Hz, nastavil jsem jako hodnotu frekvence 0,05 KHz, můžete to také změnit podle požadavků vaší aplikace.
#define _XTAL_FREQ 20000000 #define PWM_Frequency 0,05 // v KHz (50Hz)
Nyní, když máme hodnotu Frequency, můžeme vypočítat T_TOTAL pomocí výše diskutovaných vzorců. Výsledek se vydělí deseti, aby se získala hodnota času v milisekundách. V mém případě bude hodnota T_TOTAL 2 milisekundy.
int T_TOTAL = (1 / PWM_Frequency) / 10; // výpočet celkového času z frekvence (v milisekundách)) // 2 ms
Následně inicializujeme moduly ADC pro čtení polohy potenciometru, jak je popsáno v našem kurzu ADC PIC. Dále máme rutinu přerušení služby, která bude vyvolána pokaždé, časovač přetéká, k tomu se vrátíme později, prozatím si zkontrolujte hlavní funkci.
Uvnitř hlavní funkce konfigurujeme modul časovače. Zde jsem nakonfiguroval modul časovače tak, aby přetékal každých 0,1 ms. Hodnotu času lze vypočítat pomocí níže uvedených vzorců
RegValue = 256 - ((Delay * Fosc) / (Prescalar * 4)) zpoždění v sekundách a Fosc v hz
V mém případě by pro zpoždění 0,0001 sekundy (0,1ms) s prescalar 64 a Fosc 20MHz měla být hodnota mého registru (TMR0) 248. Konfigurace tedy vypadá takto
/ ***** Konfigurace portu pro časovač ****** / OPTION_REG = 0b00000101; // Timer0 s externím kmitočtem a 64 jako prescalar // Také umožňuje PULL UPs TMR0 = 248; // Načte časovou hodnotu na 0,0001 s; delayValue může být mezi 0-256 pouze TMR0IE = 1; // Povolit bit přerušení časovače v registru PIE1 GIE = 1; // Povolit globální přerušení PEIE = 1; // Povolit přerušení periferie / *********** ______ *********** /
Pak musíme nastavit konfiguraci vstupu a výstupu. Zde používáme pin AN0 ke čtení hodnoty ADC a piny PORTD k výstupu signálů PWM. Iniciujte je jako výstupní piny a snižte je pomocí níže uvedených řádků kódu.
/ ***** Konfigurace portu pro I / O ****** / TRISD = 0x00; // Instruujte MCU, aby všechny piny na PORT D byly na výstupu PORTD = 0x00; // Inicializujte všechny piny na 0 / *********** ______ *********** /
Uvnitř nekonečné smyčky while musíme z pracovního cyklu vypočítat hodnotu on time (T_ON). Čas zapnutí a pracovní cyklus se liší v závislosti na poloze POT, takže to děláme opakovaně uvnitř smyčky while, jak je znázorněno níže. 0,0976 je hodnota, kterou je třeba vynásobit 1024, abychom dostali 100, a pro výpočet T_ON jsme ji vynásobili 10, abychom získali hodnotu v milisekundách.
while (1) { POT_val = (ADC_Read (0)); // Načtěte hodnotu POT pomocí ADC Duty_cycle = (POT_val * 0,0976); // Mapa 0 až 1024 až 0 až 100 T_ON = ((Duty_cycle * T_TOTAL) * 10/100); // Výpočet doby zapnutí pomocí jednotky vzorců v milisekundách __delay_ms (100); }
Protože je časovač nastaven na přetečení každých 0,1 ms, bude servisní rutina přerušení časovače ISR volána každých 0,1 ms. Uvnitř servisní rutiny používáme proměnnou nazvanou count a zvyšujeme ji každých 0,1 ms. Tímto způsobem můžeme sledovat čas. Chcete-li se dozvědět více o přerušeních v mikrokontroléru PIC, postupujte podle odkazů
if (TMR0IF == 1) // Byl spuštěn příznak časovače kvůli přetečení časovače -> nastaveno na přetečení každých 0,1 ms { TMR0 = 248; // Načtení časovače Hodnota TMR0IF = 0; // Vymazat počet příznaků přerušení časovače ++; // Počítání přírůstků každých 0,1 ms -> počet / 10 udá hodnotu počítání v ms }
Nakonec je čas přepnout pin GPIO na základě hodnoty T_ON a T_OFF. Máme proměnnou count, která sleduje čas v milisekundách. Tuto proměnnou tedy použijeme ke kontrole, zda je čas kratší než včas , pokud ano, pak ponecháme pin GPIO zapnutý, jinak jej vypneme a necháme vypnutý, dokud nezačne nový cyklus. Toho lze dosáhnout porovnáním s celkovou dobou jednoho cyklu PWM. Níže uvedený kód je stejný
if (count <= (T_ON)) // Pokud je čas kratší než včas RD1 = 1; // Zapnout GPIO else RD1 = 0; // Jinak vypněte GPIO if (count> = (T_TOTAL * 10)) // Ponechte to vypnuté, dokud nezačne nový cyklus count = 0;
Kruhový diagram
Schéma zapojení pro generování PWM s pinem GPIO mikrokontroléru PIC je opravdu jednoduché, stačí napájet PIC oscilátorem a připojit potenciometr na pin AN0 a servomotor na pin RD1, můžeme použít pin GPIO k získání signálu PWM, vybral jsem RD1 jen náhodně. Potenciometr i servomotor jsou napájeny 5 V, které jsou regulovány z 7805, jak je znázorněno níže ve schématu zapojení.
Simulace
K simulaci projektu jsem použil svůj software proteus. Sestavte obvod zobrazený níže, propojte kód se svou simulací a spusťte jej. Měli byste dostat signál PWM na pin RD1 GPIO podle našeho programu a pracovní cyklus PWM by měl být řízen na základě polohy potenciometru. Níže uvedený GIF ukazuje, jak signál PWM a servomotor reagují, když je hodnota ADC změněna potenciometrem.
Nastavení hardwaru pro ovládání servomotoru pomocí mikrokontroléru PIC
Moje kompletní nastavení hardwaru je zobrazeno níže, pro lidi, kteří sledují mé výukové programy, by tato deska měla vypadat povědomě, je to stejná deska, kterou jsem dosud používal ve všech svých cvičeních. Výukový program Blinking LED můžete odkázat, pokud vás zajímá, jak jej sestavuji. Jinak postupujte podle výše uvedeného schématu zapojení a vše by mělo fungovat dobře.
Nahrajte program a změňte potenciometr a měli byste vidět, jak servo mění polohu na základě polohy potenciometru. Úplné fungování projektu je uveden ve videu dané na konci této stránky. Doufám, že jste pochopili projekt a užívali jste si stavění, pokud máte dotazy, neváhejte je zveřejnit na fóru a já se pokusím co nejlépe odpovědět.
Plánuji tento projekt posunout vpřed přidáním možností pro ovládání více servomotorů a tím z něj postavit robotické rameno, podobně jako Arduino Robotic Arm, které jsme již postavili. Takže do té doby se uvidíme !!