- Was ist ein PWM-Signal?
- Programmieren von PIC zum Generieren von PWM auf GPIO-Pins
- Schaltplan
- Simulation
- Hardware-Setup zur Steuerung des Servomotors mit dem PIC-Mikrocontroller
Die PWM-Signalerzeugung ist ein wichtiges Werkzeug in jedem Arsenal eingebetteter Ingenieure. Sie ist sehr praktisch für viele Anwendungen wie die Steuerung der Position des Servomotors, das Schalten weniger leistungselektronischer ICs in Wandlern / Wechselrichtern und sogar für eine einfache LED-Helligkeitssteuerung. In PIC-Mikrocontrollern können PWM-Signale mithilfe der Compare-, Capture- und PWM- Module (CCP) durch Einstellen der erforderlichen Register generiert werden. Dies haben wir bereits im PIC-PWM-Lernprogramm gelernt. Diese Methode weist jedoch einen erheblichen Nachteil auf.
Der PIC16F877A kann PWM-Signale nur an den Pins RC1 und RC2 erzeugen, wenn wir die CCP-Module verwenden. Es kann jedoch vorkommen, dass wir mehr Pins benötigen, um über PWM-Funktionen zu verfügen. In meinem Fall möchte ich beispielsweise 6 RC-Servomotoren für mein Roboterarmprojekt steuern, für das das CCP-Modul hoffnungslos ist. In diesen Szenarien können wir die GPIO-Pins so programmieren, dass sie mithilfe von Timer-Modulen PWM-Signale erzeugen. Auf diese Weise können wir mit jedem erforderlichen Pin so viele PWM-Signale erzeugen. Es gibt auch andere Hardware-Hacks wie die Verwendung eines Multiplexer-ICs, aber warum in Hardware investieren, wenn dies durch Programmierung erreicht werden kann? In diesem Tutorial lernen wir, wie man einen PIC GPIO-Pin in einen PWM-Pin umwandelt und um ihn zu testen, simulieren wir ihn auf einem Proteus mit einem digitalen Oszilloskop und auchSteuern Sie die Position des Servomotors mithilfe des PWM-Signals und variieren Sie dessen Arbeitszyklus durch Variieren eines Potentiometers.
Was ist ein PWM-Signal?
Bevor wir auf die Details eingehen, lassen Sie uns die PWM-Signale etwas auffrischen. Die Pulsweitenmodulation (PWM) ist ein digitales Signal, das am häufigsten in Steuerschaltungen verwendet wird. Dieses Signal wird in einer vordefinierten Zeit und Geschwindigkeit auf hoch (5 V) und niedrig (0 V) gesetzt. Die Zeit, während der das Signal hoch bleibt, wird als "Einschaltzeit" bezeichnet, und die Zeit, während der das Signal niedrig bleibt, wird als "Ausschaltzeit" bezeichnet. Es gibt zwei wichtige Parameter für eine PWM, wie unten erläutert:
Arbeitszyklus der PWM
Der Prozentsatz der Zeit, in der das PWM-Signal HIGH (Einschaltzeit) bleibt, wird als Arbeitszyklus bezeichnet. Wenn das Signal immer eingeschaltet ist, befindet es sich in einem Tastverhältnis von 100% und wenn es immer ausgeschaltet ist, ist es ein Tastverhältnis von 0%.
Arbeitszyklus = Einschaltzeit / (Einschaltzeit + Ausschaltzeit)
Variablennamen |
Bezieht sich auf |
PWM_Frequency |
Frequenz des PWM-Signals |
T_TOTAL |
Gesamtzeit für einen vollständigen PWM-Zyklus |
TONNE |
Einschaltzeit des PWM-Signals |
T_OFF |
Ausschaltzeit des PWM-Signals |
Auslastungsgrad |
Arbeitszyklus des PWM-Signals |
Also jetzt lass uns rechnen.
Dies sind die Standardformeln, bei denen die Frequenz einfach der Kehrwert der Zeit ist. Der Wert der Frequenz muss vom Benutzer basierend auf seiner / ihrer Anwendungsanforderung festgelegt und festgelegt werden.
T_TOTAL = (1 / PWM_Frequency)
Wenn der Benutzer den Arbeitszykluswert ändert, sollte unser Programm die T_ON-Zeit und die T_OFF-Zeit automatisch entsprechend anpassen. Die obigen Formeln können also verwendet werden, um T_ON basierend auf dem Wert von Duty_Cycle und T_TOTAL zu berechnen.
T_ON = (Duty_Cycle * T_TOTAL) / 100
Da die Gesamtzeit des PWM-Signals für einen vollen Zyklus die Summe aus Einschaltzeit und Ausschaltzeit ist. Wir können die Ausschaltzeit T_OFF wie oben gezeigt berechnen.
T_OFF = T_TOTAL - T_ON
Unter Berücksichtigung dieser Formeln können wir mit der Programmierung des PIC-Mikrocontrollers beginnen. Das Programm umfasst das PIC-Timer-Modul und das PIC-ADC-Modul, um ein PWM-Signal mit einem variierenden Arbeitszyklus gemäß dem ADC-Wert aus dem POT zu erzeugen. Wenn Sie mit diesen Modulen noch nicht vertraut sind, wird dringend empfohlen, das entsprechende Tutorial zu lesen, indem Sie auf die Hyperlinks klicken.
Programmieren von PIC zum Generieren von PWM auf GPIO-Pins
Das vollständige Programm für dieses Tutorial finden Sie wie immer am Ende der Website. In diesem Abschnitt wollen wir verstehen, wie das Programm tatsächlich geschrieben ist. Wie bei allen Programmen setzen wir zunächst die Konfigurationsbits. Ich habe die Option Speicheransichten verwendet, um sie für mich festzulegen.
// CONFIG #pragma config FOSC = HS // Oszillatorauswahlbits (HS-Oszillator) #pragma config WDTE = OFF // Watchdog-Timer-Aktivierungsbit (WDT deaktiviert) #pragma config PWRTE = OFF // Einschalt-Timer-Aktivierungsbit (PWRT) deaktiviert) #pragma Config BOREN = ON // Brown-out - Reset - Bit aktivieren (BOR aktiviert) #pragma Config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Freigabebit (RB3 ist digital I / O, HV auf MCLR muss für die Programmierung verwendet werden) #pragma config CPD = OFF // Daten-EEPROM-Speichercode- Schutzbit (Daten-EEPROM-Code-Schutz aus) #pragma config WRT = AUS // Flash-Programmspeicher Schreibaktivierungsbits (Schreibschutz aus; Der gesamte Programmspeicher kann von der EECON-Steuerung beschrieben werden. #pragma config CP = OFF // Code-Schutzbit für Flash-Programmspeicher ( Codeschutz aus) // #pragma config-Anweisungen sollten vor Projektdatei-Includes stehen. // Verwenden Sie Projektaufzählungen anstelle von #define für ON und OFF. #einschließen
Dann erwähnen wir die in der Hardware verwendete Taktfrequenz. Hier verwendet meine Hardware 20-MHz-Quarz. Sie können den Wert basierend auf Ihrer Hardware eingeben. Darauf folgt der Frequenzwert des PWM-Signals. Da ich hier einen Hobby-RC-Servomotor steuern möchte, der eine PWM-Frequenz von 50 Hz benötigt, habe ich 0,05 KHz als Frequenzwert festgelegt. Sie können dies auch basierend auf Ihren Anwendungsanforderungen ändern.
#define _XTAL_FREQ 20000000 #define PWM_Frequency 0.05 // in KHz (50Hz)
Nachdem wir nun den Wert der Frequenz haben, können wir das T_TOTAL unter Verwendung der oben diskutierten Formeln berechnen. Das Ergebnis wird um 10 getaucht, um den Zeitwert in Millisekunden zu erhalten. In meinem Fall beträgt der Wert von T_TOTAL 2 Millisekunden.
int T_TOTAL = (1 / PWM_Frequency) / 10; // Gesamtzeit aus Frequenz berechnen (in Millisekunden) // 2 ms
Anschließend initialisieren wir die ADC-Module zum Lesen der Position des Potentiometers, wie in unserem ADC PIC-Tutorial beschrieben. Als nächstes haben wir die Interrupt-Serviceroutine, die jedes Mal aufgerufen wird. Der Timer läuft über. Wir werden später darauf zurückkommen. Lassen Sie uns nun die Hauptfunktion überprüfen.
Innerhalb der Hauptfunktion konfigurieren wir das Timer-Modul. Hier habe ich das Timer-Modul so konfiguriert, dass es alle 0,1 ms überläuft. Der Wert für die Zeit kann unter Verwendung der folgenden Formeln berechnet werden
Regvalue = 256 - ((Delay * Fosc) / (Prescalar * 4)) Verzögerung in sec und Fosc in hz
In meinem Fall sollte für eine Verzögerung von 0,0001 Sekunden (0,1 ms) mit einem Prescalar von 64 und einem Fosc von 20 MHz der Wert meines Registers (TMR0) 248 betragen. Die Konfiguration sieht also so aus
/ ***** Portkonfiguration für Timer ****** / OPTION_REG = 0b00000101; // Timer0 mit externer Frequenz und 64 als Prescalar // Aktiviert auch PULL-UPs TMR0 = 248; // Lade den Zeitwert für 0,0001s; delayValue kann nur zwischen 0 und 256 liegen. TMR0IE = 1; // Timer-Interrupt-Bit im PIE1-Register aktivieren GIE = 1; // Global Interrupt aktivieren PEIE = 1; // Peripheral Interrupt aktivieren / *********** ______ *********** /
Dann müssen wir die Input- und Output-Konfiguration einstellen. Hier verwenden wir den AN0-Pin zum Lesen des ADC-Werts und die PORTD-Pins zum Ausgeben der PWM-Signale. Initiieren Sie sie also als Ausgangspins und machen Sie sie mithilfe der folgenden Codezeilen niedrig.
/ ***** Portkonfiguration für E / A ****** / TRISD = 0x00; // Weisen Sie die MCU an, dass alle Pins an PORT D ausgegeben werden. PORTD = 0x00; // Initialisiere alle Pins auf 0 / *********** ______ *********** /
Innerhalb der unendlichen während Schleife, haben wir den Wert auf Zeit (T_ON) aus dem Arbeitszyklus zu berechnen. Der auf der Zeit und Duty - Zyklus in Abhängigkeit von der Position des POT basiert, so dass wir sie wiederholt innerhalb der tun, während Schleife wie unten gezeigt. 0,0976 ist der Wert, der mit 1024 multipliziert werden muss, um 100 zu erhalten. Um T_ON zu berechnen, haben wir ihn mit 10 multipliziert, um den Wert in Millisekunden zu erhalten.
während (1) { POT_val = (ADC_Read (0)); // Den Wert von POT mit ADC lesen Duty_cycle = (POT_val * 0.0976); // 0 bis 1024 bis 0 bis 100 zuordnen T_ON = ((Duty_cycle * T_TOTAL) * 10/100); // Berechne die Einschaltzeit mit der Formeleinheit in Millisekunden __delay_ms (100); }}
Da der Timer alle 0,1 ms auf Überlauf eingestellt ist, wird die Timer-Interrupt-Serviceroutine ISR alle 0,1 ms aufgerufen. Innerhalb der Serviceroutine verwenden wir eine Variable namens count und erhöhen sie alle 0,1 ms. Auf diese Weise können wir die Zeit verfolgen. Um mehr über Interrupts im PIC-Mikrocontroller zu erfahren, folgen Sie den Links
if (TMR0IF == 1) // Timer-Flag wurde aufgrund eines Timer-Überlaufs ausgelöst -> wird alle 0,1 ms auf Überlauf gesetzt { TMR0 = 248; // Lade den Timer Wert TMR0IF = 0; // Timer Interrupt Flag Count löschen ++; // Zählinkremente für jeweils 0,1 ms -> count / 10 geben den Zählwert in ms an }
Schließlich ist es Zeit, den GPIO-Pin basierend auf dem Wert von T_ON und T_OFF umzuschalten. Wir haben die Zählervariable, die die Spuren der Zeit in Millisekunden halten. Wir verwenden diese Variable, um zu überprüfen, ob die Zeit kürzer als pünktlich ist. Wenn ja, lassen wir den GPIO-Pin eingeschaltet, andernfalls schalten wir ihn aus und lassen ihn ausgeschaltet, bis der neue Zyklus beginnt. Dies kann durch Vergleich mit der Gesamtzeit eines PWM-Zyklus erfolgen. Der Code, um dasselbe zu tun, ist unten gezeigt
if (count <= (T_ON)) // Wenn die Zeit kürzer als die Zeit RD1 = 1 ist; // GPIO einschalten sonst RD1 = 0; // Andernfalls schalten Sie GPIO aus, wenn (count> = (T_TOTAL * 10)) // Lassen Sie es ausgeschaltet, bis ein neuer Zyklus beginnt. Count = 0;
Schaltplan
Das Schaltbild zur Erzeugung von PWM mit dem GPIO-Pin des PIC-Mikrocontrollers ist wirklich einfach. Versorgen Sie den PIC einfach mit einem Oszillator und verbinden Sie das Potentiometer mit Pin AN0 und den Servomotor mit Pin RD1. Wir können den GPIO-Pin verwenden, um das von mir ausgewählte PWM-Signal zu erhalten RD1 nur zufällig. Sowohl das Potentiometer als auch der Servomotor werden mit 5 V betrieben, die vom 7805 geregelt werden, wie unten im Schaltplan gezeigt.
Simulation
Um das Projekt zu simulieren, habe ich meine Proteus-Software verwendet. Erstellen Sie die unten gezeigte Schaltung, verknüpfen Sie den Code mit Ihrer Simulation und führen Sie ihn aus. Sie sollten gemäß unserem Programm ein PWM-Signal am RD1-GPIO-Pin erhalten und das Tastverhältnis der PWM sollte basierend auf der Position des Potentiometers gesteuert werden. Das folgende GIF zeigt, wie das PWM-Signal und der Servomotor reagieren, wenn der ADC-Wert über das Potentiometer geändert wird.
Hardware-Setup zur Steuerung des Servomotors mit dem PIC-Mikrocontroller
Mein komplettes Hardware-Setup ist unten dargestellt. Für Leute, die meinen Tutorials folgen, sollte dieses Board vertraut aussehen. Es ist dasselbe Board, das ich bisher in allen meinen Tutorials verwendet habe. Sie können sich auf das Tutorial für blinkende LED beziehen, wenn Sie wissen möchten, wie ich es baue. Ansonsten folgen Sie einfach dem obigen Schaltplan und alles sollte gut funktionieren.
Laden Sie das Programm hoch und variieren Sie das Potentiometer. Das Servo sollte die Position basierend auf der Position des Potentiometers ändern. Die vollständige Arbeitsweise des Projekts wird in dem Video am Ende dieser Seite gezeigt. Ich hoffe, Sie haben das Projekt verstanden und es genossen zu bauen. Wenn Sie Fragen haben, können Sie diese gerne im Forum veröffentlichen. Ich werde mein Bestes geben, um zu antworten.
Ich plane, dieses Projekt voranzutreiben, indem ich Optionen zur Steuerung mehrerer Servomotoren hinzufüge und daraus einen Roboterarm baue, ähnlich dem Arduino-Roboterarm, den wir bereits gebaut haben. Also bis dahin bis dann !!