Circuito per slitta motorizzata con Arduino

Realizzazione di un circuito per una slitta motorizzata con Arduino.
Finalmente un pò di libertà per smanettare ancora una volta con Arduino.
E’ passato moltissimo tempo dall’ultimo articolo, tempo durante il quale purtroppo, sono stato assente dal sito e dal canale YouTube. Ciò nonostante, devo dire, siete stati in tanti a scrivere e a commentare (anche privatamente) per dei consigli o anche solo per dei ringraziamenti. Quindi prima di cominciare questo nuovo post, ringrazio tutti voi per aver continuato a leggere i miei seppur vecchi articoli, e per avermi dimostrato che se non altro sono serviti a qualcuno.
Grazie davvero!
Iniziamo
Tra gli articoli più gettonati, ho notato che a suscitare molto interesse, sono stati quelli relativi al controllo di motori passo passo, come ad esempio:
Pilotare un motore passo passo con Arduino e il driver A4988
Controllo di due motori passo passo con Arduino e un Joystick
Prendendo spunto dagli ultimi commenti, ho pensato di realizzare qualcosa che possa, se non soddisfare, quanto meno avvicinarsi, all’esigenza di Walter.
L’idea generale è quella di una slitta che si muove autonomamente avanti e in dietro su un binario. Il tutto immaginario perchè mi sono limitato soltanto alla realizzazione del circuito e del codice. Senza slitta e senza binario per intenderci 😀
All’accensione del sistema, la slitta deve essere in grado di resettare il suo stato e posizionarsi all’inizio del binario.
Questa fase l’ho chiamata “Homing”.
Al termine della fase di homing, la slitta rimane in attesa della pressione di un pulsante, il bottone “Work”, per iniziare il suo movimento.
Per determinare i fine corsa del binario, ho utilizzato due “Limit Switch” o interruttori di fine corsa (come preferisci).
Durante la fase di lavoro sarà possibile scegliere il livello di “risoluzione” del motore. Per risoluzione intendo lo scostamento in termini di step del rotore che grazie al pulsante “Risoluzione” tramite il driver A4988, potrà essere definito in: uno step, 1/2, 1/4, 1/8 e 1/16 di step.
Se durante l’esecuzione dovessero esserci problemi, ho previsto un pulsante di “Reset” che interrompe l’esecuzione del movimento e ripristina lo stato della slitta, che quindi si riposiziona in modalità iniziale.
Scenario
In uno scenario di utilizzo tipo, le cose andrebbero in questo modo:
– accendo il dispositivo;
– aspetto che termini la fase di Homing;
– avvio il movimento con il pulsante Work;
– tramite il pulsante Risoluzione scelgo quella che fa al caso mio (di default è 1 STEP);
– individuata la risoluzione ideale premo il pulsante Reset per riposizionare la slitta;
– a questo punto sono pronto per ripremere il pulsante Work ed eseguire il movimento alla risoluzione scelta.
Lo schema
Come avrai potuto notare dallo schema dei collegamenti, in questa occasione ho deciso di utilizzare un’unica fonte di alimentazione. Uso un alimentatore a 12 volt che alimenta sia Arduino, sia la VMOT del driver A4988 e di conseguenza il motore. Per l’alimentazione logica del driver, uso i 5 volt forniti da Arduino.
La capacità del condensatore elettrolitico posto in parallelo all’alimentazione motore è di 100uF, e come riportato dal sito del produttore deve essere almeno di 47uF.
Warning: This carrier board uses low-ESR ceramic capacitors, which makes it susceptible to destructive LC voltage spikes, especially when using power leads longer than a few inches. Under the right conditions, these spikes can exceed the 35 V maximum voltage rating for the A4988 and permanently damage the board, even when the motor supply voltage is as low as 12 V. One way to protect the driver from such spikes is to put a large (at least 47 µF) electrolytic capacitor across motor power (VMOT) and ground somewhere close to the board.
Sui limit switch e sui pulsanti di comando, ho collegato delle resistenze da 12 Ohm anche se sarebbe meglio qualcosa di più sostanzioso, tipo 10K, in modo da limitare il passaggio di corrente quando premuti e quindi posti a massa. Serve per salvaguardare i pin di Arduino. Purtroppo a casa avevo solo queste.
Il led di stato è collegato sul pin 13 di Arduino. Questo pin presenta già un led on board sulla scheda quindi puoi anche evitare di montarne uno esterno.
Eventualmente, anche in questo caso occorre mettere una resistenza.
Per l’eventuale led esterno, una resistenza da 220 Ohm andrà bene.
In merito al Driver A4988
Ricorda che è possibile regolare la corrente di uscita del driver A4988 tramite il trimmer onboard.
Guarda qui sotto il video del produttore per capire come fare.
Durante i miei test non ho fatto nessuna regolazione, sarà fortuna o sarà un caso, ma né il modulo né il motore sembrano risentirne.
Il codice
Come potrai notare, la velocità del motore durante le fasi di homing e di lavoro sono cablate nel codice. Se non soddisfano le tue esigenze, puoi modificarle da “SPEED_WORKING” e “SPEED_HOMING”.
Tra il movimento di andata ed il movimento di ritorno della fase di lavoro e della fase di homing, ci sono delle pause. Di default sono 4 secondi per la fase di lavoro e 2 secondi per la fase di homing. Anche queste possono essere modificate agendo sui valori delle costanti DELAY_WORK e DELAY_HOMING.
Come sempre, il codice è ampiamente commentato ma per qualsiasi dubbio o chiarimento, puoi fare riferimento alla sezione commenti a fondo pagina.
Ricordati di includere le due librerie: AccelStepper e Bounce2.
Se non le hai già, basta andare in gestione librerie dall’IDE di Arduino ed installarle.
//Inclusione delle librerie #include <AccelStepper.h> #include <Bounce2.h> //Definizione costanti relative ai PIN const int PIN_SW_LIMIT_END = 2; const int PIN_SW_WORK = 3; const int PIN_SW_RESET = 4; const int PIN_SW_RISOLUZIONE = 5; const int PIN_DR_DIR = 6; const int PIN_DR_STEP = 7; const int PIN_MS_3 = 8; const int PIN_MS_2 = 9; const int PIN_MS_1 = 10; const int PIN_DR_ENABLE = 11; const int PIN_SW_LIMIT_START = 12; const int PIN_LED_STATO = 13; /* Tabella di riferimento relativa alla risoluzione del motore prelevata dal sito del produttore https://www.pololu.com/product/1182 +---+------+------+------+----------------------+ | # | MS1 | MS2 | MS3 | Microstep resolution | +---+------+------+------+----------------------+ | 0 | Low | Low | Low | Full step | | 1 | High | Low | Low | Half step | | 2 | Low | High | Low | Quarter step | | 3 | High | High | Low | Eighth step | | 4 | High | High | High | Sixteenth step | +---+------+------+------+----------------------+ */ //Creiamo un array bidimensionale per contenere i valori della tabella della risoluzione. const int RISOLUZIONE[5][3] = { {0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {1, 1, 0}, {1, 1, 1} }; const unsigned long DELAY_WORK = 4000; const unsigned long DELAY_HOMING = 2000; //Imposta velocità del motore durante la fase di lavoro const double SPEED_WORKING = 20.0; //Imposta velocità del motore durante la fase di reset della posizione const double SPEED_HOMING = 40.0; //il delay in ms di debounce applicato agli switch const unsigned long DEBOUNCE_DELAY = 10; boolean homing, working; //risoluzione iniziale del motore int selRisoluzione = 0; //istanzia il motore AccelStepper motore(AccelStepper::DRIVER, PIN_DR_STEP, PIN_DR_DIR); //istanzia i bottoni Bounce btnSwResolution = Bounce(); //Scelta risoluzione step Bounce btnSwReset = Bounce(); //Reset operazioni Bounce btnSwWork = Bounce(); //Avvia esecuzione Bounce btnSwLimitHome = Bounce(); //Limite iniziale Bounce btnSwLimitEnd = Bounce(); //Limite fine corsa void setup() { //definizione delle modalità dei pin pinMode(PIN_LED_STATO, OUTPUT); pinMode(PIN_DR_ENABLE, OUTPUT); pinMode(PIN_MS_1, OUTPUT); pinMode(PIN_MS_2, OUTPUT); pinMode(PIN_MS_3, OUTPUT); pinMode(PIN_SW_RISOLUZIONE, INPUT_PULLUP); pinMode(PIN_SW_RESET, INPUT_PULLUP); pinMode(PIN_SW_WORK, INPUT_PULLUP); pinMode(PIN_SW_LIMIT_START, INPUT_PULLUP); pinMode(PIN_SW_LIMIT_END, INPUT_PULLUP); //associamo i pin degli switch alle istanze dei bottoni (Boune) btnSwResolution.attach(PIN_SW_RISOLUZIONE); btnSwResolution.interval(DEBOUNCE_DELAY); btnSwReset.attach(PIN_SW_RESET); btnSwReset.interval(DEBOUNCE_DELAY); btnSwWork.attach(PIN_SW_WORK); btnSwWork.interval(DEBOUNCE_DELAY); btnSwLimitHome.attach(PIN_SW_LIMIT_START); btnSwLimitHome.interval(DEBOUNCE_DELAY); btnSwLimitEnd.attach(PIN_SW_LIMIT_END); btnSwLimitEnd.interval(DEBOUNCE_DELAY); delay(2000); //Esegui reset posizione del motore. resetHomePosition(); } void loop() { //se non siamo in fase di reset della posizione if (!homing ) { //Tieni d'occhio gli switch "Work", "Reset" e "Risoluzione" handleSwResetAndResolution(); handleSwWork(); //Se siamo in fase di lavoro (working) if (working) { //Vai avanti fin quando non viene premuto lo switch di fine corsa while (digitalRead(PIN_SW_LIMIT_END) && working) { handleSwResetAndResolution(); //Durante il while, controlla sempre se vengono premuti i tasti "Reset" o "Risoluzione" motore.move(100); motore.run(); } motore.setCurrentPosition(0); //Raggiunta la posizione finale aspetta DELAY_WORK secondi delay(DELAY_WORK); //Torna in dietro fin quando non viene premuto lo switch di inizio corsa while (digitalRead(PIN_SW_LIMIT_START) && working) { handleSwResetAndResolution(); //Durante il while, controlla sempre se vengono premuti i tasti "Reset" o "Risoluzione" motore.move(-100); motore.run(); } motore.setCurrentPosition(0); //Al termine del lavoro, disabilita il driver e rimettiti in attesa working = false; setPinEnable(working); } } } //Funzione di comodo per accorpare la chiamata delle due funzioni contenute in essa void handleSwResetAndResolution() { handleSwReset(); handleSwResolution(); } //Esegui reset della posizione del motore void resetHomePosition() { homing = true; working = false; //abilitiamo il pin del driver e accendiamo il led di stato setPinEnable(true); //impostiamo velocita e accelerazione di reset motore.setMaxSpeed(SPEED_HOMING); motore.setSpeed(SPEED_HOMING); motore.setAcceleration(SPEED_HOMING * 3); //Durante la fase di reset facciamo girare il motore in full step setPinResolution(0, 0, 0); while (digitalRead(PIN_SW_LIMIT_END)) { motore.move(100); motore.run(); } motore.setCurrentPosition(0); delay(DELAY_HOMING); while (digitalRead(PIN_SW_LIMIT_START)) { motore.move(-100); motore.run(); } motore.setCurrentPosition(0); //Terminata la fase di reset, reimpostiamo la risoluzione del motore in base al valore di "selRisoluzione" setPinResolution( RISOLUZIONE[selRisoluzione][0], RISOLUZIONE[selRisoluzione][2], RISOLUZIONE[selRisoluzione][3] ); //reimpostiamo velocita e accelerazione di lavoro motore.setMaxSpeed(SPEED_WORKING); motore.setSpeed(SPEED_WORKING); motore.setAcceleration(SPEED_WORKING * 3); //definisci stato delle variabili homing = false; working = false; //Disabilita il driver e spegni il led setPinEnable(false); } //Tieni d'occhio il bottone "Risoluzione" void handleSwResolution() { btnSwResolution.update(); /* Ad ogni pressione del tasto risoluzione, incrementa di uno il valore di "selRisoluzione" fin quando non raggiunge la lunghezza dell'array "RISOLUZIONE". In questo modo possiamo cambiare risoluzione in termini di step del motore. */ if (btnSwResolution.fell()) { if (selRisoluzione < ((sizeof(RISOLUZIONE) / sizeof(RISOLUZIONE[0])) - 1)) { selRisoluzione++; } else { selRisoluzione = 0; } //Setta i valori contenuti nell'array "RISOLUZIONE" determinati dal numero presente in "selRisoluzione" sui pin MS1, MS2, MS3 setPinResolution( RISOLUZIONE[selRisoluzione][0], RISOLUZIONE[selRisoluzione][2], RISOLUZIONE[selRisoluzione][3] ); } } //Tieni d'occhio il bottone di "Reset" void handleSwReset() { btnSwReset.update(); if (btnSwReset.fell()) { delay(DELAY_HOMING); resetHomePosition(); //Richiama resetHomePosition() per resettare la posizione del motore. } } //Tieni d'occhio il bottone "Work" void handleSwWork() { btnSwWork.update(); if (btnSwWork.fell()) { working = !working; setPinEnable(working); } } //Imposta lo stato dei pin "PIN_DR_ENABLE" e "PIN_LED_STATO" in base al parametro "working"; void setPinEnable(boolean working) { digitalWrite(PIN_DR_ENABLE, !working); digitalWrite(PIN_LED_STATO, working); } //Imposta lo stato dei pin "PIN_MS_1", "PIN_MS_2" e "PIN_MS_3" in base ai parametri "MS1", "MS2" e "MS3" void setPinResolution(int MS1, int MS2, int MS3) { digitalWrite(PIN_MS_1, MS1); digitalWrite(PIN_MS_2, MS2); digitalWrite(PIN_MS_3, MS3); }
A fine pagina trovi il link per scaricare il pacchetto con codici e schemi di collegamento. Come sempre ti ricordo che acquistando prodotti Amazon passando attraverso i link del mio sito, io percepisco una piccola commissione (parliamo di centesimi) in buoni regalo. Questi buoni sommati alle eventuali donazioni PayPal, servono a mantenere attivo il sito web e ad acquistare nuovi componenti.
Prodotti Amazon
10 Pezzi Modulo Driver Motore Stepper con Dissipatore di Calore Compatibile con Stampante A4988 3D Reprap, Macchina CNC o Robotica
AZDelivery 3 x Modulo Driver Motore Passo-Passo A4988 Scheda Breakout con dissipatore di calore compatibile con Arduino incluso un E-Book!
9,99 €ANGEEK, 5 pezzi Stepper Driver A4988 Stepper Motor Driver Module con dissipatore di calore per stampante 3D Reprap
10,99 €ARCELI A4988 Stepper StepStick con motore compatibile con dissipatore di calore per 3D Printer Controller Ramps 1.4 (confezione da 5 pezzi) - rosso
8,99 €WJMY A4988 Stepper Motor Driver Module 5 pz Con Mini Dissipatore Di Calore Compatibile Con Stampante 3D RepRap
11,59 €NETGEAR Switch Ethernet Smart 16 porte GS716T, Switch Gigabit 18 porte con 2 SFP da 1G, Montaggio Desktop o su Rack e Assistenza Limitata a Vita
NETGEAR Switch PoE Smart 24 porte GS724TP, Switch Ethernet Gigabit 24 da 1G, 24 PoE+ a 190 W, 2 SFP da 1G, gestione Insight cloud opzionale, montaggio desktop o su rack e assistenza limitata a vita
NETGEAR Switch PoE Smart 24 porte GS728TPP, Switch Ethernet Gigabit con gestione Insight cloud opzionale, 24 PoE+ a 380 W, 4 SFP da 1G, montaggio desktop o su rack e assistenza limitata a vita
Switch non gestito Cisco SF110-24 con 24 porte 10/100, protezione limitata a vita (SF110-24-EU)
Youmile 20Pack Micro Switch AC 1A 125V 3Pin SPDT NO + NC Leva cerniera Pulsante momentaneo Micro finecorsa per Arduino
5,99 € (0,30 € / unità)Motore passo-passo, controller driver motore passo-passo per NEMA 17 23 motore, 4A controllo motore passo-passo scheda integrata avanti e indietro impulso velocità angolo modulo di controllo PLC
32,99 €Motore passo-passo, Mcwdoit 5 pezzi Nema 17 Stepper Motor 1.7A 0.59 Nm 84oz.in 48mm Corpo w / 1m Cavo e connettore +5 Pz Nema 17 Staffa di montaggio motore per stampante 3D / CNC
52,99 €STEPPERONLINE 1 asse motore passo-passo CNC Kit 12,0 Nm 6A Nema 34 motore passo-passo e driver 2,4 – 7,2 A 18 – 80 VAC / 36 – 110 VDC per macchina per incisione CNC, stampante 3D
146,81 €STEPPERONLINE Motore passo-passo 5 pezzi Nema 17 bipolare 42Ncm 1.5A 42x42x39mm 4 fili con cavo da 1 m e connettore per stampante 3D/fresatrice CNC, nero
37,66 €STEPPERONLINE 1 asse Closed Loop Kit motore passo-passo 12,0 Nm 1000PPR Nema 34 stepper motore e motore passo-passo driver 0~8,2A 24~80VDC per macchina per incisione CNC
167,32 €Arduino UNO Rev3 [A000066]
Arduino Uno SMD Rev3
Arduino UNO WiFi REV2 [ABX00021]
57,00 €Arduino UNO Mini Limited Edition [ABX00062]
50,00 €Arduino Make Your UNO Kit [AKX00037] - un kit completo per costruire Make Your Uno PCB + Audio Synth PCB
ARCELI 300pcs 15Value Condensatore elettrolitico Portata da 0,1uF a 470uF Assortimento Kit di condensatori
9,99 €AUKENIEN 23 Valori 288pz Condensatori Elettrolitici Kit Assortimento di Condensatore Elettrolitico Range da 10uF a 2200uF 10V 16V 25V 35V 50V Capacitor Elettrico in Alluminio
17,99 €WINGONEER Condensatori 13 Valori Total 200 PCS da 0.47uF a 1000uF kit di assortimento di condensatori elettrolitici
12,99 €Condensatori Elettrolitici Kit 24 Valori 700pz Assortimento di Condensatore Elettrolitico Range da 0,1uF a 1000uF 10V 16V 25V 50V Capacitor Elettrico in Alluminio
18,99 €Elettrolitici Condensatore 22000µF 50V 85°C ; ESMH500VSN223MA63U ; 22000uF
Il video
Come sempre
- Importa le librerie necessarie;
- Assicurati che tutti i collegamenti siano corretti;
- Ricordati di impostare la porta COM del tuo Arduino;
- Utilizza le tensioni corrette;
- Ricorda che io non mi assumo nessuna responsabilità per eventuali danni o disastri che causi 😀
Spero che questo post ti sia stato utile! Per qualsiasi domanda o chiarimento, fai riferimento alla sezione commenti.
Sono ben accetti, birre, caffè e donazioni 😉
Commentati Recentemente