Cambiare microstep all'interno di un ciclo

Salve a tutti.
Propongo un quesito per il quale, al momento, non ho trovato risposta.
Scheda Arduino Due, Stepper Nema 17, DRV8825, libreria Accelstepper (ma la libreria non è importante ai fini del problema principale).
All'interno di un loop avvio lo stepper in half-step, assegnado ai pin

digitalWrite (DEC_MODE0, HIGH);
digitalWrite (DEC_MODE1, LOW);
digitalWrite (DEC_MODE2, LOW);

premendo un pulsante, passo in 1/16-step, assegnando ai pin

digitalWrite (RA_MODE0, LOW);
digitalWrite (RA_MODE1, LOW);
digitalWrite (RA_MODE2, HIGH);

Fin qui tutto ok, il motore in effetti passa da half-step a 1/16-step senza problemi, e viceversa.
Il problema:
Che si operi a 1/2-step o 1/16-step, non riesco a far leggere il giusto numero di step; in sostanza, il passaggio crea un impiccio nel numero di step. Io vorrei che propozionalmente, passando da una risoluzione a un'altra, la libreria riuscisse ad assegnare il giusto numero di step, "proporzionato" al settaggio impostato in quel momento.
Ad esempio, se in 1/16-step leggo 8000 step, passando a 1/2 dovrei leggere 1000 step; invece spesso continuo a leggere 8000, e viceversa.
Sbaglio qualcosa o semplicemente non posso switchare il microstepping al volo senza perdere il giusto numero di step?
Grazie,
saluti a tutti.

Credo che la libreria sia invece fondamentale. In numero di step a giro viene stabilito o calcolato dalla libreria, se la libreria non lo fa o non lo fa correttamente, risulta che il problema sia la libreria.
Adesso bisognerebbe conoscere esattamente come è fatta la libreria per individuare il problema, seconda cosa vengono fornite diverse librerie con lo stesso nome. In pratica potremmo avere più versioni della libreria che stai usando, una scritta in un modo e l'altra in un altro. Trovare possibili bug in una libreria bisogna essere in grado di farlo e avere voglia di farlo...

Non è chiaro da dove leggi il numero di step infatti.

Inoltre, che utilità ha? Se il motore perde passi non avresti comunque nessun tipo di feedback.

Se lo scopo è monitorare la rotazione del motore, dovresti aggiungere un encoder, magari direttamente sul motore (encoder ad effetto Hall) per semplificare l'installazione.

Ciao Cotestant.
In effetti vorrei evitare l'uso dell'encoder. La mia è una lettura che si effettua semplicemente con un:

Serial.print (stepper1.currentPosition());

Con Accelstepper, currentPosition() visualizza il numero di step. Mi occorre per fare dei calcoli rapportati a un angolo orario, che devono essere naturalmente precisi. Certo, non al millesimo, ma al secondo sì.
Mi spiego meglio:


Dalla figura si evince che io parto in 1/2 step per tutto lo spicchio denominato "I", mi fermo e leggo con "stepper1.currentPosition())" il valore 100. Commuto a 1/16 step e per tutto il quadrante "II" avanzo con questa risoluzione, mi fermo e leggo con "stepper1.currentPosition())" il valore 1400. Commuto di nuovo a 1/2 e avanzo per tutto il quadrante "III", ma anziché leggere i valori riportati in figura, ottengo dei valori "sballati". Ecco, io vorrei leggere sempre dati attinenti alla risoluzione impostata, e non valori sfalsati. Tutto qui.
Saluti a tutti

Ok, adesso è più chiaro.

Io temo che tu stia facendo confusione sul valore che la libreria restituisce con il metodo currentPosition().

La posizione a cui fa riferimento la libreria, non ha alcuna relazione con il microstepping che vai a impostare fisicamente sul driver infatti fai tutto "esternamente" alla libreria con il digitalWrite().
Sei tu nel codice che devi fare le opportune proporzioni e scalare la posizione reale del motore in funzione del microstepping selezionato, quindi se lo modifichi in corsa devi aggiustare di conseguenza.

In pratica quel metodo ti restituisce il valore della proprietà privata della libreria _currentPos che viene incrementata quando fai uno step in verso di rotazione e decrementata se giri al contrario.

Questa variabile è indipendente dall'hardware, quindi se sei in half step ed incrementi di 100 il motore avanza di 50*1.8° posizionandosi a 90°.
Quando imposti il driver in 1/16 di passo ed incrementi di 800 il motore avanza di altri 800/16 = 50 passi da 1.8° posizionandosi a 180°, ma la variabile in questione ti dirà che sei arrivato alla posizione 900 ovvero tutti gli impulsi che il micro ha dovuto generare per arrivare fin li.

Dunque... provo a ragionare...
la libreria Accelstepper, da specifiche dice:
currentPosition(): Returns the current motor position in steps. Positive is clockwise from the 0 position.
Interpretando ciò che dice la libreria, sembrerebbe che fino a che non cambio il microstepping, lui (in base allo zero iniziale, di partenza) mi fornisca sempre la posizione corretta. Io mi limiterò a normalizzare la coordinata in positivo nel caso facessi ruotare all'indietro il motore, e ripassassi per lo zero, nel senso inverso, ottenendo pertanto un "-" nel valore degli step. Perchè solo ripassato lo zero segnerà gli step negativi. Naturalmente il disegno, essendo il senso orario positivo, interpretalo al contrario. E in effetti, facendo varie prove, così funziona. Il problema sorge nel punto da te indicato, laddove la libreria non interviene nel momento in cui cambio la risoluzione. Penso pertanto che purtroppo, come dici tu, dovrò scalare in corsa il valore di ritorno. Speravo in una cosa più immediata. Provo e farò sapere...
@torn24 Non parlerei di bug, piuttosto di una mia scarsa conoscenza su questo argomento in particolare, che sto approfondendo in questo periodo. La libreria, come noto, è parecchio bella, a me ha aiutato parecchio.
Grazie, saluti

Bhè dai non è una cosa poi cosi complicata da fare.
Tieni traccia del valore del microstepping in una variabile e in funzione di quella adatti la tua variabile che tiene traccia della posizione.

int actualPosition = 0;
int steppingValue = 2;

// istruzioni per set microstepping a 1/2 //


stepper1.moveTo(100)
actualPosition  = stepper1.currentPosition() / steppingValue ;

// istruzioni per set cambio microstepping a 1/16 //

steppingValue = 16;
stepper1.moveTo(100 + 800);
actualPosition  = stepper1.currentPosition() / steppingValue ;

Grazie per la traccia!
Tutto molto chiaro e semplice...

Ok, ho provato velocemente la versione che ha proposto @cotestatnt, e fila tutto bene. Semplice e immediato, non penso abbia bisogno di ulteriori commenti, anche perché cotestant è stato preciso.
Propongo invece una seconda versione, derivata da una lettura più attenta della libreria Accelstepper. Conoscevo già la funzione “setCurrentPosition()”, però leggendo nel dettaglio, il sito dell’ideatore della libreria specifica (tradotto):
“Reimposta la posizione corrente del motore, in modo che ovunque si trovi il motore in questo momento viene considerata la nuova posizione 0. Utile per impostare una posizione zero su uno stepper dopo un movimento di posizionamento hardware iniziale. Ha l'effetto collaterale di impostare la velocità del motore corrente su 0.”
Più nel dettaglio, la funzione della libreria è questa:
void AccelStepper::setCurrentPosition (long position) ,
cioè, avevo (male) interpretato che avrei dovuto assegnare uno zero alla funzione (stepper1.setCurrentPosition(0)), o che comunque la stessa avrebbe impostato a zero gli step una volta utilizzata. E in effetti in rete pare che altri abbiano frainteso. Accettando un long, per pura curiosità, anziché assegnare zero, ho provato a riassegnare il valore scalato della posizione dello stepper… e funziona.

Quindi, riassumendo, i passaggi che ho fatto sono questi.

1) Inizializzo la risoluzione a 1/2

2) Avvio il motore e lo fermo al punto desiderato.

3) Leggo la posizione, la moltiplico per 8 (scalato quindi per la risoluzione 1/16 di step) e la memorizzo nella mia buona variabile stepNow.

4) Inizializzo la risoluzione a 1/16.

5) Assegno i giusti step per non confondere la libreria con stepper1.setCurrentPosition(stepNow);

6) Solo ora avvio il motore e lo fermo al punto desiderato.

7) Leggo la posizione, la divido per 8 (scalato quindi per la risoluzione ½ di step) e la memorizzo nella mia solita variabile stepNow.

8) Inizializzo la risoluzione a 1/2.

9) Assegno i giusti step con stepper1.setCurrentPosition(stepNow);

10) E riavvio il motore… e così via

E ora con stepper1.currentPosition() leggo sempre i valori corretti.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.