- Kretsschema
- Genererar PWM-signaler på GPIO-stift för servomotorstyrning
- Programmering PIC16F8771A för robotarm
- Simulering av PIC Robotic Arm Code
- PCB-design med EasyEDA
- Beräkning och beställning av prover online
- Arbeta med PIC Robotic Arm
Från monteringslinjen inom biltillverkningsindustrin till telekirurgirobotarna i rymden finns robotarmar överallt. Mekanismerna hos dessa robotar liknar en människa som kan programmeras för liknande funktion och ökad kapacitet. De kan användas för att utföra upprepade åtgärder snabbare och mer exakt än människor eller kan användas i tuffa miljöer utan att riskera människoliv. Vi har redan byggt en Record and Play Robotic Arm med Arduino som kan utbildas för att göra en viss uppgift och få upprepa för alltid.
I denna handledning kommer vi att använda industristandarden PIC16F877A 8-bitars mikrokontroller för att styra samma robotarm med potentiometrar. Utmaningen med detta projekt är att PIC16F877A bara har två stift med PWN-kapacitet, men vi måste kontrollera cirka 5 servomotorer för vår robot som kräver 5 individuella PWM-stift. Så vi måste använda GPIO-stiften och generera PWM-signaler på PIC GPIO-stift med hjälp av timeravbrott. Nu kan vi naturligtvis uppgradera till en bättre mikrokontroller eller använda en de-multiplexer IC för att göra saker mycket enklare här. Men ändå är det värt att ge detta projekt ett försök för inlärningsupplevelsen.
Den mekaniska strukturen på robotarmen som jag använder i det här projektet var helt 3D-tryckt för mitt tidigare projekt; Du hittar de kompletta designfilerna och monteringsproceduren här. Alternativt, om du inte har en 3D-skrivare kan du också bygga en enkel robotarm med kartong som visas i länken. Förutsatt att du på något sätt har tagit tag i din robotarm kan vi gå vidare i projektet.
Kretsschema
Det fullständiga kretsschemat för denna PIC-mikrokontrollerbaserade robotarm visas nedan. Schemat ritades med EasyEDA.
Kretsschemat är ganska enkelt; hela projektet drivs av 12V-adaptern. Denna 12V omvandlas sedan till + 5V med två 7805 spänningsregulatorer. En är märkt som + 5V och den andra är märkt som + 5V (2). Anledningen till att ha två regulatorer är att när servon roterar drar den in mycket ström vilket skapar ett spänningsfall. Detta spänningsfall tvingar PIC att starta om sig själv, därför kan vi inte styra både PIC och servomotorer på samma + 5V-skena. Så den som är märkt som + 5V används för att driva PIC Microcontroller, LCD och potentiometrar och en separat regulatorutgång som är märkt som + 5V (2) används för att driva servomotorerna.
De fem utgångarna på potentiometrarna som ger en variabel spänning från 0V till 5V är anslutna till de analoga stiften An0 till AN4 i PIC. Eftersom vi planerar att använda timers för att generera PWM kan servomotorerna anslutas till vilken GPIO-stift som helst. Jag har valt stift från RD2 till RD6 för servomotorerna, men det kan vara valfri GPIO.
Eftersom programmet involverar mycket felsökning, är en 16x2 LCD-skärm också gränssnitt till port B på PIC. Detta visar arbetscykeln för de servomotorer som kontrolleras. Bortsett från detta har jag också utökade anslutningar för alla GPIO och analoga stift, bara om några sensorer behöver gränssnitt i framtiden. Slutligen har jag också anslutit programmeringsstiftet H1 för att direkt programmera PIC med pickit3 med ICSP-programmeringsalternativet.
Genererar PWM-signaler på GPIO-stift för servomotorstyrning
När kretsen är klar måste vi ta reda på hur man genererar PWN-signaler på GPIO-stiftet på PIC för att styra servomotorn. Vi har redan tröttnat på något liknande med Timer interrupt-metoden och lyckades. Här kommer vi bara att bygga på det, så om du är ny här rekommenderar jag starkt att du läser den här föregående handledningen innan du fortsätter vidare.
Alla hobby servomotorer arbetar med en frekvens på 50Hz. Det betyder att en komplett pulscykel för en servomotor är 1/50 (F = 1 / T) vilket är 20 ms. Av dessa kompletta 20 ms är styrsignalen endast från 0 till 2 ms medan resten av signalen alltid är avstängd. Figuren nedan visar hur ON-tiden bara varierar från 0 till 2 ms för att rotera motorn från 0 grader till 180 grader av den totala 20 ms-varaktigheten.
Med detta i åtanke måste vi skriva programmet på ett sådant sätt att PIC läser in 0 till 1204 från potentiometern och kartlägger det till 0 till 100 vilket kommer att vara servomotorns arbetscykel. Med denna arbetscykel kan vi beräkna servomotorns PÅ-tid. Då kan vi initiera timeravbrottet för att flöda med ett regelbundet intervall så att det fungerar som millis () -funktionen i Arduino. Med det kan vi växla status GPIO-stift för att vara hög under önskad varaktighet och stänga av den efter 20 ms (en komplett cykel) och sedan upprepa samma process. Nu när vi har förstått logiken, låt oss gå in i programmet.
Programmering PIC16F8771A för robotarm
Som alltid finns det kompletta programmet med en video i slutet av denna sida, koden kan också laddas ner härifrån med alla nödvändiga filer. I detta avsnitt kommer vi att diskutera logiken bakom programmet. Programmet använder ADC-modulen, timermodulen och LCD-modulen för att styra robotarmen. Om du inte är medveten om hur du använder ADC-funktionerna eller timerfunktionerna eller gränssnitt en LCD-skärm med PIC, kan du falla tillbaka till respektive länkar för att lära dig dem. Nedanstående förklaring ges förutsatt att läsaren känner till dessa begrepp.
Timer 0-portkonfiguration
Det viktigaste avsnittet i koden är att ställa in Timer 0 till överflöde för varje specifik fördröjning. Formlerna för att beräkna denna fördröjning kan ges som
Fördröjning = ((256-REG_val) * (Prescal * 4)) / Fosc
Genom att använda OPTION_REG- och TMR0-registret har vi ställt in timern 0 så att den fungerar med ett förskalvärde på 32 och REG-värdet är inställt på 248. Kristallfrekvensen (Fosc) som används i vår hårdvara är 20 MHz. Med dessa värden kan fördröjningen beräknas som
Fördröjning = ((256-248) * (32 * 4)) / (20000000) = 0,0000512 sekunder (eller) = 0,05 ms
Så nu har vi ställt in timern för att flöda vid varje 0,05 ms. Koden för att göra detsamma ges nedan
/ ***** Portkonfiguration för timer ****** / OPTION_REG = 0b00000100; // Timer0 med extern freq och 32 som prescalar // Aktiverar även PULL UPs TMR0 = 248; // Ladda tidsvärdet för 0,0001s; delayValue kan vara mellan 0-256 endast TMR0IE = 1; // Aktivera timeravbrottsbit i PIE1-registret GIE = 1; // Aktivera Global Interrupt PEIE = 1; // Aktivera perifert avbrott / *********** ______ *********** /
Av servomotorns totala kontrollfönster 0ms till 2ms kan vi styra det med en upplösning på 0,05 msek, vilket gör att vi kan ha (2 / 0,05) 40 olika positioner för motorn mellan 0 grader och 180 grader. Du kan minska detta värde ytterligare om din MCU kan stödja det för att få fler positioner och exakt kontroll.
Interrupt Service Routine (ISR)
Nu när vi har inställt Timer 0 för överflöde för varje 0,05 ms kommer TMR0IF-avbrottsflaggan att vara inställd på 0,05 ms. Så inom ISR-funktionen kan vi återställa den flaggan och öka en variabel som heter count by one. Så nu kommer denna variabel att ökas med 1 för varje 0,05 ms.
void interrupt timer_isr () { if (TMR0IF == 1) // Timerflagga har utlösts på grund av timeröverflöde -> inställt på överflöde för varje 0,05 ms { TMR0 = 248; // Ladda timern Värde TMR0IF = 0; // Rensa timer avbryta flaggantal ++; // Räkna steg med 1 för varje 0,05 ms }
Beräkning av arbetscykel och tid
Därefter måste vi beräkna arbetscykeln och i tid för alla fem servomotorer. Vi har fem servomotorer som var och en används för att styra enskilda armpartier. Så vi måste läsa ADC-värdet för alla fem och beräkna arbetscykeln och i tid för varje.
ADC-värdet ligger inom området 0 till 1024, vilket kan omvandlas till 0% till 100% arbetscykel genom att helt enkelt multiplicera 0,0976 (100/1024 = 0,0976) till det erhållna värdet. Denna 0 till 100% arbetscykel måste sedan konverteras till PÅ-tid. Vi vet att vid 100% arbetscykel måste ON-tiden vara 2 ms (för 180 grader) så att multiplicera 0,02 (2/100 = 0,02) kommer att konvertera 0 till 100 arbetscykel till 0 till 2 ms. Men då är antalet timervariabler inställt att öka en gång för varje 0,05 ms. Detta betyder att värdet på räkningen kommer att vara 20 (1 / 0,05 = 20) för varje 1 ms. Så vi måste multiplicera 20 med 0,02 för att beräkna den exakta tiden för vårt program vilket ger oss värdet 0,4 (0,02 * 20 = 0,4). Koden för detsamma visas nedan, du kan se den upprepas 5 gånger för alla 5 potter med en for loop. De resulterande värdena lagras i T_ON-matrisen.
för (int pot_num = 0; pot_num <= 3; pot_num ++) { int Pev_val = T_ON; POT_val = (ADC_Read (pot_num)); // Läs värdet på POT med ADC Duty_cycle = (POT_val * 0,0976); // Karta 0 till 1024 till 0 till 100 T_ON = Duty_cycle * 0.4; // 20 * 0.02
Välja vilken motor som ska rotera
Vi kan inte styra alla fem motorerna tillsammans eftersom det kommer att göra ISR-koden tung att sakta ner hela mikrokontrollern. Så vi måste bara rotera en servomotor åt gången. För att välja vilken servo som ska roteras övervakar mikrokontrollern PÅ-tiden för alla fem servomotorerna och jämför den med den tidigare i tid. Om det sker en förändring av ON-tiden kan vi dra slutsatsen att den specifika servon måste flyttas. Koden för detsamma visas nedan.
om (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:");} annars om (pot_num == 1) {Lcd_Set_Cursor (1,6); Lcd_Print_String ("B:");} annars om (pot_num == 2) {Lcd_Set_Cursor (1,11); Lcd_Print_String ("C:");} annars om (pot_num == 3) {Lcd_Set_Cursor (2,1); Lcd_Print_String ("D:");} annars om (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');
Vi skriver också ut servocykeln på LCD-skärmen så att användaren kan vara medveten om sin nuvarande position. Baserat på förändringen i PÅ-tid uppdateras den variabla servon med siffror från 0 till 4 som vardera representerar enskilda motorer.
Styrning av servomotorn inuti ISR
Inuti ISR har vi variabelantalet ökat för varje 0,05 ms, detta betyder att för varje 1 ms kommer variabeln att ökas med 20. Med hjälp av detta måste vi styra stiften för att producera PWM-signal. Om räknarvärdet är mindre än i tid slås GPIO för den motorn på med hjälp av nedanstående rad
PORTD = PORTD - servokod;
Här har array servo_code stiftdetaljen för alla fem servomotorer och baserat på värdet i variabel servo kommer koden för just den servomotorn att användas. Det är då logiskt ELLER (-) med befintliga PORTD-bitar så att vi inte stör värdena på andra motorer och endast uppdaterar just denna motor. På samma sätt för att stänga av stiftet
PORTD = PORTD & ~ (servokod);
Vi har vänt bitvärdet med hjälp av den logiska inversa (~) operatören och sedan utfört en AND (&) operation på PORTD för att stänga av endast önskad stift medan de andra stiften lämnas i sitt tidigare tillstånd. Det fullständiga kodavsnittet visas nedan.
void interrupt timer_isr () { if (TMR0IF == 1) // Timerflagga har utlösts på grund av timeröverflöde -> inställt på överflöde för varje 0,05 ms { TMR0 = 248; // Ladda timern Värde TMR0IF = 0; // Rensa timer avbryta flaggantal ++; // Räkna steg med 1 för varje 0,05 ms -> räkna kommer att vara 20 för varje 1 ms (0,05 / 1 = 20)) } int servo_code = {0b01000000, 0b00100000, 0b00010000, 0b00001000, 0b00000100}; if (count> = 20 * 20) count = 0; om (räkna <= (T_ON)) PORTD = PORTD - servokod; annars PORTD = PORTD & ~ (servokod); }
Vi vet att den totala cykeln måste pågå i 20 ms innan GPIO-stiftet slås på igen. Så vi kontrollerar om räkningen har överskridit 20 ms genom att jämföra värdet på räkningen med 400 (samma beräkning som diskuterats ovan) och om ja måste vi initialisera räkningen till att vara noll igen.
Simulering av PIC Robotic Arm Code
Det är alltid bättre att simulera koden innan du tar den till den verkliga hårdvaran. Så jag använde Proteus för att simulera min kod och verifierade att den skulle fungera korrekt. Kretsen som används för simulering visas nedan. Vi har använt ett oscilloskop för att kontrollera om PWM-signalerna genereras efter behov. Vi kan också verifiera om LCD- och servomotorerna roterar som förväntat.
Som du ser visar LCD: n arbetscykeln för motor D att vara 07 baserat på potten som är den tredje motorn. Liknande om en annan kruka flyttas kommer arbetscykeln för den potten och dess motornummer att visas på LCD-skärmen. PWM-signalen som visas på oscilloskopet visas nedan.
Den totala cykelperioden mäts till 22,2 ms med hjälp av marköralternativet på oscilloskopet, som ligger mycket nära de önskade 20 ms. Slutligen är vi säkra på att koden fungerar, så för att fortsätta med kretsen kan vi antingen löda den på ett perfekt kort eller använda ett kretskort. Det fungerar inte lätt på brädbrädan eftersom POT alltid tenderar att ge några problem på grund av dåliga anslutningar.
PCB-design med EasyEDA
För att utforma denna PIC-robotarm har vi valt EDA-verktyget online som heter EasyEDA. Jag har använt den länge nu och tycker att den är väldigt bekväm på grund av dess stora tillgänglighet av fotavtryck och lättanvänd natur. Efter att ha designat kretskortet kan vi beställa kretskortproverna med deras billiga tjänster för tillverkning av kretskort. De erbjuder också komponent sourcingtjänster där de har ett stort lager av elektroniska komponenter och användare kan beställa sina nödvändiga komponenter tillsammans med PCB-beställningen.
När du designar dina kretsar och kretskort kan du också göra din krets- och kretskortsdesign offentlig så att andra användare kan kopiera eller redigera dem och dra nytta av ditt arbete, vi har också gjort hela krets- och kretskortlayouterna offentliga för den här kretsen, kolla nedanstående länk:
easyeda.com/circuitdigest/pic-development-board-for-robotic-arm
Med den här länken kan du direkt beställa samma PCB som vi använder i detta projekt och använda det. När designen är klar kan tavlan ses som en 3D-modell, vilket kommer att vara till stor hjälp för att visualisera hur tavlan ser ut efter tillverkningen. 3D-modellen av kortet som vi använder visas nedan. Bortsett från detta kan du också se det övre och nedre lagret på brädet för att kontrollera om den glatta skärmen är som förväntat.
Beräkning och beställning av prover online
Efter att ha slutfört designen av denna PIC Robot PCB kan du beställa PCB via JLCPCB.com. För att beställa PCB från JLCPCB behöver du Gerber File. För att ladda ner Gerber-filer på din PCB klickar du bara på knappen Generate Fabrication File på EasyEDA-redigeringssidan och laddar sedan ner Gerber-filen därifrån eller så kan du klicka på Order at JLCPCB som visas i bilden nedan. Detta kommer att omdirigera dig till JLCPCB.com, där du kan välja antalet PCB du vill beställa, hur många kopparlager du behöver, PCB-tjockleken, kopparvikten och till och med PCB-färgen, som ögonblicksbilden som visas nedan:
När du har valt alla alternativ klickar du på "Spara i kundvagn" och sedan kommer du till sidan där du kan ladda upp din Gerber-fil som vi har laddat ner från EasyEDA. Ladda upp din Gerber-fil och klicka på "Spara i kundvagn". Och slutligen klicka på Kassan säkert för att slutföra din beställning, så får du dina PCB några dagar senare. De tillverkar kretskortet till mycket låg hastighet, vilket är $ 2. Deras byggtid är också mycket mindre vilket är 48 timmar med DHL-leverans på 3-5 dagar, i princip får du dina PCB inom en vecka efter beställning.
Efter beställning av kretskortet kan du kontrollera produktionsförloppet för ditt kretskort med datum och tid. Du kontrollerar det genom att gå till kontosidan och klicka på "Produktionsförlopp".
Efter några dagars beställning av PCB fick jag PCB-proverna i fin förpackning som visas på bilderna nedan.
Och efter att ha fått dessa bitar har jag lödt alla nödvändiga komponenter över kretskortet. Jag lödde också POT direkt direkt istället för att använda anslutningsledningar eftersom de kvinnliga till honkablarna som jag ursprungligen använde för att ge konstiga analoga utspänningar förmodligen på grund av lösa kontakter. När alla komponenterna hade monterats såg min PCB ungefär så här ut.
Du kanske har märkt att det bara finns en 7805 på detta bräde. Det beror på att jag ursprungligen trodde att jag kunde komma undan med bara regulator för att driva både PIC och servomotor och senare insåg jag att jag behöver två. Så jag har använt en extern krets för att driva servomotorerna genom de gröna ledningarna du ser här.
Ändå behöver du inte oroa dig mycket för det för; Jag har gjort ändringarna i PCB nu. Du kan använda det modifierade kretskortet och löda båda regulatorerna ombord själv.
Arbeta med PIC Robotic Arm
Efter allt tröttsamt arbete är det dags att löna sig. Löd alla komponenter på kortet och ladda upp programmet till PIC-styrenheten. Komplett kod ges nedan eller kan laddas ner härifrån. Programmeringskontakten som finns på tavlan ska hjälpa dig att ladda upp programmet direkt med Pickit 3 utan mycket krångel. När programmet har laddats upp bör du se LCD-skärmen som visar servon som för närvarande styrs. För att lära dig mer om programmering av PIC Microcontroller, följ bara föregående handledning.
Därifrån kan du helt enkelt vrida potten och kontrollera hur servomotorerna svarar på varje potentiometer. När du förstår formatet kan du styra robotarmen för att utföra vilken åtgärd du behöver för att utföra och ha kul. Du kan hitta det fullständiga arbetet med projektet i videon som länkas nedan.
Det är det som hoppas att ni förstod projektet och lärde er något nytt av det. Om du har några frågor lämnar du dem i kommentarsektionen eller använder forumen för andra tekniska diskussioner.