sabato 9 gennaio 2016

Parliamo del motore passo passo 28BYJ-48

Ciao e ben ritrovato sul blog aspettando il bus.
Rivedendo agli articoli già pubblicati sul blog, ho notato che l'articolo dedicato al motore passo 28BYJ-48 ha avuto un buon successo ed anche le sue FAQ sono state apprezzate, ma ogni cosa può essere migliorata e quindi provo, con un nuovo sketch, ad essere più chiaro.

Fig. 1 - Motore 28BYJ-48 a 5 Volt con modulo con ULN2003A - foto di Paolo Luongo
Fig. 1 - Motore 28BYJ-48 a 5 Volt con modulo con ULN2003A - foto di Paolo Luongo



Iniziamo con una piccola modifica agli schemi che ho già pubblicato nelle FAQ, che ritengo sia più chiara nei collegamenti: le modifiche riguardano solo i PIN di Arduino UNO R3 ed il loro collegamento al modulo.
Vediamoli:

Fig. 2 - Nuovo schema di Arduino e ULN2003A di Paolo Luongo
Fig. 2 - Nuovo schema di Arduino e ULN2003A di Paolo Luongo

Le modifiche riguardano esclusivamente i fili Blu, Rosa, Arancio e Giallo che, ora, non sono più incrociati.
Per la Fig. 2 in Alta Risoluzione clicca qui (circa 1MB).

Adesso facciamo alcune considerazioni sul motore passo passo 28BYJ-48.

Dal  datasheet, disponibile online, si vede che lo stride angle è 5,625°/64 ossia di circa 88 millesimi di grado. In questo momento preferisco continuare ad utilizzare i millesimi di grado invece di convertirli in primi e secondi perché appesantirebbero solo il discorso.
Per rendere più chiaro quanto detto ho preparato un foglio di calcolo che ho poi trasformato in PDF e che potete scaricare qui, dove ho inserito i primi 2048 valori e la relativa rotazione ottenuta in gradi.

Fig. 3 - PDF con i primi 128 valori e relativa rotazione del motore 28BYJ-48 di Paolo Luongo
Fig. 3 - PDF con i primi 128 valori e relativa rotazione del motore 28BYJ-48 di Paolo Luongo

La fig. 3 non è molto chiara, ma se scaricate il PDF noterete alcune cose interessanti, e le 16 pagine di valori del PDF, vediamo alcune cose:

1) un passo del motore 28BYJ48 è di 5,625 gradi, ma la riduzione interna, fatta con alcuni ingranaggi, porta la rotazione esterna a 0,088 gradi circa (il valore preciso è in quello visibile in Fig. 3).

Fig. 4 - Interno del motore 28BYJ48 - Fonte video di Bret Stateham
Fig. 4 - Interno del motore 28BYJ48 - Fonte video di Bret Stateham

2) Ad ogni movimento del motore passo passo 28BYJ48 il perno esterno ruota di pochi millesimi di grado. Ma allora quanti "impulsi" bisogna dare al motore per fargli fare una angolo giro (360 gradi) ? 
Sono 4096 e lasciatemi passare il termine impulsi .
Avremo 2048 impulsi per 180 gradi, 1024 impulsi per 90 gradi e 512 impulsi per 45 gradi.

3) Come fare a dare questi impulsi al motore passo passo? Utilizzando una tabella, basata su 7 stati che se letta dal basso verso l'alto fa girare il motore in senso orario, se letta dal basso verso l'alto fa ruotare il motore in senso antiorario. Ovviamente la rotazione oraria o antioraria è anche legata ai collegamenti, ma questo mi sembra ovvio, cambiano i collegamenti delle fasi il verso della rotazione cambia.
Vediamo lo sketch.

Fig. 5 - La tabella degli stati implementata nello sketch di Paolo Luongo
Fig. 5 - La tabella degli stati implementata nello sketch di Paolo Luongo

La funzione EseguiPasso utilizza una variabile stato per ricordare lo stato in cui si trova il motore. Se passiamo dallo stato 1 allo stato 2 il motore avrà fatto una rotazione in senso orario.
Cosa succede dopo lo stato S7 ?  Si ricomincia con lo stato S0.
Basta immaginarla come un foglio ripiegato in cui l'inizio segue la fine.

Entriamo nel dettaglio dello sketch:

Fig. 6 - Parte iniziale del nuovo sketch di Paolo Luongo
Fig. 6 - Parte iniziale del nuovo sketch di Paolo Luongo

Vorrei porre la vostra attenzione sulla variabile RitardoDegliImpulsi che è il ritardo fra un impulso e l'altro. Se assegnerete a questa variabile il valore zero (0) il motore resterà fermo. Per la massima velocità utilizzeremo il valore 1 ed aumentandolo il motore girerà più piano. Se torniamo ad datasheet leggeremo che la frequenza è di 100Hz a cui corrisponde un periodo di 10mS, che il suo valore nominale.

A questo punto metto insieme i dati della tabella in PDF, la tabella per mandare gli impulsi al motore e vengono fuori le prime funzioni dello sketch.


Fig. 7 - La funzione Ruota di 11,25 gradi - di Paolo Luongo
Fig. 7 - La funzione Ruota di 11,25 gradi - di Paolo Luongo
Con 128 impulsi abbiamo una rotazione di 11,25 gradi. A questo punto è semplice sviluppare le altre funzioni.

Fig. 8 - La funzione ruota di 22,5 gradi e di 45 Gradi - di Paolo Luongo
Fig. 8 - La funzione ruota di 22,5 gradi e di 45 Gradi - di Paolo Luongo

Fig. 9 - Le altre funzioni per 90, 180 e 360 gradi - di Paolo Luongo
Fig. 9 - Le altre funzioni per 90, 180 e 360 gradi - di Paolo Luongo

Ed infine, ecco una funzione di esempio per utilizzare le precedenti:


Fig. 10 - Funzione di esempio di Paolo Luongo
Fig. 10 - Funzione di esempio di Paolo Luongo

Vediamo alcuni punti chiave dello sketch:

Fig. 11 - Funzione Uscita di Paolo Luongo
Fig. 11 - Funzione Uscita di Paolo Luongo
Gli argomenti della funzione Uscita sono dei byte (8 bit) che indicano se deve essere attivata o non una certa fase. Con il valore 1 metteremo il PIN di Arduino UNO R3 al valore logico 1 (+5 Volt) altrimenti sarà al valore logico 0 (0 Volt). Guardando la Fig. 5 notiamo che solo 1 o 2 uscite sono al livello alto in ogni stato della tabella. Ogni  Fase attiva sul motore consuma 100 mA circa. Quindi il motore assorbirà una corrente, a vuoto, di circa 200 mA con alcuni picchi in avvio della rotazione. Questa considerazione ci permette di alimentare il motore direttamente dalla scheda Arduino UNO R3.

Fig. 12 - La variabile che è utile per regolare la velocità nella rotazione
Fig. 12 - La variabile che è utile per regolare la velocità nella rotazione

Se seguite dove e come viene utilizzata questa variabile noterete che lo sketch inizia facendo ruotare velocemente il motore ripetendo i vari pezzi di codice sempre più lentamente, rallentando il motore nella rotazione.

Vediamo un pezzo della funzione Loop, che è il programma principale di ogni sketch :

Fig. 13 - Parte della funzione Loop dello skecth - di Paolo Luongo
Fig. 13 - Parte della funzione Loop dello skecth - di Paolo Luongo

A questo punto credo sia tutto, se avete dei dubbi potete scrivermi o commentare l'articolo.
Se non conosci i motori passo passo leggi questo articolo.
Qui trovate gli altri articoli pubblicati.

Buon anno nuovo e buon lavoro !

Ciao
Paolo :-)

18 commenti:

Alessandro Mura ha detto...
Questo commento è stato eliminato dall'autore.
Alessandro Mura ha detto...

Quello che penso vada fatto, mi darai conferma, è modificare il valore "delay(500);" presente nel codice

Paolo PerCdS ha detto...

Si, Alessandro, hai ragione. Per cambiare la "pausa" fra una rotazione di 90 gradi e l'altra bisogna intervenire sul delay(500) presente in Fig.13.
Grazie per la puntuale precisazione. :-)

Alessandro Mura ha detto...
Questo commento è stato eliminato dall'autore.
Alessandro Mura ha detto...
Questo commento è stato eliminato dall'autore.
Paolo PerCdS ha detto...

Premesso che un motore passo passo viene utilizzato proprio perchè non ha bisogno di feedback per essere controllato, nulla vieta di aggiungere dei sensori di "fine corsa".
Il tempo di esecuzione, considerando che il valore in Fig. 12 sia di 1 mS (e non considerando le altre istruzioni) ci da 4096 mS ossia di 4,096 secondi. Quindi il tempo minimo di una rotazione completa, anche se in modo grossolano, si può stimare. Resta inteso che se serve un valore reale non resta che cronometrare utilizzando la console e visualizzando il tempo di inizio e fine. Tuttavia questa stima, per essere realistica, deve essere fatta con il giusto "carico" sul motore. Infine, se il carico è eccessivo e la frequenza con cui si pilota il motore è superiore alle specifiche può accadere che "salti" qualche passo non riuscendo a completare il giro in modo corretto.
Il problema del loop infinto è solo un banale problema di programmazione, molto semplice da risolvere.
Mi piace la frase "... arduino non sa". Io spero che non lo "sappia mai" altrimenti ho finito di lavorare. Ovviamente mi riferisco alla definizione di "consapevolezza" data da Federico Faggin.
Buon lavoro
Paolo

Alessandro Mura ha detto...

Paolo ho letto tutto con chiarezza, ma non mi hai dato una tua soluzione al problema prospettato :)
Ammettendo di far compiere un giro con step di 45 gradi (ad esempio) e sapendo che ad ogni 45 gradi si dovrà fermare per X secondi come gestisci lo stop dopo un giro? puoi creare uno sketch? Sono curioso di una tua interpretazione del problema..

Paolo PerCdS ha detto...

Lo sketch per far fare un solo giro al motore e poi fermarlo è nelle FAQ .

Alessandro ti ricordo che il mio obiettivo e di aiutare le persone con possibili soluzioni, non fare software su richiesta.
;-)

Buon lavoro
Paolo

Alessandro Mura ha detto...
Questo commento è stato eliminato dall'autore.
Alessandro Mura ha detto...

Paolo, il punto non è fare un sw su richiesta ma comprendere il codice da te scritto.
Ad esempio:
Io ho letto e riletto il codice "modificato" che hai riproposto nella sezione FAQ e l'ho eseguito.
La parte modificate è la seguente:
void esempio1()
{
digitalWrite(13,HIGH); //acceso LED13
RuotaDi360Gradi(RotazioneOraria);
digitalWrite(13,LOW); //spento LED13
stato=MotoreOFF;
EseguiPasso(); //spegne le luci sul motore
}

int a=0;

void loop() // fa solo un giro di 360 gradi
{
if (a==0) esempio1();
a=1;
}

Bene, con questo sketch hai comandato lo stepper ad eseguire un giro richiamando la funzione "RuotaDi360Gradi".
Se cambio funzione ed utilizzo "RuotaDi180Gradi" lo stepper dovrebbe fare due step da 180 gradi ciascuno e fermarsi, ma così non fa.
Dove sbaglio? Non capisco la correlazione che vi è tra la funzione chiamata e ciò che si trova all'interno del loop.
Grazie

Paolo Paolucci ha detto...

Ciao,
ho trovato su youtube un commento che calcola esattamente i passi dello stepper partendo dal numero dei denti delle singole ruote dentate. Alla fine si ottiene che lo stepper ha 2037,8 passi per rivoluzione.

[quote]Disassembling my eBay (Abeyerr) bought 28BJY-48 5V, I single stepped it and determined that mine have 32 steps and a reduction gear ratio of (32÷9)×(22÷11)×(26÷9)×(31÷10)=63.683950617 for 2037.886419753 steps/revolution. I've double checked the gear count. Like yours it maxes out at 14 RPM but could probably be made quicker using acceleration and higher voltage.[/quote]

Cosa ne pensi?

Alessandro Mura ha detto...
Questo commento è stato eliminato dall'autore.
Paolo PerCdS ha detto...

Ciao Paolo Panucci e grazie per il tuo contributo alla discussione.
Per esperienza diretta, confermo che i passi per un giro completo del motore (giro di 360 gradi) sono 4096.

Ciao Alessandro, mi dispiace che lo sketch che ho realizzato non ti sia di facile lettura e capisco anche l'urgenza di realizzare lo sketch per l'esame. Purtroppo la seconda parte dell'articolo sullo stepper 28BYJ48 non sarà pronta prima del fine settimana, se riesco a liberarmi un pò dal lavoro... e sarà veramente dura.
Tuttavia mi permetto di darti un suggerimento: metti da parte i miei sketch ed utilizza una delle librerie "ufficiali" per i motori passo passo, ossia la Stepper Library. Ha degli esempi che troverai semplici e chiari, oltre ad agevolarti nel tuo sketch. La libreria si trova seguendo questo link dal sito di arduino http://arduino.cc .

Cordialmente
Paolo :-)

Paolo PerCdS ha detto...

Ciao Paolo Paolucci, prima di tutto ... scusa se ho sbagliato il tuo cognome nel commento precedente.
Inoltre la tua osservazione mi ha fatto nascere qualche dubbio perchè anche io ho smontato qualche stepper per capire perchè i conti non mi tornavano. Ti confermo che la tua segnalazione è giusta ed è giusta anche la mia: la soluzione è (forse) nel modo in cui si comandano i motori passo passo.
Io conosco tre modi escludento le varianti PWM: Wavemode, Two phase-on e Half-step.
Di solito, preferisco la terza e quindi col mio sketch i "passi" sono 4096, ma con le altre due modalità sono la metà ossia 2048.
Numero molto vicino al commento del tuo post.
La questione si fà interessante, devo approfondire ;-)

gugugu ha detto...

Domanda da ignorante.
Sulla stampante 3d ho dei motorini 28byj48 con la scritta 1/32.
Online trovo solo quelli con scritto 1/64...
sono effettivamente due modelli diversi o e lo stesso e si gestisce poi tramite codice?
grazie,
gs

Paolo PerCdS ha detto...

Caro gugugu (complimenti per il nick name ... è tutto un programma), da "ignorante" ti rispondo che non conosco i motorini con la scritta 1/32. Poi ti faccio una domanda: Non ti sembra più logico chiedere questa informazione a chi ti ha venduto questi motorini ?
Buon lavoro
Paolo
;-)

Andrea Corinaldesi ha detto...

Per una particolare applicazione a cui sto lavorando ho bisogno di ridurre il consumo del motore perchè alimentato a batteria. Nell'articolo parla di un assorbimento di circa 100mA per fase, valore che ho riscontrato sperimentalmente, ma troppo elevato. Sono disposto a sacrificare un pò di coppia perchè non c'è un grande carico collegato al motore. Lei ha qualche idea su come fare? il suo aiuto mi sarebbe molto utile

cordialmente
Andrea

Paolo PerCdS ha detto...

Ciao Andrea Corinaldesi,
il problema di fondo è che i motori passo passo non sono indicati per il funzionamento a batteria perchè, almeno una fase, deve essere sempre alimentata per mantenere "fermo" il motore.
Se l'uso di un normale motorino non è adatto al tuo progetto puoi aggiungere un resistore in serie ad ogni fase del motore passo passo: non che la cosa mi piaccia, ma è la più semplice da provare.
Il valore deve essere trovato in modo empirico, privilegiando il valore più basso, per il miglior compromesso coppia/corrente assorbita.
L'alternativa migliore è controllare il motore passo passo con la pulse-width modulation (PWM) ma si complica sia l'Hardware che il Software di controllo.
Buon lavoro.
Paolo ;-)