CORSO BRACCIO ROBOT LEZIONE 6
INDICE
- Avvertenze
- Note sul Copyright
- Controllare un Braccio Robot via BT con HC-05 e PCA9685
- Progetto 12: Controllo e Comando Braccio Robot via BT con PCA9685
- Analisi degli sketch del Progetto 12 – Controllo e Comando Braccio Robot via BT
- PS2 Controller e Arduino UNO
- Progetto 13: Uso del PS2 Controller con Arduino
- Analisi dello sketch del Progetto 13 – Uso del PS2 Controller con Arduino
- Progetto 14: Braccio Robot pilotato con PS2 Controller & Arduino
- Analisi dello sketch del Progetto 14 – Braccio Robot pilotato con PS2 Controller
Avvertenze
Relativamente agli aspetti di sicurezza, poiché i progetti sono basati su alimentazione elettrica in bassissima tensione erogata dalla porta usb del pc o da batterie di supporto o alimentatori con al massimo 9V in uscita, non ci sono particolari rischi di natura elettrica. È comunque doveroso precisare che eventuali cortocircuiti causati in fase di esercitazione potrebbero produrre danni al pc, agli arredi ed in casi estremi anche a ustioni, per tale ragione ogni qual volta si assembla un circuito, o si fanno modifiche su di esso, occorrerà farlo in assenza di alimentazione e al termine dell’esercitazione occorrerà provvedere alla disalimentazione del circuito rimuovendo sia il cavo usb di collegamento al pc che eventuali batterie dai preposti vani o connettori di alimentazione esterna. Inoltre, sempre per ragioni di sicurezza, è fortemente consigliato eseguire i progetti su tappeti isolanti e resistenti al calore acquistabili in un qualsiasi negozio di elettronica o anche sui siti web specializzati.
Al termine delle esercitazioni è opportuno lavarsi le mani, in quanto i componenti elettronici potrebbero avere residui di lavorazione che potrebbero arrecare danno se ingeriti o se a contatto con occhi, bocca, pelle, etc. Sebbene i singoli progetti siano stati testati e sicuri, chi decide di seguire quanto riportato nel presente documento, si assume la piena responsabilità di quanto potrebbe accadere nell’esecuzione delle esercitazioni previste nello stesso. Per i ragazzi più giovani e/o alle prime esperienze nel campo dell’Elettronica, si consiglia di eseguire le esercitazioni con l’aiuto ed in presenza di un adulto.
Note sul Copyright
Tutti i marchi riportati appartengono ai legittimi proprietari; marchi di terzi, nomi di prodotti, nomi commerciali, nomi corporativi e società citati possono essere marchi di proprietà dei rispettivi titolari o marchi registrati d’altre società e sono stati utilizzati a puro scopo esplicativo ed a beneficio del possessore, senza alcun fine di violazione dei diritti di Copyright vigenti. Quanto riportato in questo documento è di proprietà di Roberto Francavilla, ad esso sono applicabili le leggi italiane ed europee in materia di diritto d’autore – eventuali testi prelevati da altre fonti sono anch’essi protetti dai Diritti di Autore e di proprietà dei rispettivi Proprietari. Tutte le informazioni ed i contenuti (testi, grafica ed immagini, etc.) riportate sono, al meglio della mia conoscenza, di pubblico dominio. Se, involontariamente, è stato pubblicato materiale soggetto a copyright o in violazione alla legge si prega di comunicarlo tramite email a info@bemaker.org e provvederò tempestivamente a rimuoverlo.
Roberto Francavilla
Controllare un Braccio Robot via BT con HC-05 e PCA9685
Continuiamo sulla scia delle lezioni precedenti che mostrano le varie modalità di controllo del Braccio Robot e vediamo in questa lezione come combinare l’uso della scheda PCA9685 per il controllo dei servomotori e del modulo Bluetooth HC-05 per il collegamento wireless tra PC e Arduino.
Da un punto di vista hardware utilizzeremo oggetti ben noti per cui non c’è nulla da approfondire, mentre da un punto di vista software dovremo aggiornare sia lo sketch su Arduino che quello su Processing.
Non perdiamo altro tempo passiamo subito all’azione e quindi al Progetto 12.
Progetto 12: Controllo e Comando Braccio Robot via BT con PCA9685
Anche per questo progetto si utilizzerà Processing per creare una fantastica interfaccia grafica che riporta in 3D tutti i movimenti del nostro braccio robotico che comandiamo tramite Arduino.
Descrizione del Progetto 12: impartiremo dei comandi cliccando con il tasto sinistro del mouse su dei bottoni presenti nella pagina grafica riprodotta con Processing su un PC che è collegato tramite il modulo Bluetooth HC-05 ad Arduino. Per verificare i comandi provenienti dal primo PC collegheremo ad Arduino via USB un secondo PC in modo tale da far riprodurre sul monitor seriale i vari comandi ricevuti. Ad Arduino è collegata quindi, tramite I2C la scheda PCA9685 Servormotor Controller che provvederà a smistare i comandi ai singoli servomotori e ad alimentarli. Ovviamente, come ogni mio progetto, esso è da considerarsi solo come punto di partenza anche per i vostri sviluppi e miglioramenti.
Per questo progetto ci occorre:
Andiamo a realizzare quanto rappresentato dagli schemi di montaggio sotto, come ben potete osservare sono in sostanza due sistemi separati, li rappresenterò separatamente anche per migliorarne la lettura, uno schema si occupa della comunicazione Bluetooth e l’altro del comando e controllo del braccio robot attraverso la PCA9685. L’alimentazione dei 7 servo motori è fatta attraverso un alimentatore stabilizzato con tensione a 5 V che va alla PCA9685 che a sua volta provvederà a smistare l’alimentazione ai singoli servo.
Vediamo lo schema da realizzare per la parte relativa alla comunicazione Bluetooth con l’HC-05. Come è possibile osservare è sostanzialmente identico a quanto fatto per il Progetto 5
Per quanto riguarda lo schema da realizzare per il controllo dei servomotori del braccio, potete fare riferimento allo schema sotto:
Durante il montaggio dei circuiti fate attenzione ai colori dei cavi del servo (marrone = GND, rosso = Vcc e arancio = Segnale) ed inoltre poiché sicuramente necessiterete di prolunghe, fate in modo che nei punti di giunzione non vi si creino distaccamenti di cavi mettendo del nastro adesivo di carta.
Nota: per far si che i due circuiti abbiano lo stesso riferimento a massa, i due negativi delle basette vanno collegati. Occorre fare attenzione: se non avete un buon alimentatore, tale collegamento può provocare l’entrata in protezione del PC, per cui in questo caso occorre tenerle separate (per il PC, basta staccarlo dalla rete per 10-15 sec e riattaccarlo).
Lo sketch da caricare su Arduino è il seguente:
Lo sketch da aprire in Processing sul PC è il seguente:
/* BeMaker.org - CORSO SUL BRACCIO ROBOTICO Progetto 12 – CONTROLLO BRACCIO VIA BT CON HC-05 E PCA9685 https://bemaker.org/ */ import processing.serial.*; //Importo la libreria perle comunicazioni seriali Serial myPort; //Definisco l'oggetto myPort String Stato = ""; //Definisce la variabile Stato come stringa che darà indiazioni su Arduino //String Pacchetto; //Definisce la variabile Pacchetto come stringa di caratteri che riceve da Arduino float vel=0.5; //Fattore moltiplicativo angoli di rotazione float rotazioneS1 = 0.0; //Definisco la variabile di rotazione di S1 float rotazioneS2 = 0.0; //Definisco la variabile di rotazione di S2 float rotazioneS3 = 0.0; //Definisco la variabile di rotazione di S3 float rotazioneS4 = 0.0; //Definisco la variabile di rotazione di S4 float rotazioneS5 = 0.0; //Definisco la variabile di rotazione di S5 float rotazioneS6 = 0.0; //Definisco la variabile di rotazione di S6 float rotazioneS7 = 0.0; //Definisco la variabile di rotazione di S7 int grad_rot_1 = 0; //Definisco la variabile intera che rappresenta la corrispondente rotazione in gradi int grad_rot_2 = 0; //Definisco la variabile intera che rappresenta la corrispondente rotazione in gradi int grad_rot_3 = 0; //Definisco la variabile intera che rappresenta la corrispondente rotazione in gradi int grad_rot_4 = 0; //Definisco la variabile intera che rappresenta la corrispondente rotazione in gradi int grad_rot_5 = 0; //Definisco la variabile intera che rappresenta la corrispondente rotazione in gradi int grad_rot_6 = 0; //Definisco la variabile intera che rappresenta la corrispondente rotazione in gradi int grad_rot_7 = 0; //Definisco la variabile intera che rappresenta la corrispondente rotazione in gradi String testoA = ""; //Defnisco una variabile stringa String testoB = ""; //Defnisco una variabile stringa String testoC = ""; //Defnisco una variabile stringa String testoD = ""; //Defnisco una variabile stringa String testoE = ""; //Defnisco una variabile stringa String testoF = ""; //Defnisco una variabile stringa String testoG = ""; //Defnisco una variabile stringa String Pp = "Pp"; //Defnisco una variabile stringa void setup() { String portName = "COM10"; //Associo la porta COM effettivamete utilizzata per la comunicazione - vedere Lezione 4 del Corso per come fare myPort = new Serial(this, portName, 9600); //Creazione e Settaggio della porta myPort.bufferUntil('\n'); // Definisce il carattere terminale della stringa da leggere myPort.write ((Pp)+'\n'); //Viene inviata la stringa 'Pp' alla porta BT per sincerarci che partiamo da una condizione nota delay(100); //Impostazione ambiente grafico 3D ed assegnazione variabili size( 1600, 900, P3D ); //Creao una finestra 3D x=1500, y=800 z= indefinito ambientLight(0,0,255); //Aggiungo una luce ambientale bianca diffusa pointLight(255, 0, 0, width/2, height/2, 400); //Aggiungo un proiettore di luce biancaa metà lunghezza della finestra per dare le ombre per la profondità noStroke(); //Non definisco i contorni dei solidi che andrò a disegnare rotazioneS1=PI/2; //Servo S1 BASE a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 rotazioneS2=PI/2; //Servo S2 Braccio a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 rotazioneS3=PI/2; //Servo S3 AvanBraccio a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 rotazioneS4=PI/2; //Servo S4 Rotazione AvanBraccio a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 rotazioneS5=PI/2; //Servo S5 Rotazione Polso a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 rotazioneS6=PI/2; //Servo S6 Rotazione Pinza a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 rotazioneS7=PI/2; //Servo S7 presa pinza a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 if (myPort.available() > 0) { //Controlla se ci sono dati sulla porta seriale Stato = myPort.readStringUntil('\n'); //Legge la stringa proveniente da Arduino e la mette nella variabile stato } } void draw() { background(0); lights(); DisegnaLegenda(); //CONTROLLA QUANDO VIENE PREMUTO IL TASTO SINISTRO DEL MOUSE SU UN DETERMINATO RETTANGOLO //1090,70,180,50 - Xgra: rad = 180 : pi if(mousePressed && mouseX>1090 && mouseX<1090+180 && mouseY>70 && mouseY<70+50){ IlluminaTasto(1090,70,180,50); rotazioneS1 = RotazioneGiuntoPos(rotazioneS1); grad_rot_1 = parseInt(rotazioneS1 * 180 / PI); String a1="A"; int a2 = parseInt(grad_rot_1); testoA = a1+a2; myPort.write((testoA)+'\n'); print("Rotazione Servo 1 = "); print(rotazioneS1); print(" "); print(grad_rot_1); print(" "); println(testoA); //debug delay(10); } //1320,70,180,50 if(mousePressed && mouseX>1320 && mouseX<1320+180 && mouseY>70 && mouseY<70+50){ IlluminaTasto(1320,70,180,50); rotazioneS1 = RotazioneGiuntoNeg(rotazioneS1); grad_rot_1 = parseInt(rotazioneS1 * 180 / PI); String a1="A"; int a2 = parseInt(grad_rot_1); String testoA = a1+a2; myPort.write((testoA)+'\n'); print("Rotazione Servo 1 = "); print(rotazioneS1); print(" "); print(grad_rot_1); print(" "); println(testoA); //debug delay(10); } //1090,170,180,50 if(mousePressed && mouseX>1090 && mouseX<1090+180 && mouseY>170 && mouseY<170+50){ IlluminaTasto(1090,170,180,50); rotazioneS2 = RotazioneGiuntoPos(rotazioneS2); grad_rot_2 = parseInt(rotazioneS2 * 180 / PI); String b1="B"; int b2 = parseInt(grad_rot_2); String testoB = b1+b2; myPort.write((testoB)+'\n'); print("Rotazione Servo 2 = "); print(rotazioneS2); print(" "); print(grad_rot_2); print(" "); println(testoB); //debug delay(10); } //1320,170,180,50 if(mousePressed && mouseX>1320 && mouseX<1320+180 && mouseY>170 && mouseY<170+50){ IlluminaTasto(1320,170,180,50); rotazioneS2 = RotazioneGiuntoNeg(rotazioneS2); grad_rot_2 = parseInt(rotazioneS2 * 180 / PI); String b1="B"; int b2 = parseInt(grad_rot_2); stroke(255,0,0); //Il contorno del tasto si colora di Rosso String testoB = b1+b2; myPort.write((testoB)+'\n'); print("Rotazione Servo 2 = "); print(rotazioneS2); print(" "); print(grad_rot_2); print(" "); println(testoB); //debug delay(10); } //1090,270,180,50 if(mousePressed && mouseX>1090 && mouseX<1090+180 && mouseY>270 && mouseY<270+50){ IlluminaTasto(1090,270,180,50); rotazioneS3 = RotazioneGiuntoPos(rotazioneS3); grad_rot_3 = parseInt(rotazioneS3 * 180 / PI); String c1="C"; int c2 = parseInt(grad_rot_3); String testoC = c1+c2; myPort.write((testoC)+'\n'); print("Rotazione Servo 3 = "); print(rotazioneS3); print(" "); print(grad_rot_3); print(" "); println(testoC); //debug delay(10); } //1320,270,180,50 if(mousePressed && mouseX>1320 && mouseX<1320+180 && mouseY>270 && mouseY<270+50){ IlluminaTasto(1320,270,180,50); rotazioneS3 = RotazioneGiuntoNeg(rotazioneS3); grad_rot_3 = parseInt(rotazioneS3 * 180 / PI); String c1="C"; int c2 = parseInt(grad_rot_3); String testoC = c1+c2; myPort.write((testoC)+'\n'); print("Rotazione Servo 3 = "); print(rotazioneS3); print(" "); print(grad_rot_3); print(" "); println(testoC); //debug delay(10); } //1090,370,180,50 if(mousePressed && mouseX>1090 && mouseX<1090+180 && mouseY>370 && mouseY<370+50){ IlluminaTasto(1090,370,180,50); rotazioneS4 = RotazioneGiuntoPos(rotazioneS4); grad_rot_4 = parseInt(rotazioneS4 * 180 / PI); String d1="D"; int d2 = parseInt(grad_rot_4); String testoD = d1+d2; myPort.write((testoD)+'\n'); print("Rotazione Servo 4 = "); print(rotazioneS4); print(" "); print(grad_rot_4); print(" "); println(testoD); //debug delay(10); } //1320,370,180,50 if(mousePressed && mouseX>1320 && mouseX<1320+180 && mouseY>370 && mouseY<370+50){ IlluminaTasto(1320,370,180,50); rotazioneS4 = RotazioneGiuntoNeg(rotazioneS4); grad_rot_4 = parseInt(rotazioneS4 * 180 / PI); String d1="D"; int d2 = parseInt(grad_rot_4); String testoD = d1+d2; myPort.write((testoD)+'\n'); print("Rotazione Servo 4 = "); print(rotazioneS4); print(" "); print(grad_rot_4); print(" "); println(testoD); //debug delay(10); } //1090,470,180,50 if(mousePressed && mouseX>1090 && mouseX<1090+180 && mouseY>470 && mouseY<470+50){ IlluminaTasto(1090,470,180,50); rotazioneS5 = RotazioneGiuntoPos(rotazioneS5); grad_rot_5 = parseInt(rotazioneS5 * 180 / PI); String e1="E"; int e2 = parseInt(grad_rot_5); String testoE = e1+e2; myPort.write((testoE)+'\n'); print("Rotazione Servo 5 = "); print(rotazioneS5); print(" "); print(grad_rot_5); print(" "); println(testoE); //debug delay(10); } //1320,470,180,50 if(mousePressed && mouseX>1320 && mouseX<1320+180 && mouseY>470 && mouseY<470+50){ IlluminaTasto(1320,470,180,50); rotazioneS5 = RotazioneGiuntoNeg(rotazioneS5); grad_rot_5 = parseInt(rotazioneS5 * 180 / PI); String e1="E"; int e2 = parseInt(grad_rot_5); String testoE = e1+e2; myPort.write((testoE)+'\n'); print("Rotazione Servo 5 = "); print(rotazioneS5); print(" "); print(grad_rot_5); print(" "); println(testoE); //debug delay(10); } //1090,570,180,50 if(mousePressed && mouseX>1090 && mouseX<1090+180 && mouseY>570 && mouseY<570+50){ IlluminaTasto(1090,570,180,50); rotazioneS6 = RotazioneGiuntoPos(rotazioneS6); grad_rot_6 = parseInt(rotazioneS6 * 180 / PI); String f1="F"; int f2 = parseInt(grad_rot_6); String testoF = f1+f2; myPort.write((testoF)+'\n'); print("Rotazione Servo 6 = "); print(rotazioneS6); print(" "); print(grad_rot_6); print(" "); println(testoF); //debug delay(10); } //1320,570,180,50 if(mousePressed && mouseX>1320 && mouseX<1320+180 && mouseY>570 && mouseY<570+50){ IlluminaTasto(1320,570,180,50); rotazioneS6 = RotazioneGiuntoNeg(rotazioneS6); grad_rot_6 = parseInt(rotazioneS6 * 180 / PI); String f1="F"; int f2 = parseInt(grad_rot_6); String testoF = f1+f2; myPort.write((testoF)+'\n'); print("Rotazione Servo 6 = "); print(rotazioneS6); print(" "); print(grad_rot_6); print(" "); println(testoF); //debug delay(10); } //1090,670,180,50 if(mousePressed && mouseX>1090 && mouseX<1090+180 && mouseY>670 && mouseY<670+50){ IlluminaTasto(1090,670,180,50); rotazioneS7 = RotazioneGiuntoPos(rotazioneS7); grad_rot_7 = parseInt(rotazioneS7 * 180 / PI); String g1="G"; int g2 = parseInt(grad_rot_7); String testoG = g1+g2; myPort.write((testoG)+'\n'); print("Rotazione Servo 7 = "); print(rotazioneS7); print(" "); print(grad_rot_7); print(" "); println(testoG); //debug delay(10); } //1320,670,180,50 if(mousePressed && mouseX>1320 && mouseX<1320+180 && mouseY>670 && mouseY<670+50){ IlluminaTasto(1320,670,180,50); rotazioneS7 = RotazioneGiuntoNeg(rotazioneS7); grad_rot_7 = parseInt(rotazioneS7 * 180 / PI); String g1="G"; int g2 = parseInt(grad_rot_7); String testoG = g1+g2; myPort.write((testoG)+'\n'); print("Rotazione Servo 7 = "); print(rotazioneS7); print(" "); print(grad_rot_7); print(" "); println(testoG); //debug delay(10); } //1205,770,180,50 - TASTO RESET if(mousePressed && mouseX>1205 && mouseX<1205+180 && mouseY>770 && mouseY<770+50){ IlluminaTasto(1205,770,180,50); TastoReset(); rotazioneS1=PI/2; //Servo S1 BASE a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 rotazioneS2=PI/2; //Servo S2 Braccio a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 rotazioneS3=PI/2; //Servo S3 AvanBraccio a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 rotazioneS4=PI/2; //Servo S4 Rotazione AvanBraccio a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 rotazioneS5=PI/2; //Servo S5 Rotazione Polso a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 rotazioneS6=PI/2; //Servo S6 Rotazione Pinza a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 rotazioneS7=PI/2; //Servo S7 presa pinza a riposo si trova a 90° per cui ruota da 0 a 90 e da 90 a 180 } DisegnaBraccio(); } void TastoReset() { String testoA = "A90"; myPort.write((testoA)+'\n'); print("Rotazione Servo 1 = "); print(PI/2); print(" "); print(90); print(" "); println(testoA); //debug delay(200); String testoB = "B90"; myPort.write((testoB)+'\n'); print("Rotazione Servo 2 = "); print(PI/2); print(" "); print(90); print(" "); println(testoB); //debug delay(200); String testoC = "C90"; myPort.write((testoC)+'\n'); print("Rotazione Servo 3 = "); print(PI/2); print(" "); print(90); print(" "); println(testoC); //debug delay(200); String testoD = "D90"; myPort.write((testoD)+'\n'); print("Rotazione Servo 4 = "); print(PI/2); print(" "); print(90); print(" "); println(testoD); //debug delay(200); String testoE = "E90"; myPort.write((testoE)+'\n'); print("Rotazione Servo 5 = "); print(PI/2); print(" "); print(90); print(" "); println(testoE); //debug delay(200); String testoF = "F90"; myPort.write((testoF)+'\n'); print("Rotazione Servo 6 = "); print(PI/2); print(" "); print(90); print(" "); println(testoF); //debug delay(200); String testoG = "G90"; myPort.write((testoG)+'\n'); print("Rotazione Servo 7 = "); print(PI/2); print(" "); print(90); print(" "); println(testoG); //debug delay(200); } void DisegnaLegenda() { //Posiziono il testo per sito fill(255); //Seleziono il colore Bianco textSize(20); //Dimensione testo text("WWW.BEMAKER.ORG", 50, 880); //Posiziona testo "WWW.BEMAKER.ORG" if (Stato != null) { //debug text(Stato, 400, 880); //Posiziona testo Stato } else { text("Non ho ricevuto l'OK da Arduino... controlla!", 400, 880); //Posiziona testo Stato } //Posiziono il testo per la legenda dei click di mouse di comando textSize(30); //Dimensione testo fill(255); //Seleziono il colore Bianco text("CLICK MOUSE", 1200, 50); //Posiziona testo "LEGENDA" //prima riga fill(0,123,184); //Seleziono il colore Bianco rect(1090,70,180,50); fill(255); //Seleziono il colore Bianco text("a = S1 <-", 1100, 100); //Posiziona testo "S1 <-" fill(0,123,184); //Seleziono il colore Bianco rect(1320,70,180,50); fill(255); //Seleziono il colore Bianco text("s = S1 ->", 1330, 100); //Posiziona testo "S1 <-" //seconda riga fill(0,123,184); //Seleziono il colore Bianco rect(1090,170,180,50); fill(255); //Seleziono il colore Bianco text("e = S2 v", 1100, 200); //Posiziona testo "e = S2 ^" fill(0,123,184); //Seleziono il colore Bianco rect(1320,170,180,50); fill(255); //Seleziono il colore Bianco text("d = S2 ^", 1330, 200); //Posiziona testo "d = S2 v" //terza riga fill(0,123,184); //Seleziono il colore Bianco rect(1090,270,180,50); fill(255); //Seleziono il colore Bianco text("r = S3 ^", 1100, 300); //Posiziona testo "e = S3 ^" fill(0,123,184); //Seleziono il colore Bianco rect(1320,270,180,50); fill(255); //Seleziono il colore Bianco text("f = S3 v", 1330, 300); //Posiziona testo "d = S3 v" //quarta riga fill(0,123,184); //Seleziono il colore Bianco rect(1090,370,180,50); fill(255); //Seleziono il colore Bianco text("t = S4 <-", 1100, 400); //Posiziona testo "e = S4 ^" fill(0,123,184); //Seleziono il colore Bianco rect(1320,370,180,50); fill(255); //Seleziono il colore Bianco text("g = S4 ->", 1330, 400); //Posiziona testo "d = S4 v" //quinta riga fill(0,123,184); //Seleziono il colore Bianco rect(1090,470,180,50); fill(255); //Seleziono il colore Bianco text("y = S5 <-", 1100, 500); //Posiziona testo "e = S5 ^" fill(0,123,184); //Seleziono il colore Bianco rect(1320,470,180,50); fill(255); //Seleziono il colore Bianco text("h = S5 ->", 1330, 500); //Posiziona testo "d = S5 v" //sesta riga fill(0,123,184); //Seleziono il colore Bianco rect(1090,570,180,50); fill(255); //Seleziono il colore Bianco text("u = S6 <-", 1100, 600); //Posiziona testo "e = S6 <-" fill(0,123,184); //Seleziono il colore Bianco rect(1320,570,180,50); fill(255); //Seleziono il colore Bianco text("j = S6 ->", 1330, 600); //Posiziona testo "d = S6 ->" //settima riga fill(0,123,184); //Seleziono il colore Bianco rect(1090,670,180,50); fill(255); //Seleziono il colore Bianco text("k = S7 <->", 1100, 700); //Posiziona testo "d = S7 <->" fill(0,123,184); //Seleziono il colore Bianco rect(1320,670,180,50); fill(255); //Seleziono il colore Bianco text("l = S7 >-<", 1330, 700); //Posiziona testo "d = S7 >-<" //ottava riga fill(0,123,184); //Seleziono il colore Bianco rect(1205,770,180,50); fill(255); //Seleziono il colore Bianco text("RESET", 1250, 800); //Posiziona testo "d = S7 <->" fill(255); //Seleziono il colore Bianco } void DisegnaBraccio() { // Disegno il Braccio Robot in 3D //Disegno la base noStroke(); translate(300,700,0); //Sposto il riferimento del disegno verso destra (x) di 200, verso il basso (y) di 600 e z=0 rotateY(rotazioneS1); //Ruoto lungo l'asse y fill(0,127,255); //Seleziono il colore blu box(60); //Disegno alle nuove coordinate un cubo di lato 60 //Disegno il giunto di rotazione del braccio translate( 0,-60,0 ); //Sposto il riferimento solo verso l'alto lungo la y fill(255,0,0); //Seleziono il colore Rosso rotateX( PI-rotazioneS2 ); //Ruoto lungo l'asse X sphere(30); //Disegno una sfera //Disegno il braccio translate( 0,0,140 ); //Sposto il riferimento solo verso l'alto lungo la z fill(255,255,0); //Seleziono il colore Giallo box( 60, 60, 220 ); //Disegno un parallelepipedo 60x60x220 //Disegno il giunto di rotazione dell'avanbraccio translate( 0,0,140 ); //Sposto il riferimento solo verso l'alto lungo la z fill(255,0,0); //Seleziono il colore Rosso rotateX( rotazioneS3 ); //Ruoto lungo l'asse X rotateZ( rotazioneS4 ); //Ruoto lungo l'asse z sphere(30); //Disegno una sfera //Disegno l'avanbraccio translate( 0,0,-110 ); //Sposto il riferimento solo verso l'alto lungo la z fill(255,255,0); //Seleziono il colore Giallo box( 60, 60, 150 ); //Disegno un parallelepipedo 60x60x220 //Disegno il giunto di rotazione del polso translate( 0,0,-110 ); //Sposto il riferimento solo verso l'alto lungo la z fill(255,0,0); //Seleziono il colore Rosso rotateX( rotazioneS5 ); //Ruoto lungo l'asse y rotateY( rotazioneS6 ); //Ruoto lungo l'asse z sphere(30); //Disegno una sfera //Disegno la pinza inferiore translate( 0,-70,0 ); //Sposto il riferimento solo verso l'alto lungo la z fill(70,70,70); //Seleziono il colore Rosso box( 20, 130, 20 ); //Disegno un parallelepipedo //Disegno il giunto di rotazione della pinza superiore translate( 0,35,0 ); //Sposto il riferimento solo verso l'alto lungo la z fill(255,0,0); //Seleziono il colore Rosso rotateX( PI-rotazioneS7 ); //Ruoto lungo l'asse x sphere(10); //Disegno una sfera //Disegno la pinza superiore translate( 0,50,0 ); //Sposto il riferimento solo verso l'alto lungo la z fill(70,70,70); //Seleziono il colore Rosso rotateX( -PI/2 ); //Ruoto lungo l'asse X box( 20, 20, 80 ); //Disegno un parallelepipedo translate( 0,-40,40 ); //Sposto il riferimento solo verso l'alto lungo la z fill(70,70,70); //Seleziono il colore Rosso rotateX( PI/2 ); //Ruoto lungo l'asse X box( 20, 20, 80 ); //Disegno un parallelepipedo } void IlluminaTasto(int xa, int xb, int xc, int xd) { stroke(255,0,0); //Il contorno del tasto si colora di Rosso strokeWeight(10); //lo spessore del contorno diventa da 10 noFill(); //Nessun riempimento (trasparente) rect(xa,xb,xc,xd); //rettangolo del tasto ON } float RotazioneGiuntoPos(float rg1) { rg1 = rg1+(vel*PI/180); //calcolo la rotazione giunto in radianti, facendola incrementare di un grad per volta int rg2 = parseInt(rg1 * 180/PI); //converto i valori da rad in grad if (rg2<0){ //limitare le rotazioni per valori <0 rg2 = 0; //inserisco un valore zero anche quando con il mouse si vuole dare una rotazione negativa rg1 = 0.0; } else if (rg2>180){ //limitare le rotazioni per valori >180° rg2 = 180; //inserisco 180 gradi anche quando con il muose si vuole dare una rotazione maggiore rg1 = PI; } return rg1; } float RotazioneGiuntoNeg(float rg1) { rg1 = rg1-(vel*PI/180); //calcolo la rotazione giunto in radianti, facendola incrementare di un grad per volta int rg2 = parseInt(rg1 * 180/PI); //converto i valori da rad in grad if (rg2<0){ //limitare le rotazioni per valori <0 rg2 = 0; //inserisco un valore zero anche quando con il mouse si vuole dare una rotazione negativa rg1 = 0.0; } else if (rg2>180){ //limitare le rotazioni per valori >180° rg2 = 180; //inserisco 180 gradi anche quando con il muose si vuole dare una rotazione maggiore rg1 = PI; } return rg1; }
Analisi degli sketch del Progetto 12 - Controllo e Comando Braccio Robot via BT
Gli sketch non presentano particolari difficoltà meritevoli di note, oltretutto non sono altro che riadattamenti considerando quanto già svolto nei progetti precedenti. Questo è ovviamente un aspetto positivo da considerare, perché è facilmente intuibile come i progetti che sono proposti in queste lezioni del Corso sono come tanti mattoni con cui poi si passa a progetti più evoluti che incrementano significativamente le varie funzionalità.
PS2 Controller e Arduino UNO
Un metodo alternativo per il controllo dei servo motori del Braccio Robot che vedremo nei prossimi progetti della Lezione 6, è quello che utilizza il Gamepad della Playstation, in particolare il PS2 Controller. In realtà il PS2 Controller può essere utilizzato per diversi progetti, ma lascio alla vostra fantasia eventuali ulteriori suoi impieghi con Arduino.
Non avendo la Playstation, per l’esecuzione dei progetti e per studiarne il funzionamento, ne ho dovuto comprare uno nuovo, anzi, facendo una ricerca su internet ho visto che il PS2 Controller viene venduto anche già compreso di modulo adattatore per Arduino.
Personalmente ho acquistato un PS2 Controller della DOIT, di tipo wireless, con frequenza radio di funzionamento a 2.4 GHz. Vi riporto alcune foto dell’acquisto:
Come potete osservare dalle foto, il modulo adattatore per Arduino non è altro che un connettore femmina per il modulo wireless del PS2 Controller a cui è stata saldata una breakout board rendendo disponibili i PIN che saranno utilizzati per interfacciarsi con Arduino.
Se non avete questo modulo di interfaccia non disperate, potete tranquillamente realizzarne una voi, ma vi occorrerà fare delle saldature, in basso vi metto la foto con i vari PIN:
I PIN colorati di azzurro sono quelli che andranno resi disponibili per Arduino. Attenzione all’alimentazione del modulo wireless è a 3,3V.
Per interfacciare il Gamepad della PS2 ad Arduino occorre una libreria specifica che si chiama: Arduino-PS2X.
I pulsanti disponibili sul Gamepad con i nomi assegnati nella libreria sono:
Il Controller PS2 utilizza un protocollo di comunicazione di tipo SPI, ovvero Serial Peripheral Interface normalmente su radiofrequenza a 2.4 GHz.
Sul sito della DOIT https://www.vvdoit.com/ suggeriscono il seguente collegamento:
Inoltre, sempre dal sito della DOIT ci vengono fornite alcune informazioni sulle precauzioni da adottare per il collegamento, nonché alcune informazioni generali che di seguito vi riporto tradotte dall’inglese e soprattutto dagli esperimenti che ho fatto:
- L’alimentazione del Gamepad è indicata dal led rosso posto sul controller, nel caso fosse spento verificare che l’interruttore posto nella parte frontale sia nella posizione di ON:
- Il modulo di interfaccia è anch’esso dotato di led rosso che se acceso indica la corretta alimentazione;
- Quando i led non sono pienamente accesi, allora significa che ci sono probabili problemi di alimentazione (verificare innanzi tutto che il gamepad abbia le batterie cariche, le batterie utilizzate sono del tipo AAA).
- Se il LED rosso sul Gamepad lampeggia significa che non c’è connessione tra il gamepad e la stazione ricevente.
- Una volta eseguita la connessione tra Gamepad e modulo ricevente, il LED smette di lampeggiare e rimane fisso rosso;
- Se la connessione tra gamepad e modulo ricevente non avviene al momento dell’alimentazione, provate a premere il pulsante di “START” sul Gamepad o qualsiasi altro tasto per innescare la comunicazione;
- Fare molta attenzione nell’alimentazione del modulo ricevente, sia per la tensione di alimentazione (3,3V) che per il segno.
Vediamo ora come connettere la scheda PCA9685 ad Arduino. La connessione è molto semplice, vediamo il PIN out di Arduino (figura in basso)
Progetto 13: Uso del PS2 Controller con Arduino
Questo primo progetto con l’uso del Gamepad lo dedichiamo a conoscere il PS2 Controller connesso ad Arduino ed a fare un po’ di pratica con la parte coding.
Per utilizzare il PS2 Controller con Arduino abbiamo necessità della libreria Arduino-PS2X che potete scaricate cliccando sul seguente link Arduino-PS2X .
Cliccando sul link proposto accederete ad un’area su Github, come mostrato sotto:
Cliccando su Code e nel menu a tendina che compare, cliccate su Download ZIP
Una volta scaricato il file .zip, scompattatelo e copiate l’intera directory PS2X_lib che si trova all’interno di Arduino-PS2X-master, nella directory delle librerie di Arduino che per default si trova in Documenti/Arduino/.
A questo punto potete aprire l’IDE e vi risulterà istallata la nuova libreria.
Passiamo al progetto. Per questo progetto ci occorre:
Fate attenzione alla tensione di alimentazione del modulo ricevitore che è di 3,3V . Lo schema da realizzare è il seguente:
Versione descrittiva collegamenti:
Lo sketch da caricare su Arduino è il seguente:
Analisi dello sketch del Progetto 13 – Uso del PS2 Controller con Arduino
Ogni riga dello sketch è commentata, per cui non troverete difficoltà nel comprendere cosa fanno le singole istruzioni. Come potete osservare lo sketch del progetto è stato ricavato alleggerendo quello di esempio ed adattandolo alle nostre esigenze.
Progetto 14: Braccio Robot pilotato con PS2 Controller & Arduino
Per lo sviluppo di questo progetto uniremo le conoscenze acquisite per la scheda PCA0685 e quanto imparato sul Gamepad PS2 Controller. Piloteremo direttamente un Braccio Robot tramite Gamepad. Il metodo di controllo che utilizzeremo è quello che con alcuni tasti del Gamepad selezioniamo il servo che si desidera pilotare e poi con i tasti di giù, su, destra e sinistra, invece piloteremo la rotazione del servo selezionato.
La fgura sotto mostra l’associazione tra tasti Gamepad e Servo con i relativi movimenti:
Per questo progetto ci occorre:
Lo schema da realizzare è il seguente:
Per una migliore comprensione dei collegamenti, riportiamoli anche in modo descrittivo e tabellare:
Per quanto riguarda i PIN dei servo presenti sulla Scheda PCA9685, ad essi andranno collegati i singoli servomotori del braccio robot come mostrato in figura, facendo attenzione ai colori che ricordo: cavetto di colore arancione – segnale, cavetto di colore rosso – Vcc e cavetto di colore marrone – GND.
Per lo sketch da caricare su Arduino:
Il Video Progetto che segue mostra tutti i passaggi in dettaglio.
Analisi dello sketch del Progetto 14 – Braccio Robot pilotato con PS2 Controller
A prima vista sembra complicato, ma in realtà lo sketch è composto solo da cicli di controllo con degli “if” e il gioco è fatto!. Infatti volendo schematizzare in modo banale quello che fa il nostro sketch, lo possiamo rappresentare così:
Ogni riga dello sketch è commentata, per cui non troverete difficoltà nel comprendere cosa fanno le singole istruzioni.
Con questo progetto termina la Lezione 6, ovviamente, come dico sempre, le mie proposte di progetto servono solo a solleticare la vostra curiosità e devono essere visti non come punti di arrivo, ma come punti di partenza, per cui se avete suggerimenti o se vi va di migliorare ciò che ho proposto, sentitevi liberi di farlo e se avete bisogno di aiuto contattatemi all’indirizzo info@bemaker.org .