- Diagrama circuitului
- Generarea semnalelor PWM pe pinul GPIO pentru Servo Motor Control
- Programare PIC16F8771A pentru braț robotizat
- Simularea codului PIC Robotic Arm
- Proiectare PCB folosind EasyEDA
- Calcularea și comandarea eșantioanelor online
- Funcționarea brațului robotic PIC
De la linia de asamblare a industriilor producătoare de automobile până la roboții de telesurgie din spațiu, brațele robotice se găsesc peste tot. Mecanismele acestor roboți sunt similare cu un om care poate fi programat pentru funcții similare și capacități sporite. Ele pot fi utilizate pentru a efectua acțiuni repetate mai rapide și mai precise decât oamenii sau pot fi utilizate în medii dure fără a risca viața umană. Am construit deja un braț robotizat de înregistrare și redare folosind Arduino, care ar putea fi instruiți să facă o anumită sarcină și să fie repetat pentru totdeauna.
În acest tutorial vom folosi standardul industrial PIC16F877A Microcontroler pe 8 biți pentru a controla același braț robotizat cu potențiometre. Provocarea acestui proiect este că PIC16F877A are doar doi pini capabili PWN, dar trebuie să controlăm aproximativ 5 servo-motoare pentru robotul nostru care necesită 5 pini PWM individuali. Deci, trebuie să folosim pinii GPIO și să generăm semnale PWM pe pinii GPIO PIC folosind întreruperile temporizatorului. Acum, bineînțeles, am putea face upgrade la un microcontroler mai bun sau să folosim un IC de multiplexor pentru a face lucrurile mult mai ușoare aici. Dar totuși, merită să încercați acest proiect pentru experiența de învățare.
Structura mecanică a brațului robotizat pe care o folosesc în acest proiect a fost complet imprimată 3D pentru proiectul meu anterior; aici puteți găsi fișierele complete de proiectare și procedura de asamblare. Alternativ, dacă nu aveți o imprimantă 3D, puteți construi, de asemenea, un braț robotizat simplu folosind cartoane, așa cum se arată în link. Presupunând că într-un fel ai pus mâna pe brațul tău robotizat, poți continua proiectul.
Diagrama circuitului
Diagrama completă a circuitului pentru acest braț robotizat bazat pe microcontroler PIC este prezentată mai jos. Schemele au fost desenate folosind EasyEDA.
Diagrama circuitului este destul de simplă; proiectul complet este alimentat de adaptorul de 12V. Acest 12V este apoi convertit la + 5V folosind două regulatoare de tensiune 7805. Unul este etichetat ca + 5V, iar celălalt este etichetat ca + 5V (2). Motivul pentru care există două regulatoare este că atunci când servo-ul se rotește, trage mult curent, ceea ce creează o cădere de tensiune. Această cădere de tensiune forțează PIC-ul să se repornească singur, prin urmare nu putem opera atât PIC, cât și servomotorele pe aceeași șină + 5V. Deci, cel etichetat ca + 5V este utilizat pentru alimentarea microcontrolerului PIC, LCD și potențiometrelor și o ieșire separată a regulatorului care este etichetată ca + 5V (2) este utilizată pentru alimentarea servomotorelor.
Cei cinci pini de ieșire ai potențiometrelor care furnizează o tensiune variabilă de la 0V la 5V sunt conectați la pinii analogici An0 la AN4 ai PIC. Deoarece intenționăm să folosim temporizatoare pentru a genera PWM, servomotorele pot fi conectate la orice pin GPIO. Am selectat pinii de la RD2 la RD6 pentru servomotori, dar poate fi orice GPIO la alegere.
Deoarece programul implică o mulțime de depanare, un afișaj LCD de 16x2 este, de asemenea, interfațat cu portul B al PIC. Aceasta va afișa ciclul de funcționare al servomotorelor care sunt controlate. În afară de aceasta, am extins și conexiunile pentru toate pin-urile GPIO și analogice, doar în cazul în care este nevoie de interfață a unor senzori în viitor. În cele din urmă, am conectat și pinul programatorului H1 pentru a programa direct PIC cu pickit3 folosind opțiunea de programare ICSP.
Generarea semnalelor PWM pe pinul GPIO pentru Servo Motor Control
Odată ce circuitul este gata, trebuie să ne dăm seama cum să generăm semnale PWN pe pinul GPIO al PIC pentru a controla servomotorul. Am obosit deja ceva similar folosind metoda de întrerupere Timer și am avut succes. Aici vom construi doar deasupra acestuia, așa că, dacă sunteți nou aici, vă recomand cu tărie să citiți acest tutorial anterior înainte de a continua mai departe.
Toate servomotorele hobby funcționează cu o frecvență de 50Hz. Adică un ciclu de impuls complet pentru un servomotor va fi 1/50 (F = 1 / T), care este de 20 ms. Din acest 20ms complet semnalul de control este doar de la 0 la 2ms în timp ce restul semnalului este întotdeauna oprit. Figura de mai jos arată cum timpul de pornire variază doar de la 0 la 2 ms pentru a roti motorul de la 0 la 180 de grade din durata totală de 20 ms.
Având în vedere acest lucru, trebuie să scriem programul în așa fel încât PIC să citească de la 0 la 1204 din potențiometru și să îl mapeze la 0 la 100, care va fi ciclul de funcționare al servomotorului. Folosind acest ciclu de lucru putem calcula timpul de pornire al servomotorului. Apoi putem inițializa întreruperea temporizatorului pentru a revărsa la un interval regulat astfel încât să acționeze similar cu funcția millis () din Arduino. Cu aceasta, putem comuta pinul de stare GPIO pentru a fi ridicat pentru o durată dorită și îl putem opri după 20 ms (un ciclu complet) și apoi repeta același proces. Acum, că am înțeles logica, ne permite să intrăm în program.
Programare PIC16F8771A pentru braț robotizat
Ca întotdeauna programul complet cu un videoclip poate fi găsit la sfârșitul acestei pagini, codul poate fi descărcat și de aici cu toate fișierele necesare. În această secțiune vom discuta despre logica din spatele programului. Programul folosește modulul ADC, modulul temporizator și modulul LCD pentru a controla brațul robotizat. Dacă nu sunteți conștienți de modul de utilizare a funcțiilor ADC sau a funcțiilor Timer sau pentru interfața unui LCD cu PIC, atunci puteți reveni la linkurile respective pentru a le învăța. Explicația de mai jos este dată presupunând că cititorul este familiarizat cu aceste concepte.
Configurarea portului Timer 0
Cea mai importantă secțiune din cod este setarea cronometrului 0 la un flux de peste pentru fiecare întârziere specifică. Formulele pentru calcularea acestei întârzieri pot fi date ca
Întârziere = ((256-REG_val) * (Prescal * 4)) / Fosc
Prin utilizarea registrului OPTION_REG și TMR0, am setat Temporizatorul 0 să funcționeze cu o valoare prescalar de 32 și valea REG este setată la 248. Frecvența cristalului (Fosc) utilizat în hardware-ul nostru este de 20Mhz. Cu aceste valori întârzierea poate fi calculată ca
Întârziere = ((256-248) * (32 * 4)) / (20000000) = 0,0000512 secunde (sau) = 0,05 msec
Așadar, acum am setat temporizatorul să revarsă la fiecare 0,05 ms. Codul pentru a face același lucru este dat mai jos
/ ***** Port Configuration for Timer ****** / OPTION_REG = 0b00000100; // Timer0 cu frecvență externă și 32 ca prescalar // De asemenea, activează PULL UP TMR0 = 248; // Încărcați valoarea timpului pentru 0.0001s; delayValue poate fi între 0-256 numai TMR0IE = 1; // Activați bitul de întrerupere a temporizatorului în registrul PIE1 GIE = 1; // Activați Global Interrupt PEIE = 1; // Activați întreruperea periferică / *********** ______ *********** /
Din fereastra de control totală de la 0ms la 2ms a servomotorului o putem controla cu o rezoluție de 0,05msec, ceea ce ne permite să avem (2 / 0,05) 40 de poziții diferite pentru motor între 0 și 180 de grade. Puteți reduce această valoare în continuare dacă MCU-ul dvs. ar putea să o susțină pentru a obține mai multe poziții și un control precis.
Rutina serviciului de întrerupere (ISR)
Acum că avem Timerul 0 setat pentru a depăși fluxul la fiecare 0,05 ms, vom avea semnalul de întrerupere TMR0IF setat pentru 0,05 ms. Deci, in interiorul functiei ISR putem reseta că pavilion și incrementa o variabilă numită count de unul. Deci, acum această variabilă va fi incrementată cu 1 pentru fiecare 0,05 ms.
void interrupt timer_isr () { if (TMR0IF == 1) // Timer flag a fost declanșat din cauza depășirii temporizatorului -> setat la depășire pentru fiecare 0.05ms { TMR0 = 248; // Încărcați temporizatorul Valoare TMR0IF = 0; // Ștergeți numărul de semnal de întrerupere a temporizatorului ++; // Numărați incrementele cu 1 pentru fiecare 0,05 ms }
Calculul ciclului de funcționare și la timp
Apoi, trebuie să calculăm ciclul de funcționare și la timp pentru toți cei cinci servomotori. Avem cinci servomotoare, fiecare dintre ele fiind utilizat pentru controlul secțiunii individuale a brațului. Deci, trebuie să citim valoarea ADC a tuturor celor cinci și să calculăm ciclul de funcționare și la timp pentru fiecare.
Valoarea ADC va fi în intervalul de la 0 la 1024, care poate fi convertită la 0% la 100% ciclu de funcționare prin simpla multiplicare a 0,0976 (100/1024 = 0,0976) la valoarea obținută. Acest ciclu de funcționare de la 0 la 100% trebuie apoi convertit la timpul de pornire. Știm că la un ciclu de funcționare de 100% timpul de pornire trebuie să fie de 2 ms (pentru 180 de grade), deci înmulțirea 0,02 (2/100 = 0,02) va converti ciclul de funcționare de la 0 la 100 la 0 la 2 ms. Dar apoi numărul de variabile ale temporizatorului este setat să crească o dată la fiecare 0,05 ms. Aceasta înseamnă că valoarea numărării va fi de 20 (1 / 0,05 = 20) pentru fiecare 1 ms. Deci, trebuie să înmulțim 20 cu 0,02 pentru a calcula exact la timp pentru programul nostru, care ne va da valoarea 0,4 (0,02 * 20 = 0,4). Codul pentru același lucru este prezentat mai jos, îl puteți vedea repetat de 5 ori pentru toate cele 5 poturi folosind o buclă for. Valorile rezultate sunt stocate în matricea T_ON.
for (int pot_num = 0; pot_num <= 3; pot_num ++) { int Pev_val = T_ON; POT_val = (ADC_Read (pot_num)); // Citiți valoarea POT folosind ADC Duty_cycle = (POT_val * 0.0976); // Harta de la 0 la 1024 la 0 la 100 T_ON = Duty_cycle * 0,4; // 20 * 0,02
Selectarea motorului de rotit
Nu putem controla toate cele cinci motoare împreună, deoarece va face ca codul ISR să încetinească întregul microcontroler. Deci, trebuie să rotim un singur servomotor odată. Pentru a selecta care servo să se rotească, microcontrolerul monitorizează timpul de pornire al tuturor celor cinci servo-motoare și îl compară cu timpul anterior. Dacă există o modificare a timpului de pornire, putem concluziona că servo-ul special trebuie mutat. Codul pentru același lucru este prezentat mai jos.
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');
De asemenea, imprimăm ciclul de servodirecție pe ecranul LCD, astfel încât utilizatorul să poată fi conștient de poziția sa actuală. Pe baza schimbării timpului de pornire, servo-ul variabil este actualizat cu numere de la 0 la 4, fiecare reprezentând motoare individuale.
Controlul servomotorului din interiorul ISR
În cadrul ISR avem creșterea numărului de variabile pentru fiecare 0,05 ms, ceea ce înseamnă că pentru fiecare 1 ms variabila va fi incrementată cu 20. Folosind aceasta trebuie să controlăm pinii pentru a produce semnal PWM. Dacă valoarea numărării este mai mică decât timpul, GPIO-ul motorului respectiv este pornit folosind linia de mai jos
PORTD = PORTD - servo_code;
Aici matricea servo_code conține detaliile pinului tuturor celor cinci servo-motor și, pe baza valorii în servo variabil, va fi utilizat codul pentru servo-motorul respectiv. Apoi, este logic SAU (-) cu biții PORTD existenți, astfel încât să nu deranjăm valorile altor motoare și să actualizăm doar acest motor special. În mod similar pentru oprirea știftului
PORTD = PORTD & ~ (servo_code);
Am inversat valoarea bitului folosind operatorul logic invers (~) și apoi am efectuat o operație AND (&) pe PORTD pentru a opri doar pinul dorit, lăsând în același timp ceilalți pin în starea lor anterioară. Fragmentul de cod complet este prezentat mai jos.
void interrupt timer_isr () { if (TMR0IF == 1) // Timer flag a fost declanșat din cauza depășirii temporizatorului -> setat la depășire pentru fiecare 0,05 ms { TMR0 = 248; // Încărcați temporizatorul Valoare TMR0IF = 0; // Ștergeți numărul de semnal de întrerupere a temporizatorului ++; // Incremente de numărare cu 1 pentru fiecare 0,05 ms -> numărarea va fi de 20 pentru fiecare 1 ms (0,05 / 1 = 20)) } int servo_code = {0b01000000, 0b00100000, 0b00010000, 0b00001000, 0b00000100}; if (count> = 20 * 20) count = 0; if (count <= (T_ON)) PORTD = PORTD - servo_code; else PORTD = PORTD & ~ (servo_code); }
Știm că ciclul total trebuie să dureze 20 ms înainte ca pinul GPIO să fie pornit din nou. Deci, verificăm dacă numărul a depășit 20 ms comparând valoarea numărului cu 400 (același calcul așa cum am discutat mai sus) și dacă da, trebuie să inițializăm numărul pentru a fi din nou zero.
Simularea codului PIC Robotic Arm
Este întotdeauna mai bine să simulați codul înainte de a-l duce la hardware-ul real. Așa că am folosit Proteus pentru a-mi simula codul și l-am verificat pentru a funcționa corect. Circuitul utilizat pentru simulare este prezentat mai jos. Am folosit un osciloscop pentru a verifica dacă semnalele PWM sunt generate în funcție de necesități. De asemenea, putem verifica dacă motoarele LCD și Servo se rotesc conform așteptărilor.
După cum puteți vedea, ecranul LCD afișează ciclul de funcționare al motorului D să fie 07 pe baza valorii potului, care este al treilea motor. Similar, dacă un alt pot este mutat, ciclul de funcționare al potului respectiv și numărul motorului acestuia vor fi afișate pe ecranul LCD. Semnalul PWM afișat pe osciloscop este prezentat mai jos.
Perioada ciclului total este măsurată la 22,2 ms, folosind opțiunea cursor de pe osciloscop, care este foarte aproape de 20 ms dorită. În cele din urmă, suntem siguri că codul funcționează, așa că, pentru a continua cu circuitul, îl putem lipi pe o placă de perfecționare sau putem folosi un PCB. Nu va funcționa ușor pe panou, deoarece POT tinde întotdeauna să ofere unele probleme din cauza conexiunilor slabe.
Proiectare PCB folosind EasyEDA
Pentru a proiecta acest braț robot PIC, am ales instrumentul EDA online numit EasyEDA. Îl folosesc de mult timp și îl găsesc foarte convenabil din cauza disponibilității sale vaste de amprentă și a naturii ușor de utilizat. După proiectarea PCB-ului, putem comanda probele de PCB după serviciile lor de fabricare a PCB-urilor cu costuri reduse. De asemenea, oferă servicii de aprovizionare a componentelor, unde au un stoc mare de componente electronice, iar utilizatorii pot comanda componentele necesare împreună cu comanda PCB.
În timp ce vă proiectați circuitele și PCB-urile, puteți, de asemenea, să vă faceți publice circuitele și PCB-urile, astfel încât ceilalți utilizatori să le poată copia sau edita și să poată profita de munca dvs. linkul de mai jos:
easyeda.com/circuitdigest/pic-development-board-for-robotic-arm
Folosind acest link puteți comanda direct același PCB pe care îl folosim în acest proiect și îl puteți utiliza. Odată ce designul este complet, placa poate fi vizualizată ca model 3D, ceea ce va fi foarte util în vizualizarea modului în care ar apărea placa după fabricare. Modelul 3D al plăcii pe care o folosim este prezentat mai jos. În afară de aceasta, puteți vizualiza și stratul superior și inferior al plăcii pentru a verifica dacă ecranul slick este așa cum era de așteptat.
Calcularea și comandarea eșantioanelor online
După finalizarea proiectării acestui PCB robot PIC, puteți comanda PCB prin JLCPCB.com. Pentru a comanda PCB-ul de la JLCPCB, aveți nevoie de Gerber File. Pentru a descărca fișierele Gerber ale PCB-ului dvs., faceți clic pe butonul Generați fișierul de fabricație de pe pagina editorului EasyEDA, apoi descărcați fișierul Gerber de acolo sau puteți face clic pe Comandă la JLCPCB așa cum se arată în imaginea de mai jos. Acest lucru vă va redirecționa către JLCPCB.com, unde puteți selecta numărul de PCB-uri pe care doriți să le comandați, de câte straturi de cupru aveți nevoie, grosimea PCB-ului, greutatea cuprului și chiar culoarea PCB-ului, cum ar fi instantaneul prezentat mai jos:
După ce ați selectat toate opțiunile, faceți clic pe „Salvați în coș” și apoi veți fi direcționat la pagina de unde puteți încărca fișierul Gerber pe care l-am descărcat din EasyEDA. Încărcați fișierul Gerber și faceți clic pe „Salvați în coș”. Și, în cele din urmă, faceți clic pe Checkout Securely pentru a finaliza comanda, apoi veți primi PCB-urile câteva zile mai târziu. Ei fabrică PCB la o rată foarte mică, care este de 2 USD. Timpul lor de construcție este, de asemenea, foarte redus, adică 48 de ore cu livrare DHL de 3-5 zile, practic veți primi PCB-urile dvs. într-o săptămână de la comandă.
După ce ați comandat PCB-ul, puteți verifica progresul producției PCB-ului dvs. cu data și ora. O verificați accesând pagina Contului și faceți clic pe „Progresul producției”.
După câteva zile de a comanda PCB-uri, am obținut probele de PCB într-un ambalaj frumos, așa cum se arată în imaginile de mai jos.
Și după ce am primit aceste piese, am lipit toate componentele necesare peste PCB. De asemenea, am lipit direct POT-ul în loc să folosesc fire de conectare, deoarece firele de la mamă la mamă pe care le-am folosit inițial, oferind tensiuni de ieșire analogice ciudate, probabil din cauza contactelor libere. Odată ce toate componentele au fost asamblate, PCB-ul meu arăta cam așa.
Este posibil să fi observat că există doar un 7805 pe această placă. Asta pentru că inițial am crezut că pot scăpa doar de regulator pentru alimentarea PIC și a servomotorului și ulterior am realizat că am nevoie de două. Așa că am folosit un circuit extern pentru a alimenta servo-motoarele prin firele verzi pe care le vedeți aici.
Cu toate acestea, nu trebuie să vă faceți griji prea mult pentru că; Am făcut modificările PCB acum. Puteți utiliza PCB modificat și puteți lipi ambele regulatoare de la bord.
Funcționarea brațului robotic PIC
După toată munca obositoare, este timpul să plătești. Lipiți toate componentele de pe placă și încărcați programul pe controlerul PIC. Codul complet este dat mai jos sau poate fi descărcat de aici. Conectorul de programare furnizat pe placă ar trebui să vă ajute să încărcați programul direct folosind Pickit 3 fără probleme. Odată ce programul este încărcat, ar trebui să vedeți ecranul LCD afișând servo-ul care este controlat în prezent. Pentru a afla mai multe despre programarea microcontrolerului PIC, trebuie doar să urmați tutorialul anterior.
De acolo puteți pur și simplu roti potul și puteți verifica modul în care servomotorele răspund la fiecare potențiometru. Odată ce înțelegeți formatul, puteți controla brațul robotizat pentru a efectua orice acțiune de care aveți nevoie pentru a efectua și a vă distra. Puteți găsi funcționarea completă a proiectului în videoclipul legat mai jos.
Adică băieții speră că ați înțeles proiectul și ați învățat ceva nou din acesta. Dacă aveți întrebări, lăsați-le în secțiunea de comentarii sau folosiți forumurile pentru alte discuții tehnice.