- Kretsdiagram
- Genererer PWM-signaler på GPIO-pin for servomotorkontroll
- Programmering PIC16F8771A for robotarm
- Simulering av PIC Robotic Arm Code
- PCB-design ved bruk av EasyEDA
- Beregning og bestilling av prøver online
- Arbeid av PIC Robotic Arm
Fra samlebåndet til bilindustrien til telekirurgisk roboter i verdensrommet, finnes robotvåpen overalt. Mekanismene til disse robotene ligner på et menneske som kan programmeres for lignende funksjon og økte evner. De kan brukes til å utføre gjentatte handlinger raskere og nøyaktig enn mennesker, eller de kan brukes i tøffe omgivelser uten å risikere menneskeliv. Vi har allerede bygget en Record and Play Robotic Arm ved hjelp av Arduino, som kan bli trent til å gjøre en bestemt oppgave og få gjenta for alltid.
I denne opplæringen vil vi bruke industristandarden PIC16F877A 8-biters mikrokontroller for å kontrollere den samme robotarmen med potensiometere. Utfordringen med dette prosjektet er at PIC16F877A bare har to PWN-kompatible pinner, men vi trenger å kontrollere omtrent 5 servomotorer for roboten vår som krever 5 individuelle PWM-pinner. Så vi må bruke GPIO-pinnene og generere PWM-signaler på PIC GPIO-pinner ved hjelp av tidsavbruddene. Nå kan vi selvfølgelig oppgradere til en bedre mikrokontroller eller bruke en de-multiplexer IC for å gjøre ting mye enklere her. Men likevel er det verdt å gi dette prosjektet en prøve for læringsopplevelsen.
Den mekaniske strukturen til robotarmen som jeg bruker i dette prosjektet ble fullstendig 3D-trykt for mitt forrige prosjekt; du finner de komplette designfilene og monteringsprosedyren her. Alternativt, hvis du ikke har en 3D-skriver, kan du også bygge en enkel robotarm ved hjelp av papp som vist i lenken. Forutsatt at du på en eller annen måte har fått tak i robotarmen din, kan vi fortsette med prosjektet.
Kretsdiagram
Komplett kretsskjema for denne PIC Microcontroller-baserte robotarmen er vist nedenfor. Skjemaene ble tegnet med EasyEDA.
Kretsskjemaet er ganske enkelt; hele prosjektet drives av 12V-adapteren. Denne 12V konverteres deretter til + 5V ved bruk av to 7805 spenningsregulatorer. Den ene er merket som + 5V og den andre er merket som + 5V (2). Årsaken til å ha to regulatorer er at når servoen roterer, trekker den inn mye strøm som skaper et spenningsfall. Dette spenningsfallet tvinger PIC til å starte på nytt, derfor kan vi ikke betjene både PIC og servomotorer på samme + 5V-skinne. Så den som er merket som + 5V brukes til å drive PIC Microcontroller, LCD og potensiometere, og en separat regulatorutgang som er merket som + 5V (2) brukes til å drive servomotorene.
De fem utgangspinnene til potensiometrene som gir en variabel spenning fra 0V til 5V er koblet til de analoge pinnene An0 til AN4 i PIC. Siden vi planlegger å bruke tidtakere for å generere PWM, kan servomotorene kobles til en hvilken som helst GPIO-pin. Jeg har valgt pinner fra RD2 til RD6 for servomotorene, men det kan være hvilken som helst GPIO etter eget valg.
Siden programmet innebærer mye feilsøking, er en 16x2 LCD-skjerm også grensesnittet til port B på PIC. Dette viser driftssyklusen til servomotorene som blir kontrollert. Bortsett fra dette har jeg også utvidet tilkoblinger for alle GPIO og analoge pinner, bare i tilfelle hvis noen sensorer trenger å være grensesnitt i fremtiden. Endelig har jeg også koblet programmeringspinnen H1 for å programmere PIC direkte med pickit3 ved hjelp av ICSP-programmeringsalternativet.
Genererer PWM-signaler på GPIO-pin for servomotorkontroll
Når kretsen er klar, må vi finne ut hvordan vi genererer PWN-signaler på GPIO-pinnen på PIC for å kontrollere servomotoren. Vi har allerede sliten noe lignende ved hjelp av Timer interrupt-metoden og var vellykkede. Her skal vi bare bygge på toppen av det, så hvis du er ny her, vil jeg sterkt anbefale deg å lese denne forrige veiledningen før du fortsetter videre.
Alle hobby servomotorer fungerer med en frekvens på 50Hz. Betydningen av en komplett pulssyklus for en servomotor vil være 1/50 (F = 1 / T) som er 20ms. Av disse komplette 20 ms er styresignalet bare fra 0 til 2 ms mens resten av signalet alltid er av. Figuren nedenfor viser hvordan ON-tiden bare varierer fra 0 til 2 ms for å rotere motoren fra 0 grader til 180 grader av den totale varigheten på 20 ms.
Med dette i bakhodet må vi skrive programmet på en slik måte at PIC leser i 0 til 1204 fra potensiometeret og kartlegger det til 0 til 100 som vil være driftssyklusen til servomotoren. Ved hjelp av denne driftssyklusen kan vi beregne PÅ-tiden til servomotoren. Deretter kan vi initialisere tidsuravbruddet til å flyte med et jevnlig intervall slik at det virker som millis () -funksjonen i Arduino. Med det kan vi bytte status GPIO-pinnen til å være høy i ønsket varighet og slå den av etter 20 ms (en komplett syklus) og deretter gjenta den samme prosessen. Nå som vi har forstått logikken, la oss komme inn i programmet.
Programmering PIC16F8771A for robotarm
Som alltid finner du hele programmet med en video på slutten av denne siden, og koden kan også lastes ned herfra med alle nødvendige filer. I denne delen vil vi diskutere logikken bak programmet. Programmet benytter ADC-modulen, timermodulen og LCD-modulen for å kontrollere robotarmen. Hvis du ikke er klar over hvordan du bruker ADC-funksjonene eller Timer-funksjonene eller å grensesnitt en LCD med PIC, kan du falle tilbake til de respektive koblingene for å lære dem. Forklaringen nedenfor er gitt forutsatt at leseren er kjent med disse begrepene.
Timer 0 Port Configuration
Den viktigste delen i koden er å sette Timer 0 til overflyt for hver spesifikke forsinkelse. Formlene for å beregne denne forsinkelsen kan gis som
Forsinkelse = ((256-REG_val) * (Prescal * 4)) / Fosc
Ved å bruke OPTION_REG- og TMR0-registeret har vi satt timeren 0 til å fungere med en prescalar-verdi på 32 og REG-verdien er satt til 248. Krystallfrekvensen (Fosc) som brukes i maskinvaren er 20 MHz. Med disse verdiene kan forsinkelsen beregnes som
Forsinkelse = ((256-248) * (32 * 4)) / (20000000) = 0,0000512 sekunder (eller) = 0,05 msek
Så nå har vi satt timeren til å flyte over hver 0,05 ms. Koden for å gjøre det samme er gitt nedenfor
/ ***** Portkonfigurasjon for timer ****** / OPTION_REG = 0b00000100; // Timer0 med ekstern freq og 32 som prescalar // Aktiverer også PULL UPs TMR0 = 248; // Last inn tidsverdien for 0,0001s; delayValue kan være mellom 0-256 bare TMR0IE = 1; // Aktiver tidsavbruddsbit i PIE1-registeret GIE = 1; // Aktiver Global Interrupt PEIE = 1; // Aktiver perifer interrupt / *********** ______ *********** /
Av det totale 0 ms til 2 ms kontrollvinduet til servomotoren kan vi kontrollere det med en oppløsning på 0,05 ms, som gjør at vi kan ha (2 / 0,05) 40 forskjellige posisjoner for motoren mellom 0 grader og 180 grader. Du kan redusere denne verdien ytterligere hvis MCU-en din kan støtte den for å oppnå flere posisjoner og presis kontroll.
Interrupt Service Routine (ISR)
Nå som vi har timeren 0 satt til overstrøm for hver 0,05 ms, vil vi få TMR0IF-avbruddsflagget satt til 0,05 ms. Så inne i ISR-funksjonen kan vi tilbakestille det flagget og øke en variabel som heter count by one. Så nå vil denne variabelen økes med 1 for hver 0,05 ms.
ugyldig avbryt timer_isr () { hvis (TMR0IF == 1) // Timer-flagg har blitt utløst på grunn av timeroverløp -> satt til overløp for hver 0,05 ms { TMR0 = 248; // Last timeren Verdi TMR0IF = 0; // Clear timer interrupt flag count ++; // Telle trinn med 1 for hver 0,05 ms }
Beregning av driftssyklus og tid
Deretter må vi beregne driftssyklusen og i tide for alle fem servomotorer. Vi har fem servomotorer som hver brukes til å kontrollere den enkelte delen av armen. Så vi må lese ADC-verdien på alle fem og beregne driftssyklusen og i tide for hver.
ADC-verdien vil være i området fra 0 til 1024, som kan konverteres til 0% til 100% driftssyklus ved ganske enkelt å multiplisere 0,0976 (100/1024 = 0,0976) til den oppnådde verdien. Denne 0 til 100% driftssyklusen må deretter konverteres til PÅ-tid. Vi vet at ved 100% driftssyklus må ON-tiden være 2 ms (i 180 grader), så å multiplisere 0,02 (2/100 = 0,02) vil konvertere 0 til 100 driftssyklus til 0 til 2 ms. Men så er antallet timervariabler satt til å øke en gang for hver 0,05 ms. Dette betyr at verdien av tellingen vil være 20 (1 / 0,05 = 20) for hver 1 ms. Så vi må multiplisere 20 med 0,02 for å beregne den nøyaktige tiden for programmet vårt som gir oss verdien 0,4 (0,02 * 20 = 0,4). Koden for det samme er vist nedenfor, du kan se den gjentas 5 ganger for alle 5 pottene ved hjelp av en for loop. De resulterende verdiene lagres i T_ON-matrisen.
for (int pot_num = 0; pot_num <= 3; pot_num ++) { int Pev_val = T_ON; POT_val = (ADC_Read (pot_num)); // Les verdien av POT ved hjelp av ADC Duty_cycle = (POT_val * 0.0976); // Kart 0 til 1024 til 0 til 100 T_ON = Duty_cycle * 0.4; // 20 * 0.02
Velge hvilken motor som skal rotere
Vi kan ikke kontrollere alle fem motorene sammen, da det vil gjøre ISR-koden tung å bremse hele mikrokontrolleren. Så vi må bare rotere en servomotor om gangen. For å velge hvilken servo som skal roteres, overvåker mikrokontrolleren PÅ-tiden til alle fem servomotorene og sammenligner den med den forrige i tide. Hvis det er en endring i PÅ-tiden, kan vi konkludere med at den aktuelle servoen må flyttes. Koden for det samme er vist nedenfor.
hvis (T_ON! = Pev_val) { Lcd_Clear (); servo = pot_num; Lcd_Set_Cursor (2,11); Lcd_Print_String ("S:"); Lcd_Print_Char (servo + '0'); hvis (pot_num == 0) {Lcd_Set_Cursor (1,1); Lcd_Print_String ("A:");} annet hvis (pot_num == 1) {Lcd_Set_Cursor (1,6); Lcd_Print_String ("B:");} annet hvis (pot_num == 2) {Lcd_Set_Cursor (1,11); Lcd_Print_String ("C:");} annet hvis (pot_num == 3) {Lcd_Set_Cursor (2,1); Lcd_Print_String ("D:");} annet hvis (pot_num == 4) {Lcd_Set_Cursor (2,6); Lcd_Print_String ("E:");} char d2 = (Duty_cycle)% 10; røye d1 = (Duty_cycle / 10)% 10; Lcd_Print_Char (d1 + '0'); Lcd_Print_Char (d2 + '0');
Vi skriver også ut servo-driftssyklusen på LCD-skjermen, slik at brukeren kan være klar over sin nåværende posisjon. Basert på endringen i PÅ-tid oppdateres variabel servo med tall fra 0 til 4 som hver representerer individuelle motorer.
Styring av servomotoren inne i ISR
Inne i ISR har vi variabeltallet som økes for hver 0,05 ms, dette betyr at for hver 1 ms vil variabelen økes med 20. Ved å bruke dette må vi kontrollere pinnene for å produsere PWM-signal. Hvis verdien på telleren er mindre enn i tide, slås GPIO for den motoren på ved hjelp av linjen nedenfor
PORTD = PORTD - servo_code;
Her har matrisen servo_code pin-detaljene til alle fem servomotorer og basert på verdien i variabel servo, vil koden for den aktuelle servomotoren bli brukt. Det er da logisk ELLER (-) med eksisterende PORTD-biter, slik at vi ikke forstyrrer verdiene til annen motor og bare oppdaterer denne bestemte motoren. Tilsvarende for å slå av pinnen
PORTD = PORTD & ~ (servokode);
Vi har reversert bitverdien ved hjelp av den logiske inversoperatoren (~), og deretter har vi utført en AND (&) -operasjon på PORTD for å slå av bare den ønskede pinnen mens de andre pinnene er i sin forrige tilstand. Den komplette kodebiten er vist nedenfor.
ugyldig avbryt timer_isr () { hvis (TMR0IF == 1) // Timer-flagg har blitt utløst på grunn av timeroverløp -> satt til overløp for hver 0,05 ms { TMR0 = 248; // Last timeren Verdi TMR0IF = 0; // Clear timer interrupt flag count ++; // Telle trinn med 1 for hver 0,05 ms -> telle vil være 20 for hver 1 ms (0,05 / 1 = 20)) } int servo_code = {0b01000000, 0b00100000, 0b00010000, 0b00001000, 0b00000100}; hvis (count> = 20 * 20) count = 0; hvis (count <= (T_ON)) PORTD = PORTD - servo_code; ellers PORTD = PORTD & ~ (servokode); }
Vi vet at den totale syklusen må vare i 20 ms før GPIO-pinnen slås på igjen. Så vi sjekker om tellingen har overskredet 20ms ved å sammenligne verdien av tellingen med 400 (samme beregning som diskutert ovenfor), og hvis ja, må vi initialisere tellingen til å være null igjen.
Simulering av PIC Robotic Arm Code
Det er alltid bedre å simulere koden før du tar den med til den virkelige maskinvaren. Så jeg brukte Proteus til å simulere koden min og bekreftet at den fungerte riktig. Kretsen som brukes til simulering er vist nedenfor. Vi har brukt et oscilloskop for å sjekke om PWM-signalene blir generert etter behov. Vi kan også kontrollere om LCD- og servomotorene roterer som forventet.
Som du ser, viser LCD-skjermen driftssyklusen til motor D til å være 07 basert på potten som er den tredje motoren. Lignende hvis en annen gryte flyttes, vises driftssyklusen til gryten og dens motornummer på LCD-skjermen. PWM-signalet vist på oscilloskopet er vist nedenfor.
Den totale syklusperioden måles til 22,2 ms ved å bruke markøralternativet på oscilloskopet, som er veldig nær de ønskede 20 ms. Endelig er vi sikre på at koden fungerer, så for å fortsette med kretsen kan vi enten lodde den på et perf-kort eller bruke et PCB. Det fungerer ikke lett på brødbrett fordi POTEN alltid har en tendens til å gi noen problemer på grunn av dårlige forbindelser.
PCB-design ved bruk av EasyEDA
For å designe denne PIC-robotarmen har vi valgt det elektroniske EDA-verktøyet kalt EasyEDA. Jeg har brukt den i lang tid nå, og synes den er veldig praktisk på grunn av den store tilgjengeligheten av fotavtrykk og den enkle å bruke naturen. Etter å ha designet PCB, kan vi bestille PCB-prøvene etter deres lave kostnader PCB-fabrikasjonstjenester. De tilbyr også komponent sourcing-tjenester der de har et stort lager av elektroniske komponenter og brukere kan bestille de nødvendige komponentene sammen med PCB-bestillingen.
Mens du designer kretsene og kretskortene dine, kan du også gjøre krets- og kretskortsdesign offentlig, slik at andre brukere kan kopiere eller redigere dem og dra nytte av arbeidet ditt, vi har også gjort hele krets- og kretskortoppsett offentlig for denne kretsen, sjekk lenken nedenfor:
easyeda.com/circuitdigest/pic-development-board-for-robotic-arm
Ved hjelp av denne lenken kan du direkte bestille samme PCB som vi bruker i dette prosjektet og bruke den. Når designen er fullført, kan brettet sees på som en 3D-modell, som vil være veldig nyttig for å visualisere hvordan brettet vil se ut etter fabrikasjon. 3D-modellen av brettet som vi bruker er vist nedenfor. Bortsett fra dette kan du også se det øverste og nederste laget av brettet for å sjekke om den glatte skjermen er som forventet.
Beregning og bestilling av prøver online
Etter å ha fullført utformingen av denne PIC Robot PCB, kan du bestille PCB via JLCPCB.com. For å bestille PCB fra JLCPCB, trenger du Gerber File. For å laste ned Gerber-filer på PCB-en klikker du bare på Generer fabrikasjonsfil- knappen på EasyEDA-redigeringssiden, og deretter laster du ned Gerber-filen derfra, eller du kan klikke på Bestill på JLCPCB som vist i bildet nedenfor. Dette vil omdirigere deg til JLCPCB.com, hvor du kan velge antall PCB du vil bestille, hvor mange kobberlag du trenger, PCB-tykkelsen, kobbervekten og til og med PCB-fargen, som øyeblikksbildet vist nedenfor:
Når du har valgt alle alternativene, klikker du på "Lagre i handlekurven" og deretter blir du ført til siden der du kan laste opp Gerber-filen som vi har lastet ned fra EasyEDA. Last opp Gerber-filen og klikk “Lagre i handlekurven”. Og til slutt klikker du på Kassen sikkert for å fullføre bestillingen din, så får du PCB-ene noen dager senere. De fabrikerer kretskortet til veldig lav pris, som er $ 2. Byggetiden deres er også veldig mindre, som er 48 timer med DHL-levering på 3-5 dager, i utgangspunktet får du PCB-ene dine innen en uke etter bestilling.
Etter at du har bestilt PCB, kan du kontrollere produksjonsfremdriften til PCB med dato og klokkeslett. Du sjekker det ved å gå til Kontoside og klikke på "Produksjonsfremdrift".
Etter noen dager med bestilling av PCB fikk jeg PCB-prøvene i fin emballasje som vist på bildene nedenfor.
Og etter å ha fått disse delene har jeg loddet alle nødvendige komponenter over PCB. Jeg loddet også direkte POTEN i stedet for å bruke tilkoblingsledninger fordi kvinnelige til kvinnelige ledninger som jeg opprinnelig brukte, hvor jeg ga rare analoge utgangsspenninger sannsynligvis på grunn av løse kontakter. Når alle komponentene var samlet, så PCB-en min slik ut.
Du har kanskje lagt merke til at det bare er en 7805 på dette brettet. Det var fordi jeg i utgangspunktet trodde jeg kunne komme unna med bare regulator for å drive både PIC og servomotor, og senere skjønte jeg at jeg trenger to. Så jeg har brukt en ekstern krets for å drive servomotorene gjennom de grønne ledningene du ser her.
Likevel trenger du ikke å bekymre deg mye for det fordi; Jeg har gjort endringene på PCB nå. Du kan bruke den modifiserte kretskortet og lodde begge regulatorene ombord selv.
Arbeid av PIC Robotic Arm
Etter alt slitsomt arbeid er det på tide å lønne seg. Lodde alle komponentene på kortet og last opp programmet til PIC-kontrolleren. Komplett kode er gitt nedenfor eller kan lastes ned herfra. Programmeringskontakten som er gitt på tavlen, skal hjelpe deg med å laste opp programmet direkte ved hjelp av Pickit 3 uten mye bry. Når programmet er lastet opp, bør du se LCD-skjermen som viser servoen som for øyeblikket blir kontrollert. For å lære mer om programmering av PIC Microcontroller, følg bare forrige veiledning.
Derfra kan du bare vri potten og sjekke hvordan servomotorene reagerer på hvert potensiometer. Når du har forstått formatet, kan du kontrollere robotarmen for å utføre den handlingen du trenger for å utføre og ha det gøy. Du kan finne fullstendig bearbeiding av prosjektet i videoen som er lenket nedenfor.
Det er det gutta håper du forsto prosjektet og lærte noe nytt av det. Hvis du har spørsmål, la dem være i kommentarseksjonen eller bruk forumene til andre tekniske diskusjoner.