- Schema elettrico
- Generazione di segnali PWM sul pin GPIO per il controllo del servomotore
- Programmazione PIC16F8771A per braccio robotico
- Simulazione del codice del braccio robotico PIC
- Progettazione PCB utilizzando EasyEDA
- Calcolo e ordinazione di campioni online
- Funzionamento del braccio robotico PIC
Dalla catena di montaggio delle industrie di produzione automobilistica ai robot di telechirurgia nello spazio, i bracci robotici si trovano ovunque. I meccanismi di questi robot sono simili a quelli umani che possono essere programmati per funzioni simili e maggiori capacità. Possono essere utilizzati per eseguire azioni ripetute in modo più rapido e accurato degli esseri umani o possono essere utilizzati in ambienti difficili senza rischiare la vita umana. Abbiamo già costruito un Braccio Robotico Registra e Riproduci utilizzando Arduino che potrebbe essere addestrato per svolgere un compito particolare e fatto ripetere per sempre.
In questo tutorial useremo il microcontrollore a 8 bit PIC16F877A standard del settore per controllare lo stesso braccio robotico con potenziometri. La sfida con questo progetto è che PIC16F877A ha solo due pin compatibili con PWN, ma dobbiamo controllare circa 5 servomotori per il nostro robot che richiede 5 pin PWM individuali. Quindi dobbiamo utilizzare i pin GPIO e generare segnali PWM sui pin GPIO PIC usando gli interrupt del timer. Ora, ovviamente, potremmo passare a un microcontrollore migliore o utilizzare un IC de-multiplexer per rendere le cose molto più semplici qui. Tuttavia, vale la pena provare questo progetto per l'esperienza di apprendimento.
La struttura meccanica del braccio robotico che sto utilizzando in questo progetto è stata completamente stampata in 3D per il mio progetto precedente; puoi trovare i file di progettazione completi e la procedura di assemblaggio qui. In alternativa, se non hai una stampante 3D puoi anche costruire un semplice Braccio Robotico utilizzando dei cartoncini come mostrato nel link. Supponendo che tu abbia in qualche modo impegnato il tuo braccio robotico, procediamo nel progetto.
Schema elettrico
Di seguito è mostrato lo schema circuitale completo per questo braccio robotico basato su microcontrollore PIC. Gli schemi sono stati disegnati utilizzando EasyEDA.
Lo schema del circuito è piuttosto semplice; il progetto completo è alimentato dall'adattatore 12V. Questo 12V viene quindi convertito in + 5V utilizzando due regolatori di tensione 7805. Uno è etichettato come + 5V e l'altro è etichettato come + 5V (2). Il motivo per avere due regolatori è che quando il servo ruota, attira molta corrente che crea una caduta di tensione. Questa caduta di tensione costringe il PIC a riavviarsi, quindi non possiamo azionare sia il PIC che i servomotori sulla stessa linea + 5V. Quindi quello etichettato come + 5V viene utilizzato per alimentare il microcontrollore PIC, LCD e potenziometri e un'uscita del regolatore separata che è etichettata come + 5V (2) viene utilizzata per alimentare i servomotori.
I cinque pin di uscita dei potenziometri che forniscono una tensione variabile da 0V a 5V sono collegati ai pin analogici da An0 a AN4 del PIC. Poiché abbiamo in programma di utilizzare timer per generare PWM, i servomotori possono essere collegati a qualsiasi pin GPIO. Ho selezionato i pin da RD2 a RD6 per i servomotori, ma può essere qualsiasi GPIO di tua scelta.
Dato che il programma richiede molto debugging, anche un display LCD 16x2 è interfacciato alla porta B del PIC. Questo visualizzerà il ciclo di lavoro dei servomotori che vengono controllati. Oltre a questo, ho anche esteso le connessioni per tutti i pin GPIO e analogici, nel caso in cui in futuro dovessero essere interfacciati sensori. Infine ho anche collegato il pin del programmatore H1 per programmare direttamente il PIC con pickit3 utilizzando l'opzione di programmazione ICSP.
Generazione di segnali PWM sul pin GPIO per il controllo del servomotore
Una volta che il circuito è pronto, dobbiamo capire come generare segnali PWN sul pin GPIO del PIC per controllare il servomotore. Abbiamo già stancato qualcosa di simile usando il metodo di interruzione del timer e abbiamo avuto successo. Qui ci limiteremo a costruire sopra di esso, quindi se sei nuovo qui, ti consiglio vivamente di leggere questo tutorial precedente prima di procedere oltre.
Tutti i servomotori per hobby funzionano con una frequenza di 50Hz. Significa che un ciclo di impulsi completo per un servomotore sarà 1/50 (F = 1 / T) che è 20 ms. Di questi 20ms completi il segnale di controllo è solo da 0 a 2ms mentre il resto del segnale è sempre spento. La figura seguente mostra come il tempo di accensione varia solo da 0 a 2 ms per ruotare il motore da 0 gradi a 180 gradi della durata totale di 20 ms.
Con questo in mente dobbiamo scrivere il programma in modo tale che il PIC legga da 0 a 1204 dal potenziometro e lo mappi da 0 a 100 che sarà il duty cycle del servomotore. Utilizzando questo ciclo di lavoro possiamo calcolare il tempo di accensione del servomotore. Quindi possiamo inizializzare l'interruzione del timer per overflow a intervalli regolari in modo che agisca in modo simile alla funzione millis () in Arduino. Con ciò, possiamo impostare lo stato del pin GPIO su alto per una durata desiderata e spegnerlo dopo 20 ms (un ciclo completo) e quindi ripetere lo stesso processo. Ora che abbiamo capito la logica, entriamo nel programma.
Programmazione PIC16F8771A per braccio robotico
Come sempre il programma completo con un video si trova alla fine di questa pagina, anche il codice può essere scaricato da qui con tutti i file necessari. In questa sezione discuteremo la logica alla base del programma. Il programma utilizza il modulo ADC, il modulo timer e il modulo LCD per controllare il braccio robotico. Se non sei a conoscenza di come utilizzare le funzionalità ADC o Timer o per interfacciare un LCD con PIC, puoi tornare ai rispettivi collegamenti per apprenderle. La spiegazione seguente viene fornita supponendo che il lettore abbia familiarità con questi concetti.
Configurazione porta timer 0
La sezione più importante del codice è l' impostazione del timer 0 in overflow per ogni ritardo specifico. Le formule per calcolare questo ritardo possono essere fornite come
Ritardo = ((256-REG_val) * (Prescal * 4)) / Fosc
Utilizzando i registri OPTION_REG e TMR0 abbiamo impostato il Timer 0 per funzionare con un valore prescalar di 32 e il REG val è impostato a 248. La frequenza del cristallo (Fosc) utilizzata nel nostro hardware è 20Mhz. Con questi valori il ritardo può essere calcolato come
Ritardo = ((256-248) * (32 * 4)) / (20000000) = 0,0000512 secondi (o) = 0,05 msec
Quindi ora abbiamo impostato il timer in overflow ogni 0,05 ms. Il codice per fare lo stesso è fornito di seguito
/ ***** Configurazione porta per timer ****** / OPTION_REG = 0b00000100; // Timer0 con freq esterna e 32 come prescalar // Abilita anche PULL UP TMR0 = 248; // Carica il valore temporale per 0.0001s; delayValue può essere compreso tra 0 e 256 solo TMR0IE = 1; // Abilita il bit di interrupt del timer nel registro PIE1 GIE = 1; // Abilita interrupt globale PEIE = 1; // Abilita l'interruzione periferica / *********** ______ *********** /
Della finestra di controllo totale da 0ms a 2ms del servomotore possiamo controllarla con una risoluzione di 0.05msec, che ci permette di avere (2 / 0.05) 40 diverse posizioni per il motore tra 0 gradi e 180 gradi. È possibile diminuire ulteriormente questo valore se il proprio MCU può supportarlo per ottenere più posizioni e un controllo preciso.
Interrupt Service Routine (ISR)
Ora che abbiamo il timer 0 impostato su overflow per ogni 0,05 ms, avremo il flag di interrupt TMR0IF impostato per 0,05 ms. Quindi all'interno della funzione ISR possiamo resettare quel flag e incrementare una variabile chiamata count di uno. Quindi ora questa variabile verrà incrementata di 1 ogni 0,05 ms.
void interrupt timer_isr () { if (TMR0IF == 1) // Il flag del timer è stato attivato a causa dell'overflow del timer -> impostato su overflow per ogni 0,05 ms { TMR0 = 248; // Carica il timer Value TMR0IF = 0; // Cancella il conteggio dei flag di interruzione del timer ++; // Conta gli incrementi di 1 per ogni 0,05 ms }
Calcolo del ciclo di lavoro e della puntualità
Successivamente dobbiamo calcolare il ciclo di lavoro e il tempo per tutti e cinque i servomotori. Abbiamo cinque servomotori ciascuno dei quali viene utilizzato per controllare la singola sezione del braccio. Quindi dobbiamo leggere il valore ADC di tutti e cinque e calcolare il ciclo di lavoro e in tempo per ciascuno.
Il valore ADC sarà compreso tra 0 e 1024, che può essere convertito in un duty cycle da 0% a 100% semplicemente moltiplicando 0,0976 (100/1024 = 0,0976) per il valore ottenuto. Questo ciclo di lavoro da 0 a 100% deve essere quindi convertito in tempo ON. Sappiamo che con un duty cycle del 100% il tempo di attivazione deve essere di 2 ms (per 180 gradi), quindi moltiplicando 0,02 (2/100 = 0,02) si convertirà da 0 a 100 duty cycle in 0 a 2 ms. Ma poi il conteggio della nostra variabile del timer è impostato per aumentare una volta ogni 0,05 ms. Ciò significa che il valore del conteggio sarà 20 (1 / 0,05 = 20) per ogni 1 ms. Quindi dobbiamo moltiplicare 20 per 0,02 per calcolare l'esatta puntualità per il nostro programma che ci darà il valore 0,4 (0,02 * 20 = 0,4). Il codice per lo stesso è mostrato sotto, puoi vederlo ripetuto per 5 volte per tutti e 5 i piatti usando un ciclo for. I valori risultanti vengono memorizzati nella matrice T_ON.
for (int pot_num = 0; pot_num <= 3; pot_num ++) { int Pev_val = T_ON; POT_val = (ADC_Read (pot_num)); // Leggi il valore di POT usando ADC Duty_cycle = (POT_val * 0.0976); // Mappa da 0 a 1024 a 0 a 100 T_ON = Duty_cycle * 0.4; // 20 * 0.02
Selezione del motore da ruotare
Non possiamo controllare tutti e cinque i motori insieme in quanto renderà il codice ISR pesante rallentando l'intero microcontrollore. Quindi dobbiamo ruotare solo un servomotore alla volta. Per selezionare quale servo ruotare il microcontrollore controlla il tempo di accensione di tutti e cinque i servomotori e lo confronta con il tempo precedente. Se c'è un cambiamento nel tempo ON, possiamo concludere che il servo particolare deve essere spostato. Il codice per lo stesso è mostrato di seguito.
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');
Stampiamo anche il ciclo di lavoro del servo sullo schermo LCD in modo che l'utente possa essere consapevole della sua posizione attuale. In base alla variazione del tempo di accensione, il servo variabile viene aggiornato con numeri da 0 a 4 ciascuno che rappresenta i singoli motori.
Controllo del servomotore all'interno dell'ISR
All'interno dell'ISR abbiamo il conteggio della variabile che viene incrementato ogni 0,05 ms, questo significa che per ogni 1 ms la variabile verrà incrementata di 20. Usando questo dobbiamo controllare i pin per produrre il segnale PWM. Se il valore di conteggio è inferiore al tempo di accensione, il GPIO di quel motore viene acceso utilizzando la riga sottostante
PORTD = PORTD - servo_code;
Qui l'array servo_code ha i dettagli dei pin di tutti e cinque i servomotori e in base al valore in servo variabile, verrà utilizzato il codice per quel particolare servomotore. È quindi logicamente OR (-) con i bit PORTD esistenti in modo da non disturbare i valori di altri motori e aggiornare solo questo particolare motore. Allo stesso modo per spegnere il perno
PORTD = PORTD & ~ (servo_code);
Abbiamo invertito il valore del bit utilizzando l'operatore logico inverso (~) e quindi abbiamo eseguito un'operazione AND (&) sul PORTD per disattivare solo il pin desiderato lasciando gli altri pin nello stato precedente. Lo snippet di codice completo è mostrato di seguito.
void interrupt timer_isr () { if (TMR0IF == 1) // Il flag del timer è stato attivato a causa dell'overflow del timer -> impostato su overflow per ogni 0,05 ms { TMR0 = 248; // Carica il timer Value TMR0IF = 0; // Cancella il conteggio dei flag di interrupt del timer ++; // Conta incrementi di 1 per ogni 0,05 ms -> il conteggio sarà 20 per ogni 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; altrimenti PORTD = PORTD & ~ (servo_code); }
Sappiamo che il ciclo totale deve durare per 20 ms prima che il pin GPIO venga riattivato. Quindi controlliamo se il conteggio ha superato i 20 ms confrontando il valore di count con 400 (stesso calcolo discusso sopra) e in caso affermativo dobbiamo inizializzare il conteggio per essere nuovamente zero.
Simulazione del codice del braccio robotico PIC
È sempre meglio simulare il codice prima di portarlo sull'hardware reale. Quindi ho usato Proteus per simulare il mio codice e verificato che funzionasse correttamente. Il circuito utilizzato per la simulazione è mostrato di seguito. Abbiamo utilizzato un oscilloscopio per verificare se i segnali PWM vengono generati come richiesto. Inoltre possiamo verificare se l'LCD e i servomotori stanno ruotando come previsto.
Come puoi vedere, il display LCD visualizza il duty cycle del motore D in modo che sia 07 in base al valore del potenziometro che è il 3 ° motore. Analogamente, se viene spostata un'altra pentola, il ciclo di lavoro di quella pentola e il suo numero di motore verranno visualizzati sul display LCD. Di seguito è mostrato il segnale PWM mostrato sull'oscilloscopio.
Il periodo di ciclo totale viene misurato in 22,2 ms utilizzando l'opzione cursore sull'oscilloscopio, che è molto vicino ai 20 ms desiderati. Finalmente siamo sicuri che il codice funzioni, quindi per continuare con il circuito possiamo saldarlo su una scheda perf o utilizzare un PCB. Non funzionerà facilmente sulla breadboard perché il POT tende sempre a dare qualche problema a causa delle cattive connessioni.
Progettazione PCB utilizzando EasyEDA
Per progettare questo braccio robotico PIC, abbiamo scelto lo strumento EDA online chiamato EasyEDA. Lo uso da molto tempo e lo trovo molto conveniente per la sua vasta disponibilità di impronta e per la sua natura facile da usare. Dopo aver progettato il PCB, possiamo ordinare i campioni di PCB tramite i loro servizi di fabbricazione di PCB a basso costo. Offrono anche un servizio di approvvigionamento di componenti in cui hanno un ampio stock di componenti elettronici e gli utenti possono ordinare i componenti richiesti insieme all'ordine del PCB.
Durante la progettazione dei tuoi circuiti e PCB, puoi anche rendere pubblici i tuoi progetti di circuiti e PCB in modo che altri utenti possano copiarli o modificarli e possano trarre vantaggio dal tuo lavoro, abbiamo anche reso pubblici tutti i nostri layout di circuiti e PCB per questo circuito, controlla il link sottostante:
easyeda.com/circuitdigest/pic-development-board-for-robotic-arm
Usando questo link puoi ordinare direttamente lo stesso PCB che stiamo usando in questo progetto e usarlo. Una volta completato il progetto, la scheda può essere visualizzata come un modello 3D che sarà molto utile per visualizzare come apparirà la scheda dopo la fabbricazione. Di seguito è mostrato il modello 3D della scheda che stiamo utilizzando. Oltre a questo puoi anche visualizzare il livello superiore e inferiore della scheda per verificare se lo schermo liscio è come previsto.
Calcolo e ordinazione di campioni online
Dopo aver completato la progettazione di questo PCB per robot PIC, è possibile ordinare il PCB tramite JLCPCB.com. Per ordinare il PCB da JLCPCB, è necessario Gerber File. Per scaricare i file Gerber del tuo PCB, fai clic sul pulsante Genera file di fabbricazione nella pagina dell'editor EasyEDA, quindi scarica il file Gerber da lì oppure puoi fare clic su Ordina su JLCPCB come mostrato nell'immagine sottostante. Questo ti reindirizzerà a JLCPCB.com, dove puoi selezionare il numero di PCB che desideri ordinare, quanti strati di rame ti servono, lo spessore del PCB, il peso del rame e persino il colore del PCB, come l'istantanea mostrata di seguito:
Dopo aver selezionato tutte le opzioni, fai clic su "Salva nel carrello" e verrai portato alla pagina in cui puoi caricare il tuo file Gerber che abbiamo scaricato da EasyEDA. Carica il tuo file Gerber e fai clic su "Salva nel carrello". Infine, fai clic su Checkout Securely per completare l'ordine, quindi riceverai i tuoi PCB pochi giorni dopo. Stanno fabbricando il PCB a un prezzo molto basso che è di $ 2. Anche il loro tempo di costruzione è molto inferiore, ovvero 48 ore con consegna DHL di 3-5 giorni, in pratica riceverai i tuoi PCB entro una settimana dall'ordine.
Dopo aver ordinato il PCB, puoi controllare lo stato di avanzamento della produzione del tuo PCB con data e ora. Puoi verificarlo andando nella pagina Account e facendo clic su "Avanzamento produzione".
Dopo pochi giorni dall'ordinazione di PCB, ho ricevuto i campioni di PCB in una bella confezione come mostrato nelle immagini sottostanti.
E dopo aver ottenuto questi pezzi ho saldato tutti i componenti richiesti sul PCB. Ho anche saldato direttamente il POT direttamente invece di usare i cavi di collegamento perché i fili femmina-femmina che ho usato inizialmente dovevano fornire strane tensioni di uscita analogiche probabilmente a causa di contatti allentati. Una volta che tutti i componenti sono stati assemblati, il mio PCB sembrava qualcosa di simile.
Potresti aver notato che c'è solo un 7805 su questa scheda. Questo perché inizialmente pensavo di poter farla franca solo con il regolatore per alimentare sia il PIC che il servomotore e in seguito ho capito che ne avevo bisogno di due. Quindi ho usato un circuito esterno per alimentare i servomotori attraverso i fili verdi che vedi qui.
Tuttavia non devi preoccuparti molto perché; Ora ho apportato le modifiche al PCB. È possibile utilizzare il PCB modificato e saldare entrambi i regolatori a bordo stesso.
Funzionamento del braccio robotico PIC
Dopo tutto il lavoro faticoso è tempo di ripagare. Saldare tutti i componenti sulla scheda e caricare il programma sul controller PIC. Il codice completo è fornito di seguito o può essere scaricato da qui. Il connettore di programmazione fornito sulla scheda dovrebbe aiutarti a caricare il programma direttamente utilizzando Pickit 3 senza troppi problemi. Una volta caricato il programma dovresti vedere il display LCD che mostra il servo che è attualmente controllato. Per saperne di più sulla programmazione del microcontrollore PIC, basta seguire il tutorial precedente.
Da lì puoi semplicemente girare la pentola e controllare come i servomotori rispondono a ciascun potenziometro. Una volta compreso il formato, puoi controllare il braccio robotico per eseguire qualsiasi azione tu abbia bisogno per eseguire e divertirti. Potete trovare il funzionamento completo del progetto nel video linkato sotto.
Questo è tutto, ragazzi, spero che abbiate capito il progetto e da esso abbia imparato qualcosa di nuovo. Se hai domande, lasciale nella sezione commenti o usa i forum per altre discussioni tecniche.