Accelstepper

Salve

Ho seguito il consiglio di Torn24 e per muovere il braccio robotico sto utilizzando la libreria accelstepper.
Il codice che ho scritto dovrebbe a 4000 passi di distanza dall'arrivo dello stepper1 muovere gia' lo stepper 2 che a sua volta prima che arrivi in fondo corsa(5000) e precisamente a meno di 2500 passi dovrebbe muovere lo stepper 3 che arrivando in fondo corsa fa indietreggiare di 4000 passi lo stepper 1. l'introduzione di una variabile(prova)
impostata ora sullo zero dovrebbe farmi ripetere il ciclo sempre.
Purtroppo non e' cosi',completato il ritorno dello stepper 1 il ciclo si ferma.
Se qualcuno mi sa indicare il perche' lo ringrazio.
Saluti

 #include <AccelStepper.h>

 int prova=0;
//int verso = 1;

AccelStepper stepper1(AccelStepper::FULL2WIRE,2,3 );
AccelStepper stepper2(AccelStepper::FULL2WIRE,6,7 );
AccelStepper stepper3(AccelStepper::FULL2WIRE,10,9 );
void setup()
{ 
    stepper1.setMaxSpeed(100000.0);
    stepper1.setAcceleration(2000.0);
    stepper2.setMaxSpeed(100000.0);
    stepper2.setAcceleration(2000.0);
    stepper3.setMaxSpeed(100000.0);
    stepper3.setAcceleration(2000.0);
    stepper1.move(8000);
    pinMode(13,OUTPUT);
}

void loop()
{
   
    
    if(stepper1.distanceToGo () == 4000 &&(prova==0))
    {
       stepper2.move(5000); 
       digitalWrite(13,HIGH);
       prova=1;
    }
    if(stepper2.distanceToGo() ==2500 &&(prova==1))
    {
       stepper3.move(1500); 
       prova=2;
      }
       if(stepper3.distanceToGo() ==0 &&(prova==2))
    {
       stepper1.move(-4000); 
       prova=0;

      }
 
        
    stepper1.run();
    stepper2.run();
    stepper3.run();
         
}

Al posto di quelle if potresti usare uno switch case come di seguito,

switch (state)
    {

        case 0:
            // qui il tuo codice quando state == 0
            state = 1; // switch to state 1
            break;

        case 1:
            // qui il tuo codice quando state == 1
            state = 2; // switch to state 2
            break;

        case 2:
            // qui il tuo codice quando state == 2
            state = 3; // switch to state 3
            break;

        case 3:
            // qui il tuo codice quando state == 3
            state = 0; // switch to state 0

            break;
    }

Sinceramente non capisco perché non ricominci, anzi per me non dovrebbe neanche entrare in questa if:

   if(stepper3.distanceToGo() ==0 &&(prova==2))
    {
       stepper1.move(-4000);
       prova=0;

      }

Però non riesco a seguire il codice perché ci sono varie versioni di questa lib e non so da dove l'hai presa.

Ciao.

Ti ringrazio dell'attenzione,purtroppo ho sempre utilizzato in altri progetti anche complicati questa sequenza
con una variabile che alla fine assumeva il valore zero per far ricominciare il ciclo all'infinito.
Pero' con motori in c.c. e rele' ma non stepper.
Vedo che qui nascono dei problemi.
La parte di codice che hai postato e' senza dubbio piu' fluida ma non ho mai utilizzato switch
capisco che sia' migliorativa ma ho difficolta' a completarla. Anzi mi piacerebbe farlo.
Se vuoi puoi modificare il codice che ho postato introducendo questo aspetto migliorativo e cosi' ho anche l'opportunita' di comprenderlo e per questo ti ringrazio.
La libreria accelstepper porta poche istruzioni che ti mando.
Saluti

Funzioni accelstepper.pdf (15.6 KB)

switch (prova)
    {

        case 0:
            // qui il tuo codice quando state == 0
            prova = 1; // switch to state 1
            break;

        case 1:
            // qui il tuo codice quando state == 1
            prova = 2; // switch to state 2
            break;

        case 2:
            // qui il tuo codice quando state == 2
            prova = 3; // switch to state 3
            break;

        case 3:
            // qui il tuo codice quando state == 3
            serial.println("prova 3");
            prova = 0; // switch to state 0

            break;
    }

Ho già messo il naso su questa libreria in passato ma devo dire che non la so usare al momento.
Io posso scaricare questa:AccelStepper: AccelStepper library for Arduino

Lo switch è semplice da seguire ed è quello che fai tu con le if, ora che ho sostituto
la variabile state con prova dovrebbe essere più chiaro seguire il funzionamento.

Se ancora non è chiaro aiutati con stampando su serial monitor come ho fatto in case 3
Ciao.

Ad ogni valore di case (0,1,2,ecc accade una azione che e' quella raccolta tra case(valore) e il suo breck.
Per dare continuita tra i vari "case" si utilizza la variabile che nel mio caso e' "prova".
La stessa viene riconosciuta dal case successivo "perche' il suo numero coincide con quello di "prova"?

Non so se sono sulla strada giusta comunque il tutto si complica se prima di arrivare al valore della variabile prova
ci sono piu'if.
Es: In questo listato consideriamo anche l'accensione e spegnimento di un led.
Lo stepper parte in accelerazione,si accende e si spegne un led e dopo lo stepper viene bloccato nella nuova posizione.

const int stepPin1 = 2;//primo motore 
const int dirPin1 = 3;//primo motore 
const int stepPin2 = 6;//secondo motore 
const int dirPin2 = 7; //secondo motore 
const int stepPin3 = 10;//terzo motore 
const int dirPin3 = 9;//terzo motore
int tempo=2500;
int prova=0;
int tempo1=1500; 

 void setup()
 {
  
  // Sets the two pins as Outputs
  pinMode(stepPin1,OUTPUT); 
  pinMode(dirPin1,OUTPUT);
  pinMode(stepPin2,OUTPUT); 
  pinMode(dirPin2,OUTPUT);
   pinMode(stepPin3,OUTPUT); 
  pinMode(dirPin3,OUTPUT);
   
  pinMode(13,OUTPUT);
  
}
void loop()
{
 if(prova==0)
 {
     digitalWrite(dirPin1,HIGH); 
     for (int x = 0; x < 4000; x++)
     {
    
        digitalWrite(stepPin1,HIGH); 
        delayMicroseconds(tempo); 
        digitalWrite(stepPin1,LOW); 
        delayMicroseconds(tempo);
       
        if(x==300)
{
digitalWrite(13,HIGH);
  }
   if(x==500)
{
digitalWrite(13,LOW);
  }
   
        if( tempo>500)//lentezza della velocita' che prende dopo accelerazione piu' e' alto e piu' va piano 400
        {
             tempo-=2;
             
             prova=1;
              }
               }
       }
   }

In questo caso cosa suggeriresti?

Ciao

const int stepPin1 = 2;//primo motore
const int dirPin1 = 3;//primo motore
const int stepPin2 = 6;//secondo motore
const int dirPin2 = 7; //secondo motore
const int stepPin3 = 10;//terzo motore
const int dirPin3 = 9;//terzo motore
byte currentState = 0;  // lo stato corrente 
boolean direction = HIGH;
unsigned long nStep = 0;
int tempo=3000;
int prova=0;


void setup()
{
    
    // Sets the two pins as Outputs
    pinMode(stepPin1,OUTPUT);
    pinMode(dirPin1,OUTPUT);
    pinMode(stepPin2,OUTPUT);
    pinMode(dirPin2,OUTPUT);
    pinMode(stepPin3,OUTPUT);
    pinMode(dirPin3,OUTPUT);
    
    pinMode(13,OUTPUT);
    
}

void loop()
{
    switch (currentState) {
    case 0:   
        digitalWrite(dirPin1, direction);  // set direction
        currentState = 1;
        break;
        
    case 1:
        // partenza e accelerazione fino a tot 
        digitalWrite(stepPin1,HIGH);
        delayMicroseconds(tempo);
        digitalWrite(stepPin1,LOW);
        delayMicroseconds(tempo);
        nStep++;  // incrementa di 1 nStep
        
        if (nStep <1000) // riduce tempo di 1 per ogni step, dopo 1000 step tempo = 3000 - 1000 = 2000
            tempo--;
        if (nStep == 4000)  // a 4000 step passa all case 2
            currentState = 2;
        break;
    case 2:
        direction = !direction;    // inverte la direzione
        nStep = 0;      //  azzera nStep
        if (direction == HIGH)  
            tempo = 3000;
        else
            tempo = 2000;  // parte più veloce quando direction è LOW
        currentState = 0;  // riparte da 0
    
    }
}

Purtroppo non posso provarlo su arduino, quindi controlla se manca qualche ; () {} ecc.

Dovrebbe la prima volta impostare la direzione HIGH e passare a case 1.
Su case 1 accelerare linearmente da 0 a 1000 step per mantenere la velocità tempo - 1000.
Raggiunti i 4000 step passa a case 2.

Case 2 inverte la direzione e imposta variabile tempo e lasci lo stato corrente per poi passare al case 0.

Accidenti che bravo!!!
Funziona alla grande.
Toglimi una curiosita' ma hai studiato su qualche libro di arduino o sul web?
Nel primo caso puoi consigliarmi un testo decente dove si possa imparare veramente oppure qualche
link.
Ora mi rimane da studiare quello che hai scritto e vedere se riesco a fare un piccolo passo in avanti.
Dopo di che allargare il discorso per coordinare gli altri motori.
Senza dubbio avro' ancora bisogno del tuo sostegno.
Ti ringrazio.

Accidenti che bravo!!!
Funziona alla grande.

Ok, mi fa piacere funzioni, tuttavia non è questo il modo di procedere per muovere 3 motori contemporaneamente e purtroppo io il modo corretto non lo conosco. Ho solo mostrato un esempio di uso switch case che è molto simile a come hai usato tu la variabile prova.

Toglimi una curiosita' ma hai studiato su qualche libro di arduino o sul web?
Nel primo caso puoi consigliarmi un testo decente dove si possa imparare veramente oppure qualche
link.

Ti do solo un link ad un PDF: Tiziana Marsella arduino

Mentre per il linguaggio C, ti basta fare una ricerca con google. il linguaggio C
Inizialmente ti devi concentrare su i tipi di variabile e i costrutti base, incluse le funzioni C.
Poi tutto quello che riesci a leggere di informatica può sempre tornare utile, ad esempio lo switch case viene impiegato per spiegare le macchina a stati finiti.

Ciao.

Grazie delle informazioni
Ciao

Il problema a non usare librerie è che poi devi scrivere un codice che faccia quello che farebbe la libreria.
Se devo eseguire una cosa in più posizioni del codice, come ti avevo già detto,è meglio crearsi una funzione personalizzata da richiamare quando è necessario.
Adesso hai creato il codice per un motore, è probabile che se devi agire su tre motori differenti dovrai ripetere il codice. Ecco qui l'utilità di una funzione che ricevendo argomenti può agire su tre o più motori differenti.
Poi io mi chiedo io, accelero e decelero un motore e quindi il movimento del braccio, ma quale sarebbe la giusta accelerazione da impostare, forse bisognerebbe avere accelerazioni e decelerazioni ben quantificate e calcolate ma io non sarei in grado di farlo :slight_smile: :slight_smile:

Ciao, 1oniudra2
Non ho studiato bene il codice, ma ho visto che per verificare i valori hai usato ==: in molti casi è bene usare >= (o <=, a seconda dei casi) perché se viene perso il momento in cui si ha l'uguaglianza (a causa di un'altra parte del programma in esecuzione) poi l'if non funziona più.

@ torn24

Si bisognerebbe conoscere la giusta accelerazione ma trattandosi di un braccio robotico che quello che dovra' fare sara' di prendere con le pinze un oggetto e spostarlo in un altra posizione mi accontento di variare i valori a vista per non creare troppe vibrazioni.Le parti strutturali le ho stampate con prusa 3d anche se c'e' da dire che per quanto riguarda i file stl non ci sono problemi ma dopo la stampa bisogna "adattare" i pezzi stampati per problemi nell'assemblaggio.
Comunque dopo aver "digerito" la sequenza del codice per far fare le operazioni programmate mi piacerebbe
modificare il codice stesso per far muovere contemporaneamente i motori.
Piano..piano.Tappa successiva.

@ Datman

Ti ringrazio del suggerimento
pensavo che fosse sufficiente == per far fare qualche cosa al sistema in un preciso momento.
es: dopo 1000 passi accendi un led,dopo 3000 passi spegnilo......
Se al posto di == metto <= dovrebbe restituirmi l'accensione subito....Ma avendo la consapevolezza
di essere alle prime armi mi scuso se ho scritto qualche cosa di sbagliato (probabile).
ciao

Sicuramente == va bene per verificare un'uguaglianza; a volte, però, in particolare se verifichi i millisecondi trascorsi, usando solo == può sfuggire inosservato l'istante in cui il valore coincide con quello previsto: in tal caso, pur essendo trascorso il tempo previsto, la condizione non è mai soddisfatta. Ad esempio, se il ciclo viene periodicamente interrotto da un sensore a ultrasuoni o da un pulseIn in attesa, le letture di millis()-t0 potrebbero essere:

988
991
992
995
996
999
1002
1003
1005

Se mettiamo un
if(millis()-t0==1000) {...}
tale condizione non sarà mai soddisfatta. Scrivendo, invece:
if(millis()-t0>=1000) {...}
la condizione sarà soddisfatta con la lettura 1002: con due millisecondi di ritardo, ma sarà soddisfatta.

Questo è un discorso di carattere generale, che va applicato nei casi in cui i valori cambiano abbastanza rapidamente ed è possibile che la lettura soddisfacente venga saltata. Altre volte, invece, bisogna assolutamente usare ==, perché la condizione deve essere soddisfatta solo se i due valori sono veramente uguali.

Nota: con variabili di tipo float (che, anche per questo, vanno usate solo se è assolutamente indispensabile) non bisogna usare ==, perché molto probabilmente la condizione non verrà mai soddisfatta! Ad esempio, se leggi una temperatura in Fahrenheit, la converti in Celsius e la elabori ulteriormente ottenendo un float irrazionale, poi vai a scrivere if(temperatura==20.0) {...} tale condizione non sarà mai soddisfatta, perché temperatura potrà valere 19,99768 o 20,00001 ma ben difficilmente 20,00000.

Ottima spiegazione.

Ora ne approffitto.
Vorrei ritornare al mio listato e tolta l'accelerazione per il momento per comodita ' vorrei che il secondo motore si attivasse quando il primo motore ha compiuto 5000 step con i parametri segnati.
Se vuoi correggere il listato stesso ti ringrazio perche' io non riesco a farlo ho provato con l'if cercando di stare attento alle parentesi niente da fare....

const int dirPin1 = 2;//primo motore 
const int stepPin1 = 3;//primo motore 
///////////////////////////////////
const int dirPin2 = 4;//secondo motore 
const int stepPin2 = 5; //secondo motore
////////////////////////////////// 
const int dirPin3 = 6;//terzo motore 
const int stepPin3 = 7;//terzo motore

int tempo=50;
int tempo1=10000;
int prova=0; 

 void setup()
 {
  
  // Sets the two pins as Outputs
  pinMode(stepPin1,OUTPUT); 
  pinMode(dirPin1,OUTPUT);
  pinMode(stepPin2,OUTPUT); 
  pinMode(dirPin2,OUTPUT);
  pinMode(stepPin3,OUTPUT); 
  pinMode(dirPin3,OUTPUT);
   
  pinMode(13,OUTPUT);
  
}
void loop()
{
 
 if(prova==0)
 {
     digitalWrite(dirPin1,LOW);  
     for (int x = 0; x < 10000; x++)//1000
     {
    
        digitalWrite(stepPin1,HIGH); 
        delayMicroseconds(tempo); 
        digitalWrite(stepPin1,LOW); 
        delayMicroseconds(tempo);
        
        prova=1;
              
       } 
   }
   if(prova==1)
 {
     digitalWrite(dirPin3,LOW);  
     for (int x = 0; x < 100; x++) 
     {
    
        digitalWrite(stepPin3,HIGH); 
        delayMicroseconds(tempo1); 
        digitalWrite(stepPin3,LOW); 
        delayMicroseconds(tempo1);
        
        prova=2;
              
       } 
   } 
   }
    
    
    ////////////////////////////////////////////////

ciao

L'invito e' esteso logicamente anche a Torn24.

P.S.
Ho ripreso il mio listato mettendo per il momento nel cassetto il tuo perche' ne ho piu' confidenza, poi risolto il problema lo adatto al tuo che e' senza dubbio migliorativo.
Saluti