- Schaltplan
- Generieren von PWM-Signalen am GPIO-Pin für die Servomotorsteuerung
- Programmierung PIC16F8771A für Roboterarm
- Simulation des PIC-Roboterarmcodes
- PCB Design mit EasyEDA
- Muster online berechnen und bestellen
- Arbeiten des PIC Robotic Arm
Vom Fließband der Automobilindustrie bis zu den Telechirurgierobotern im Weltraum sind Robotic Arms überall zu finden. Die Mechanismen dieser Roboter ähneln denen eines Menschen, die für ähnliche Funktionen und erhöhte Fähigkeiten programmiert werden können. Sie können verwendet werden, um wiederholte Aktionen schneller und genauer als Menschen auszuführen, oder sie können in rauen Umgebungen verwendet werden, ohne das Leben von Menschen zu gefährden. Wir haben bereits einen Record and Play-Roboterarm mit Arduino gebaut, der für eine bestimmte Aufgabe trainiert und für immer wiederholt werden kann.
In diesem Tutorial verwenden wir den Industriestandard PIC16F877A 8-Bit-Mikrocontroller, um denselben Roboterarm mit Potentiometern zu steuern. Die Herausforderung bei diesem Projekt besteht darin, dass PIC16F877A nur zwei PWN-fähige Pins hat, aber wir müssen ungefähr 5 Servomotoren für unseren Roboter steuern, für die 5 einzelne PWM-Pins erforderlich sind. Wir müssen also die GPIO-Pins verwenden und PWM-Signale auf PIC-GPIO-Pins unter Verwendung der Timer-Interrupts erzeugen. Jetzt könnten wir natürlich auf einen besseren Mikrocontroller upgraden oder einen De-Multiplexer-IC verwenden, um die Dinge hier viel einfacher zu machen. Trotzdem lohnt es sich, dieses Projekt für die Lernerfahrung auszuprobieren.
Die mechanische Struktur des Roboterarms, den ich in diesem Projekt verwende, wurde für mein vorheriges Projekt vollständig in 3D gedruckt. Die vollständigen Konstruktionsdateien und das Montageverfahren finden Sie hier. Wenn Sie keinen 3D-Drucker haben, können Sie alternativ auch einen einfachen Roboterarm aus Pappe bauen, wie im Link gezeigt. Angenommen, Sie haben Ihren Roboterarm irgendwie in die Hand genommen, können Sie mit dem Projekt fortfahren.
Schaltplan
Das vollständige Schaltbild für diesen auf PIC-Mikrocontrollern basierenden Roboterarm ist unten dargestellt. Die Schaltpläne wurden mit EasyEDA erstellt.
Der Schaltplan ist ziemlich einfach; Das gesamte Projekt wird über den 12-V-Adapter mit Strom versorgt. Diese 12 V werden dann mit zwei 7805-Spannungsreglern in + 5 V umgewandelt. Einer ist als + 5V und der andere als + 5V (2) gekennzeichnet. Der Grund für zwei Regler ist, dass das Servo beim Drehen viel Strom zieht, was zu einem Spannungsabfall führt. Dieser Spannungsabfall zwingt den PIC, sich selbst neu zu starten, daher können wir nicht sowohl den PIC als auch die Servomotoren auf derselben + 5V-Schiene betreiben. Der mit + 5 V gekennzeichnete wird zur Stromversorgung des PIC-Mikrocontrollers, des LCD und der Potentiometer verwendet, und ein separater Reglerausgang mit der Bezeichnung + 5 V (2) wird zur Stromversorgung der Servomotoren verwendet.
Die fünf Ausgangspins der Potentiometer, die eine variable Spannung von 0 V bis 5 V liefern, sind mit den analogen Pins An0 bis AN4 des PIC verbunden. Da wir planen, Timer zur Erzeugung von PWM zu verwenden, können die Servomotoren an jeden GPIO-Pin angeschlossen werden. Ich habe Pins von RD2 bis RD6 für die Servomotoren ausgewählt, aber es kann ein beliebiger GPIO Ihrer Wahl sein.
Da das Programm viel Debugging erfordert, ist ein 16x2-LCD-Display auch an Port B des PIC angeschlossen. Dies zeigt den Arbeitszyklus der Servomotoren an, die gesteuert werden. Abgesehen davon habe ich auch die Anschlüsse für alle GPIO- und Analog-Pins erweitert, nur für den Fall, dass in Zukunft Sensoren angeschlossen werden müssen. Schließlich habe ich auch den Programmierstift H1 angeschlossen, um den PIC mit pickit3 über die ICSP-Programmieroption direkt zu programmieren.
Generieren von PWM-Signalen am GPIO-Pin für die Servomotorsteuerung
Sobald die Schaltung fertig ist, müssen wir herausfinden, wie PWN-Signale am GPIO-Pin des PIC erzeugt werden, um den Servomotor zu steuern. Wir haben bereits etwas Ähnliches mit der Timer-Interrupt-Methode müde gemacht und waren erfolgreich. Hier bauen wir nur darauf auf. Wenn Sie neu hier sind, würde ich Ihnen dringend empfehlen, dieses vorherige Tutorial zu lesen, bevor Sie fortfahren.
Alle Hobby- Servomotoren arbeiten mit einer Frequenz von 50 Hz. Dies bedeutet, dass ein vollständiger Impulszyklus für einen Servomotor 1/50 (F = 1 / T) beträgt, was 20 ms entspricht. Von diesen vollständigen 20 ms ist das Steuersignal nur von 0 bis 2 ms, während der Rest des Signals immer ausgeschaltet ist. Die folgende Abbildung zeigt, wie die EIN-Zeit nur von 0 bis 2 ms variiert, um den Motor von 0 Grad auf 180 Grad der gesamten Dauer von 20 ms zu drehen.
In diesem Sinne müssen wir das Programm so schreiben, dass der PIC 0 bis 1204 vom Potentiometer einliest und es auf 0 bis 100 abbildet, was das Tastverhältnis des Servomotors darstellt. Mit diesem Arbeitszyklus können wir die Einschaltzeit des Servomotors berechnen. Dann können wir den Timer-Interrupt so initialisieren, dass er in regelmäßigen Abständen überläuft, sodass er ähnlich wie die millis () -Funktion in Arduino funktioniert. Damit können wir den Status-GPIO-Pin für eine gewünschte Dauer auf High schalten und ihn nach 20 ms (ein vollständiger Zyklus) ausschalten und dann den gleichen Vorgang wiederholen. Nachdem wir die Logik verstanden haben, lassen Sie uns in das Programm einsteigen.
Programmierung PIC16F8771A für Roboterarm
Wie immer finden Sie das komplette Programm mit einem Video am Ende dieser Seite. Von hier aus kann auch Code mit allen erforderlichen Dateien heruntergeladen werden. In diesem Abschnitt werden wir die Logik hinter dem Programm diskutieren. Das Programm verwendet das ADC-Modul, das Timer-Modul und das LCD-Modul zur Steuerung des Roboterarms. Wenn Sie nicht wissen, wie Sie die ADC- oder Timer-Funktionen verwenden oder ein LCD mit PIC verbinden, können Sie auf die entsprechenden Links zurückgreifen, um sie zu lernen. Die folgende Erklärung wird unter der Annahme gegeben, dass der Leser mit diesen Konzepten vertraut ist.
Timer 0 Port Konfiguration
Der wichtigste Abschnitt im Code ist das Einstellen des Timers 0 auf Überlauf für jede bestimmte Verzögerung. Die Formeln zur Berechnung dieser Verzögerung können wie folgt angegeben werden
Verzögerung = ((256-REG_val) * (Prescal * 4)) / Fosc
Mit dem Register OPTION_REG und TMR0 haben wir den Timer 0 so eingestellt, dass er mit einem Vorskalarwert von 32 arbeitet, und der REG-Wert ist auf 248 eingestellt. Die in unserer Hardware verwendete Kristallfrequenz (Fosc) beträgt 20 MHz. Mit diesen Werten kann die Verzögerung berechnet werden als
Verzögerung = ((256-248) * (32 * 4)) / (20000000) = 0,0000512 Sekunden (oder) = 0,05 ms
Jetzt haben wir den Timer so eingestellt, dass er alle 0,05 ms überläuft. Der Code, um dasselbe zu tun, ist unten angegeben
/ ***** Portkonfiguration für Timer ****** / OPTION_REG = 0b00000100; // Timer0 mit externer Frequenz und 32 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 / *********** ______ *********** /
Von dem gesamten Steuerfenster von 0 ms bis 2 ms des Servomotors können wir es mit einer Auflösung von 0,05 ms steuern, wodurch wir (2 / 0,05) 40 verschiedene Positionen für den Motor zwischen 0 Grad und 180 Grad haben können. Sie können diesen Wert weiter verringern, wenn Ihre MCU ihn unterstützen könnte, um mehr Positionen und eine präzise Steuerung zu erhalten.
Interrupt Service Routine (ISR)
Nachdem der Timer 0 alle 0,05 ms auf Überlauf eingestellt ist, wird das TMR0IF-Interrupt-Flag auf 0,05 ms gesetzt. So in der ISR - Funktion können wir diese Flag zurückgesetzt und eine Variable namens Zahl erhöhen durch ein. Jetzt wird diese Variable alle 0,05 ms um 1 erhöht.
void Interrupt timer_isr () { if (TMR0IF == 1) // Timer-Flag wurde aufgrund eines Timer-Überlaufs ausgelöst -> wird alle 0,05 ms auf Überlauf gesetzt { TMR0 = 248; // Lade den Timer Wert TMR0IF = 0; // Timer Interrupt Flag Count löschen ++; // Zähle die Inkremente für jeweils 0,05 ms um 1 }
Berechnung des Arbeitszyklus und der Pünktlichkeit
Als nächstes müssen wir das Tastverhältnis und die Pünktlichkeit für alle fünf Servomotoren berechnen. Wir haben fünf Servomotoren, von denen jeder zur Steuerung einzelner Armabschnitte verwendet wird. Wir müssen also den ADC-Wert aller fünf lesen und den Arbeitszyklus und die Pünktlichkeit für jeden berechnen.
Der ADC-Wert liegt im Bereich von 0 bis 1024, der durch einfaches Multiplizieren von 0,0976 (100/1024 = 0,0976) mit dem erhaltenen Wert in einen Arbeitszyklus von 0% bis 100% umgewandelt werden kann. Dieser Arbeitszyklus von 0 bis 100% muss dann in die EIN-Zeit umgewandelt werden. Wir wissen, dass bei einem Tastverhältnis von 100% die EIN-Zeit 2 ms (für 180 Grad) betragen muss. Wenn Sie also 0,02 (2/100 = 0,02) multiplizieren, wird das Tastverhältnis von 0 in 100 in 0 bis 2 ms umgewandelt. Aber dann wird die Anzahl unserer Timer-Variablen einmal pro 0,05 ms erhöht. Dies bedeutet, dass der Zählwert alle 1 ms 20 (1 / 0,05 = 20) beträgt. Wir müssen also 20 mit 0,02 multiplizieren, um die genaue Pünktlichkeit für unser Programm zu berechnen, die uns den Wert 0,4 ergibt (0,02 * 20 = 0,4). Der Code für dasselbe ist unten gezeigt. Sie können sehen, dass er 5 Mal für alle 5 Potts mit einer for-Schleife wiederholt wird. Die resultierenden Werte werden im Array T_ON gespeichert.
für (int pot_num = 0; pot_num <= 3; pot_num ++) { int Pev_val = T_ON; POT_val = (ADC_Read (pot_num)); // 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 * 0,4; // 20 * 0,02
Auswahl des zu drehenden Motors
Wir können nicht alle fünf Motoren zusammen steuern, da dadurch der ISR-Code den gesamten Mikrocontroller stark verlangsamt. Wir müssen also jeweils nur einen Servomotor drehen. Um auszuwählen, welches Servo gedreht werden soll, überwacht der Mikrocontroller die Einschaltzeit aller fünf Servomotoren und vergleicht sie mit der vorherigen Einschaltzeit. Wenn sich die EIN-Zeit ändert, können wir daraus schließen, dass das jeweilige Servo bewegt werden muss. Der Code dafür ist unten gezeigt.
if (T_ON! = Pev_val) { Lcd_Clear (); servo = pot_num; Lcd_Set_Cursor (2,11); Lcd_Print_String ("S:"); Lcd_Print_Char (Servo + '0'); if (pot_num == 0) {Lcd_Set_Cursor (1,1); Lcd_Print_String ("A:");} else if (pot_num == 1) {Lcd_Set_Cursor (1,6); Lcd_Print_String ("B:");} else if (pot_num == 2) {Lcd_Set_Cursor (1,11); Lcd_Print_String ("C:");} else if (pot_num == 3) {Lcd_Set_Cursor (2,1); Lcd_Print_String ("D:");} else if (pot_num == 4) {Lcd_Set_Cursor (2,6); Lcd_Print_String ("E:");} char d2 = (Duty_cycle)% 10; char d1 = (Duty_cycle / 10)% 10; Lcd_Print_Char (d1 + '0'); Lcd_Print_Char (d2 + '0');
Wir drucken auch den Servo-Arbeitszyklus auf dem LCD-Bildschirm, damit der Benutzer seine aktuelle Position erkennen kann. Basierend auf der Änderung der Einschaltzeit wird das variable Servo mit Zahlen von 0 bis 4 aktualisiert, die jeweils einzelne Motoren darstellen.
Steuerung des Servomotors im ISR
Innerhalb des ISR wird die Anzahl der Variablen alle 0,05 ms erhöht. Dies bedeutet, dass die Variable alle 1 ms um 20 erhöht wird. Damit müssen wir die Pins steuern, um ein PWM-Signal zu erzeugen. Wenn der Zählwert kleiner als die Einschaltzeit ist, wird der GPIO dieses Motors über die folgende Zeile eingeschaltet
PORTD = PORTD - Servocode;
Hier hat das Array servo_code das Pin-Detail aller fünf Servomotoren und basierend auf dem Wert im variablen Servo wird der Code für diesen bestimmten Servomotor verwendet. Es ist dann logisch ODER (-) mit vorhandenen PORTD-Bits, damit wir die Werte anderer Motoren nicht stören und nur diesen bestimmten Motor aktualisieren. Ähnliches gilt für das Ausschalten des Stifts
PORTD = PORTD & ~ (Servocode);
Wir haben den Bitwert mit dem logisch inversen (~) Operator umgekehrt und dann eine UND (&) -Operation am PORTD ausgeführt, um nur den gewünschten Pin auszuschalten, während die anderen Pins in ihrem vorherigen Zustand belassen wurden. Das vollständige Code-Snippet ist unten dargestellt.
void Interrupt timer_isr () { if (TMR0IF == 1) // Timer-Flag wurde aufgrund eines Timer-Überlaufs ausgelöst -> wird alle 0,05 ms auf Überlauf gesetzt { TMR0 = 248; // Lade den Timer Wert TMR0IF = 0; // Timer Interrupt Flag Count löschen ++; // Zählinkremente um 1 für jeweils 0,05 ms -> Anzahl beträgt 20 für jeweils 1 ms (0,05 / 1 = 20) } int into_code = {0b01000000, 0b00100000, 0b00010000, 0b00001000, 0b00000100}; if (count> = 20 * 20) count = 0; if (count <= (T_ON)) PORTD = PORTD - Servocode; sonst PORTD = PORTD & ~ (Servocode); }}
Wir wissen, dass der gesamte Zyklus 20 ms dauern muss, bevor der GPIO-Pin wieder eingeschaltet wird. Wir prüfen also, ob die Zählung 20 ms überschritten hat, indem wir den Wert der Zählung mit 400 vergleichen (gleiche Berechnung wie oben beschrieben), und wenn ja, müssen wir die Zählung neu initialisieren, um wieder Null zu sein.
Simulation des PIC-Roboterarmcodes
Es ist immer besser, den Code zu simulieren, bevor Sie ihn auf die reale Hardware übertragen. Also habe ich Proteus verwendet, um meinen Code zu simulieren und zu überprüfen, ob er korrekt funktioniert. Die für die Simulation verwendete Schaltung ist unten dargestellt. Wir haben ein Oszilloskop verwendet, um zu überprüfen, ob die PWM-Signale nach Bedarf erzeugt werden. Wir können auch überprüfen, ob sich die LCD- und Servomotoren wie erwartet drehen.
Wie Sie den LCD - Displays 07 basierend auf dem Topf Wert sein das Tastverhältnis des Motors D sehen können, die der 3 rd Motor. Ähnlich ist es, wenn ein anderer Topf bewegt wird, der Arbeitszyklus dieses Topfes und seine Motornummer werden auf dem LCD angezeigt. Das auf dem Oszilloskop angezeigte PWM-Signal ist unten dargestellt.
Die Gesamtzyklusdauer wird mit der Cursoroption am Oszilloskop mit 22,2 ms gemessen, was sehr nahe an den gewünschten 20 ms liegt. Schließlich sind wir sicher, dass der Code funktioniert. Um mit der Schaltung fortzufahren, können wir ihn entweder auf eine Perf-Platine löten oder eine Leiterplatte verwenden. Auf Steckbrettern funktioniert es nicht so einfach, da der POT aufgrund schlechter Verbindungen immer Probleme verursacht.
PCB Design mit EasyEDA
Für die Entwicklung dieses PIC-Roboterarms haben wir das Online-EDA-Tool EasyEDA ausgewählt. Ich benutze es schon seit langer Zeit und finde es sehr praktisch, da es sehr viel Platz bietet und einfach zu bedienen ist. Nach dem Entwurf der Leiterplatte können wir die Leiterplattenmuster über ihre kostengünstigen Leiterplattenherstellungsdienste bestellen. Sie bieten auch einen Komponentenbeschaffungsservice an, bei dem sie über einen großen Bestand an elektronischen Komponenten verfügen und Benutzer ihre erforderlichen Komponenten zusammen mit der Leiterplattenbestellung bestellen können.
Während Sie Ihre Schaltungen und Leiterplatten entwerfen, können Sie auch Ihre Schaltungs- und Leiterplattenentwürfe veröffentlichen, damit andere Benutzer sie kopieren oder bearbeiten und von Ihrer Arbeit profitieren können. Wir haben auch unsere gesamten Schaltungs- und Leiterplattenlayouts für diese Schaltung veröffentlicht der folgende Link:
easyeda.com/circuitdigest/pic-development-board-for-robotic-arm
Über diesen Link können Sie direkt dieselbe Leiterplatte bestellen, die wir in diesem Projekt verwenden, und sie verwenden. Sobald das Design fertig ist, kann die Platine als 3D-Modell betrachtet werden, was sehr hilfreich ist, um zu visualisieren, wie die Platine nach der Herstellung aussehen würde. Das 3D-Modell der von uns verwendeten Platine ist unten dargestellt. Abgesehen davon können Sie auch die obere und untere Ebene der Platine anzeigen, um zu überprüfen, ob der Slick-Bildschirm den Erwartungen entspricht.
Muster online berechnen und bestellen
Nachdem Sie das Design dieser PIC-Roboterplatine abgeschlossen haben, können Sie die Platine über JLCPCB.com bestellen. Um die Platine bei JLCPCB zu bestellen, benötigen Sie Gerber File. Um Gerber-Dateien von Ihrer Leiterplatte herunterzuladen, klicken Sie einfach auf der EasyEDA-Editor-Seite auf die Schaltfläche Generate Fabrication File (Fertigungsdatei generieren) und laden Sie dann die Gerber-Datei von dort herunter, oder klicken Sie auf Order at JLCPCB (siehe Abbildung unten). Dadurch werden Sie zu JLCPCB.com weitergeleitet, wo Sie die Anzahl der zu bestellenden Leiterplatten, die Anzahl der benötigten Kupferschichten, die Leiterplattendicke, das Kupfergewicht und sogar die Leiterplattenfarbe auswählen können, wie in der folgenden Abbildung dargestellt:
Nachdem Sie alle Optionen ausgewählt haben, klicken Sie auf "In den Warenkorb speichern" und Sie werden zu der Seite weitergeleitet, auf der Sie Ihre Gerber-Datei hochladen können, die wir von EasyEDA heruntergeladen haben. Laden Sie Ihre Gerber-Datei hoch und klicken Sie auf "In Warenkorb speichern". Klicken Sie abschließend sicher auf Kasse, um Ihre Bestellung abzuschließen. Einige Tage später erhalten Sie Ihre Leiterplatten. Sie stellen die Leiterplatte mit einer sehr niedrigen Rate her, die 2 US-Dollar beträgt. Ihre Bauzeit ist auch sehr viel kürzer, was 48 Stunden bei einer DHL-Lieferung von 3-5 Tagen beträgt. Grundsätzlich erhalten Sie Ihre Leiterplatten innerhalb einer Woche nach der Bestellung.
Nach der Bestellung der Leiterplatte können Sie den Produktionsfortschritt Ihrer Leiterplatte mit Datum und Uhrzeit überprüfen . Sie überprüfen dies, indem Sie auf der Kontoseite auf "Produktionsfortschritt" klicken.
Nachdem ich einige Tage lang Leiterplatten bestellt hatte, erhielt ich die Leiterplattenmuster in einer schönen Verpackung, wie in den folgenden Abbildungen gezeigt.
Und nachdem ich diese Teile erhalten habe, habe ich alle erforderlichen Komponenten über die Leiterplatte gelötet. Ich habe den POT auch direkt gelötet, anstatt Verbindungsdrähte zu verwenden, da die von mir ursprünglich verwendeten Buchsen zu Buchsen seltsame analoge Ausgangsspannungen lieferten, wahrscheinlich aufgrund loser Kontakte. Nachdem alle Komponenten zusammengebaut waren, sah meine Platine ungefähr so aus.
Möglicherweise haben Sie bemerkt, dass sich auf diesem Board nur ein 7805 befindet. Das liegt daran, dass ich anfangs dachte, ich könnte mit nur einem Regler davonkommen, um sowohl den PIC als auch den Servomotor anzutreiben, und später wurde mir klar, dass ich zwei brauche. Daher habe ich einen externen Stromkreis verwendet, um die Servomotoren über die hier gezeigten grünen Drähte mit Strom zu versorgen.
Trotzdem müssen Sie sich nicht viel darum kümmern, weil; Ich habe jetzt die Änderungen an der Leiterplatte vorgenommen. Sie können die modifizierte Leiterplatte verwenden und beide Regler an Bord selbst löten.
Arbeiten des PIC Robotic Arm
Nach all der anstrengenden Arbeit ist es Zeit für eine Auszahlung. Löten Sie alle Komponenten auf der Platine und laden Sie das Programm auf den PIC-Controller hoch. Der vollständige Code ist unten angegeben oder kann hier heruntergeladen werden. Der auf der Platine bereitgestellte Programmieranschluss soll Ihnen helfen, das Programm ohne großen Aufwand direkt mit Pickit 3 hochzuladen. Nach dem Hochladen des Programms sollte auf dem LCD das Servo angezeigt werden, das gerade gesteuert wird. Um mehr über die Programmierung des PIC-Mikrocontrollers zu erfahren, folgen Sie einfach dem vorherigen Tutorial.
Von dort aus können Sie einfach den Topf drehen und überprüfen, wie die Servomotoren auf jedes Potentiometer reagieren. Sobald Sie das Format verstanden haben, können Sie den Roboterarm steuern, um die Aktion auszuführen, die Sie benötigen, um Spaß zu haben. Sie können finden Sie die komplette Bearbeitung des Projekts in dem Video unten verlinkt.
Das heißt, Leute hoffen, dass Sie das Projekt verstanden und etwas Neues daraus gelernt haben. Wenn Sie Fragen haben, lassen Sie diese im Kommentarbereich oder nutzen Sie die Foren für andere technische Diskussionen.