I robot sono sempre più utilizzati nel campo dell'automazione per compiere movimentazioni e lavorazioni più complesse di quelle delle normali macchine automatiche.
I robot usati nell'industria sono estremamente costosi, ingombranti e difficili. A scuola useremo un modellino che si ispira al robot pallettizatore di ABB.
Questo modello adotta una serie di soluzioni interessanti tra cui:
Su internet ci sono tanti progetti di bracci robotici realizzabili con stampante 3D o laser cutter1) che è possibile replicare a scuola. Noi cercavamo un modello:
La scelta è caduta su un kit di montaggio proposto nel numero di agosto 2018 della rivista Futura Elettronica2), che è stato acquistato e assemblato alla fine dell'anno scolastico 2018-2019.
Il kit contiene la sola parte meccanica:
La parte elettronica è venduta separatamente e prevede:
La parte meccanica non è direttamente replicabile perché né la rivista, né il sito mettono a disposizione i file di progetto ma dalle immagini nelle istruzioni è comunque possibile generare un file per la nostra laser cutter. Lo shield, che contiene un regolatore a 5V per i servo e due uscite a transistor per l'attuatore pneumatico opzionale, non è strettamente indispensabile; per comandare i 5 servo bastano le uscite PWM della scheda Arduino e un'alimentazione separata a 5V4).
Le istruzioni, complete e dettagliate, sono indispensabili per l'assemblaggio. Il procedimento non è dei più semplici; oltre a ciò:
Il prodotto sembra solido e ben fatto. E' possibile muovere il braccio anche senza alimentazione a patto di farlo con un po' di cautela5).
Nella pagina prodotto del kit è disponibile questo software:
Nessuno dei file sembra particolarmente utile ma ci sono degli ottimi esempio nel sito di Mauro Alfieri.
Progettiamo uno shield Arduino per alimentare i cinque motori servo RC ispirandoci al modello proposto da Futura Shop in abbinamento al kit del braccio robotico (vedi il documento nella sezione Risorse in fondo alla pagina).
Per prima cosa occorre individuare le specifiche:
Per l'alimentazione bisogna considerare:
Si sceglie di alimentazione schede e motori con un alimentatore da banco a 12V e di utilizzare un morsetto a vite. Questa tensione, a valle di un diodo di protezione 1N4001, sarà collegata al piedino Vin per alimentare anche la scheda Arduino.
Per il dimensionamento del regolatore occorre sapere:
e scegliere:
Oltre a questo servono 5 connettori SIL per i servo con segnale (giallo), 5V (rosso) e GND (marrone) in questo ordine. Fare riferimento ai vari datasheet dei servo per non sbagliare l'ordine. Il pin del segnale va collegato come nello shield venduto col kit:
sigla connettore | pin Arduino | descrizione |
---|---|---|
S1 | 11 | rotazione base |
S2 | 10 | braccio avanti-indietro |
S3 | 9 | inclinazione polso |
S4 | 6 | rotazione polso |
S5 | 5 | pinza |
Per progettare lo shield usermo i template scaricabili dal sito della National Instruments, come descritto qui. Dopo aver scaricato i template e aggiunto al database utente (user) footprint e componenti usati nei modelli, si può creare un nuovo progetto in Multisim aprendo il file del template per schede Arduino Uno6).
Cominciamo così:
In Multisim:
A questo punto generiamo la netlist e la importiamo in Ultiboard scegliendo Forward Annotate to Ultiboard dal menu Transfer (se necessario scegliamo il file Ultiboard su ci portare i componenti).
In Ultiboard cominciare
Facciamo riferimento al circuito di figura 32 e alle formule da pagina 22 del datasheet dell'LM2576. Sappiamo che la versione Adjustable dell'LM2576 mantiene una Vref costante a 1,23V sul piedino 4 di feedback. La legge del partitore dice che:
`V_{REF}=R_1/(R_1+R_2)V_{OUT}`
Ricavando Vout e poi R2 otteniamo la formula di pagina 22:
`R_2 =R_1 (V_{OUT}/V_{REF}-1)`
quindi scegliendo R1 = 1k si ottiene una R2 di circa 3k, che otterremo con un resistore fisso R2=2,7k e un trimmer da 500 Ohm per regolare la tensione tra 4,5 e 5,3 Volt (si veda la formula di Vout per il calcolo dei due valori limite).
Da Multisim:
Piazzo l'LM2576 e collego gli altri componenti:
Lo schematico dovrebbe avere più o meno questo aspetto.
Forward annotate sul file già salvato in Ultiboard, poi aggiustare i footprint di:
Tentare il primo sbroglio seguendo le indicazioni di figura 32 del datasheet (collegamenti in grassetto devono essere corti e grossi). Tracce da 1mm. Piazzole tonde con fori da 0.8 e diametro 2,6 dove possibile altrimenti ovali custom (vedi qui o qui). Io non sono riuscito a fare lo sbroglio solo sul bottom (ma Alifuoco e D'Agostino sì!) e ho dovuto piazzare 2 via e un collegamento sul top.
Se è necessario realizzare dei collegamenti nel lato top bisogna piazzare delle via:
Al termine aggiungere il piano di massa:
Controllare sempre:
I piedini dei condensatori elettrolitici possono risultare invertiti. Lo si vede controllando il collegamenti in Ultiboard ma anche in Multisim se nella scheda Display delle proprietà del componente si mette la spunta su show symbol pin names e show package pin names. Per correggere si può procedere in due modi:
Montata la scheda single layer8) con questi componenti:
Per tutti i componenti punta da 0,8mm tranne che per: stripline, morsetto a vite, induttore, regolatore dove serve la punta da 1mm.
La scheda è stata collaudata usando un reostato come carico e 100mA di corrente e la tensione in uscita, regolata con l'aiuto del tester, a 5V. All'oscilloscopio osserviamo il ripple della tensione in uscita e la tensione al piedino Vout10):
Si osserva un ripple di circa 20mV e il tipico andamento della tensione su Vout prodotta dalla commutazione del regolatore.
Ho usato la libreria servo e l'esempio 4 da qui per inviare i dati da monitor seriale. La scheda switching funziona e il regolatore senza dissipatore non scalda granché. Per calibrare ognuno dei servo si può usare questo sketch.
aggiustare i valori dopo la riparazione
Range valori per i 5 attuatori:
Codice adattato da qui:
/* da https://www.mauroalfieri.it/bricolage/posizionamento-braccio-robot.html#more-12400 * aggiunto start-stop da seriale * le posizioni vanno ricalibrate in base al nostro robot * i movimenti sono rallentati usando la funzione goPos() */ #include <Servo.h> // per il range di valori vedi qui // https://leonardocanducci.org/wiki/tp4/braccio_robotico#collaudo Servo base; // 1 0 - 180 Servo shoulder; // 2 140 - 37 Servo elbow; // 3 65 - 140 Servo wrist_rot; // 4 0 - 180 Servo gripper; // 5 0 - 75 // posizione iniziale byte pos[5] = {90,90,90,90,0}; // serve per la funzione goPos() byte oldpos[5] = {90,90,90,90,0}; // sequenza coordinate //byte seq[][5] = { // {90,90,90,90,0}, // {110,90,130,90,0}, // {110,63,130,90,50}, // {110,90,110,90,50}, // {30,90,110,90,50}, // {30,63,110,90,0}, // {30,90,110,90,0}, // {90,90,130,90,0}, // {90,63,130,90,40}, // {90,90,110,90,40}, // {40,90,110,90,40}, // {40,63,110,90,0}, // {40,90,110,90,0}, // {70,90,130,90,0}, // {70,63,130,90,40}, // {70,90,110,90,40}, // {45,90,110,90,40}, // {45,63,110,90,0}, // {45,90,110,90,0}, // {90,90,90,90,75,} //}; byte seq[][5] = { {90,90,90,90,0}, {140,110,60,90,0}, {140,110,60,90,0}, {140,110,60,90,35}, {140,90,90,90,35}, {90,90,90,90,60}, {90,110,60,90,0}, {90,90,90,90,0} }; // avvio se arriva del testo da seriale bool run = false; void setup() { Serial.begin(115200); // abbinamento servo-pin base.attach(11); shoulder.attach(10); elbow.attach(9); wrist_rot.attach(6); gripper.attach(5); // comando posizione iniziale base.write(pos[0]); shoulder.write(pos[1]); elbow.write(pos[2]); wrist_rot.write(pos[3]); gripper.write(pos[4]); Serial.println( "#### invia testo per avviare e per fermare la sequenza ####" ); } void loop() { startStop(); while (run) { for ( byte line=0; line < (sizeof(seq)/5); line++ ) { Serial.print("Seq["); Serial.print(line); Serial.print("]:"); for( byte i=0; i<5; i++ ) { Serial.print(" "); Serial.print(seq[line][i]); pos[i] = seq[line][i]; } Serial.print("\n"); goPos(0,base,15); goPos(1,shoulder,15); goPos(2,elbow,15); goPos(3,wrist_rot,15); goPos(4,gripper,15); delay(1000); startStop(); } delay(2000); } } void goPos(byte servo, Servo instance, byte pause) { if (oldpos[servo] >= pos[servo]) { for ( byte i = oldpos[servo]; i > pos[servo]; i--) { instance.write(i); delay(pause); } } if (oldpos[servo] <= pos[servo]) { for ( byte i = oldpos[servo]; i < pos[servo]; i++) { instance.write(i); delay(pause); } } oldpos[servo] = pos[servo]; } void startStop() { // se arriva del testo dal monitor seriale if (Serial.available()>0){ // senza questo ritardo non legge tutti i dati del buffer! delay(10); Serial.println("buffer non vuoto"); Serial.print("buffer dati: "); Serial.println(Serial.available()); // svuota il buffer clearInputBuffer(); Serial.print("buffer dati: "); Serial.println(Serial.available()); // toggle della variabile che attiva la sequenza run = !run; Serial.print("run vale: "); Serial.println(run); } } void clearInputBuffer() { while (Serial.available() > 0) { char t = Serial.read(); } }
Torna all'indice.