stepper

ciao a tutti, sono ancora alle prese con un motore passo passo.
Volevo tramite due stringhe Pxxxx e Vxxxx passare rispettivamente i passi da eseguire e la velocità in rpm e tutto questo utilizzando la libreria <Stepper.h>
Pensavo fosse possibile variare in corsa i parametri "stepsPerRevolution" e "Rpm" direttamente nel "Loop" dopo aver trattato le stringhe ricevute in questo modo:

myStepper.setSpeed (Rpm);
e
myStepper.step(stepsPerRevolution);

ma ho visto che se faccio così il motore non gira, gira invece se li inserisco nelle definizioni iniziali e nel setup.

C'è un modo per variare velocità e passi da eseguire?

renato

Ti è stato già detto che cortesemente devi presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e leggere con attenzione il REGOLAMENTO ...
... ti sollecito a farlo. Grazie.

Guglielmo

Scusami, pensavo di averlo già fatto. Ora lo eseguirò di nuovo. Chiedo venia.

Ecco, sotto riporto il codice che ho scritto. Come scritto prima volevo tramite i parametri Pxxxx e Vxxxx, variare i passi e la velocità di esecuzione. Purtroppo scritto così non mi funziona.

#include <Stepper.h>
 #define dimVettore 5            // lunghezza max del buffer di lettura (stringa seriale)

  char stringaSERIALE[dimVettore + 1]; // stringa buffer. Deve sempre essere sempre della lunghezza + 1 
  char  Parameter;
  int   Rpm, comand, fineLettura, i;    //stepsPerRevolution=velocità
  int   stepsPerRevolution;
  
  //const int stepsPerRevolution = 200;  // setto i passi per giro per il motore
                                    
  // creo una istanza della classe stepper "myStepper"
  // si indicano i passi/giro, nel nostro caso motore da 1,8° gradi/passo quindi 200 
  // e i pin collegati agli avvolgimenti.
  Stepper myStepper(stepsPerRevolution, 2,3,4,5);            
  
  void setup() {
  // setto la velocità a 60 giri minuto per l'istanza creata:
  myStepper.setSpeed(60);
  // inizializo la seriale:
  Serial.begin(9600);
}
void loop() {

   if (Serial.available()>0)leggiSeriale();
        
   if (comand==1){ 
      Serial.println("Go");
      //stepsPerRevolution=200;
      myStepper.step(stepsPerRevolution);
      delay(500);
      comand=0;
   }
     
}


// funzione lettura seriale
void leggiSeriale()
{
 
  int index=0;
  do    
    {
       if(Serial.available()> 0)                
        {
          stringaSERIALE[index]=Serial.read();  
          index++;                            
          }
           
     fineLettura = ( (index >= dimVettore));
     }
   while (!fineLettura);  

   index=0; 
   Parameter=stringaSERIALE[index];
    //stampa della stringa ricevuta
   Serial.print ("Stringa ricevuta: ");
   for (index=0; index<dimVettore;index++)
    {
    Serial.print(stringaSERIALE[index]);
    }   
   Serial.print ("\n"); 


   //stampa del parametro ricevuto  
  if (Parameter=='P') 
      {
      index=0;  
      stepsPerRevolution= (((stringaSERIALE[1]-48)*1000)+ ((stringaSERIALE[2]-48)*100)+((stringaSERIALE[3]-48)*10)+ ((stringaSERIALE[4]-48)*1));  
      Serial.print ("Passi da eseguire: ");
      Serial.println(stepsPerRevolution);
      comand=1;
      } 
  else if (Parameter=='V') 
      {
      Rpm= atoi(&stringaSERIALE[1]);
      Serial.print ("Rpm (giri/minuto): ");
      Serial.println(Rpm);
      myStepper.setSpeed(Rpm);
      }
      
//fine funzione seriale  
    
}

Non funziona nel senso che non modifica i parametri? Il messaggio "Go" te lo stampa correttamente (ovvero ... entra nella IF)? Un link alla libreria che stai usando?

Guglielmo

grazie mille per la risposta!
Non so come sia, dopo averlo "pulito" per metterlo sul forum, l'ho ricaricato e funziona: mi cambia i passi e la velocità. Quello che volevo.
Ora sono alle prese con la funzione per svuotare il buffer array nel caso la stringa non sia corretta.

quello che ottengo sulla seriale è questo:

Stringa ricevuta: V0300
Rpm (giri/minuto): 300
Stringa ricevuta: P0800
Passi da eseguire: 800
Go

Fin qui tutto bene, esegue i passi. Se però sbaglio a scrivere il buffer mi rimane sporco, non riesco più a riprendere la stringa corretta.
Qui sbaglio a scrivere e digito un carattere in più: P08000. Quello che poi ottengo è questo:

Stringa ricevuta: P0800
Passi da eseguire: 800
Go

e poi digitando correttamento P0800

Stringa ricevuta: 0P080
Stringa non valida:

grazie ancora

Prova, prima di iniziare a ricevere i dati, a pulire il buffer ... basta che con una FOR lo riempi di 0x00 che, oltretutto, sono gli identificativi di fine stringa.

Comunque, personalmente, NON mi piace affatto come gestisci la cosa ... e i risultati ti mostrano i limiti di una gestione senza un carattere identificatore di "fine messaggio" (es. CR ovvero 0x0D) e senza una analisi di "correttezza del messaggio" ...
... e, io che sono un maniaco, ci aggiungerei anche un carattere di controllo CRC per verificare che il messaggio non si sia corrotto durante il transito :smiley: :smiley: :smiley:

Guglielmo

Dici poco! concordo in tutto con te. Se hai tempo e se non ti disturbo troppo potresti indicarmi un link oppure un esempio di un controllo anche sul solo controllo ?
grazie mille! Dopo tre ore che ci "giro" per oggi, ahimè, devo abbandonare.
Renato

Se fai qualche ricerca qui sul forum se ne è parlato un sacco di volte ... ma comunque tu sei già a buon punto, inutile buttare il tutto, meglio mettersi li e sistemare/modificare/integrare quello che già c'è ... così impari pure :wink:

Intanto, si deve decidere una sintassi valida ... esempio:

  1. il primo carattere DEVE essere sempre un carattere tra 'V', 'P' e ??? definisci quelli validi
  2. i caratteri successivi DEVONO essere numerici (0 .. 9)
  3. il numero minimo di caratteri numerici È 1 ... ovvero DEVI avere almeno un carattere numerico dopo il primo carattere
  4. il numero massimo di caratteri numerici è ... 5 ? ovvero il numero di caratteri che servono per un intero senza segno ... ti bastano ?
  5. Tutto DEVE sempre terminare con il carattere CR (0x0D)
  6. se si super ail limite di lunghezza del buffer e NON si è ricevuto il CR ... il dato NON è valido, lo si scarta e non si deve fare alcuna azione.

... quindi, fai un programmino a parte SOLO con lo scopo di leggere correttamente la seriale, prendi la tua routine leggiSeriale(), butta via tutto quello che non ci serve al momento e imposta SOLO le cose che abbiamo detto. Ovviamente, se abbiamo 1 carattere + massimo 5 numeri + il CR ... il buffer dovrà essere di 7+1 (il fine stringa 0x00) = 8 char :wink:

OK ?

Guglielmo

ciao e grazie di nuovo. Sto continuando con il controllo della stringa.
Dapprima vorrei controllare se il primo carattere ricevuto è, nel mio caso, una P o una V e questo pensavo di scriverlo dopo la ricezione completa della stringa stessa. Poi controllare se i a seguire sono effettivamente caratteri numerici (0-9).
Ho scritto quello che segue per inziare, ma mi da "stringa non valida" anche se inizio con P o V.

  int index=0;
  do    
    {
       if(Serial.available()> 0)                
        {
          stringaSERIALE[index]=Serial.read();  
          index++;                            
        }
       
     fineLettura = ( (index >= dimVettore));// 
     }
   while (!fineLettura);  

   if  (stringaSERIALE[0]!=('P' || 'V')){
        Serial.println ("Stringa non valida");
   }

eppure dovrebbe essere scritto: se il primo carattere della stringa è diverso da P o V allora scrivi Stringa non valida.
Renato

Purtroppo in 'C' NON si scrive così ...
... in quel modo sai cosa hai fatto ? Hai fatto OR Booleano tra 'P' (0x50) e 'V' (0x56) e DOPO hai confrontato stringaSERIALE[0] con il risultato del OR (0x50 diverso da 0 qundi TRUE, 0x56 diverso da 0 quindi TRUE, TRUE OR Booleano con TRUE da cui il risultato è = TRUE) :wink:

La sintassi corretta è :

if ( (stringaSERIALE[0] != 'P') && (stringaSERIALE[0] != 'V') ) { ..... }

... ovvero, se stringaSERIALE[0] != 'P' ed è anche stringaSERIALE[0] != 'V', allora non è né 'P' né 'V' e quindi dai errore.

Naturalmente potevi anche fare un piccolo switch/case ...
... che poi sarebbe facilmente espandibile per "comandi" futuri:

switch (stringaSERIALE[0]) {
  case 'P':
    // fai quello che devi fare per 'P'
    break;
  case 'V':
    // fai quello che devi fare per 'V'
    break;
  default:
    // dai il messaggio di errore per comando sconosciuto
    break;
}

Guglielmo

Scusami, ma sono proprio un neofita. Ho scritto come segue, facendo il controllo su ogni carattere.

 if  (stringaSERIALE[0]==('P' ))
        Serial.println ("Stringa valida");
   else if   (stringaSERIALE[0]==('V' ))
        Serial.println ("Stringa valida");     
   else 
        Serial.println ("Stringa non valida");

Magari ci sarà un modo meno arcaico per scriverlo ma pare funzioni.
Intanto continuo con il resto
Renato

  1. ti consiglio di studiarti lo switch/case che ti semplifica la vita ...

  2. puoi semplificare i tuoi IF eliminando parentesi inutili ...

if (stringaSERIALE[0] == 'P')
   Serial.println ("Stringa valida");
else if (stringaSERIALE[0] == 'V')
   Serial.println ("Stringa valida");     
else 
   Serial.println ("Stringa non valida");

Guglielmo

Perfetto, dovrebbe essere più leggibile in questo modo:

Comand =  stringaSERIALE[0];
         switch (Comand) {  
          case 'P': Serial.println ("Stringa valida");
          break;
          case 'V': Serial.println ("Stringa valida");                                           
          break;
          default:
          Serial.println ("Stringa non valida");
          }

Ora provo debbo controllare se i caratteri a seguire a sono numerici, questo pensavo di farlo dentro alla ricezione ovvero qui:

 int index=0;
  do    
    {
       if(Serial.available()> 0)                
        {
          stringaSERIALE[index]=Serial.read();  
          index++;
                                      
        }
   fineLettura = ( index >= dimVettore);// 
     }

Intanto ancora grazie.
Renato

In realtà io avrei controllato tutto in tempo reale, mano mano che si riceve ...

... se index == 0 controlli se il carattere ricevuto è 'P', 'V' ...
... se index > 0 e index < max_index controlli se il carattere ricevuto è tra '0' e '9' oppure CR
... se index == max_index controlli se il carattere ricevuto è CR

se una delle condizioni NON è verificata, tutto quello che ricevi dopo, sino al 'CR' o al limite del buffer (... o al timeout, perché occorrerà tenere conto anche di questo) lo scarti e alla fine torni indietro un codice di errore.

Guglielmo

Ho scritto quello di cui sotto, ma come sempre non funziona.

 int index=0,NoValidChar=0 ;
  do    
    {
       if(Serial.available()> 0)                
        {
          stringaSERIALE[index]=Serial.read();  
          if (index>0){
                   
            if  ((stringaSERIALE[index]< 0x30)||(stringaSERIALE[index]> 0x39)){
              NoValidChar=1;
              Serial.println ("No carattere valido");
            }  
          }
          index++;
                                        
        }
   fineLettura = (( index >= dimVettore)||(NoValidChar=1));;//

per come la leggo io: se index>0, controllo se il carattere è compreso tra '0' e '9'. Se così esco. Però non mi passa se non scrive "No carattere valido".

leggo ora il tuo ultimo post. Seguirò il tuo consiglio.

ciao Guglielmo, sono tornato alla stesura, sempre da neofita, del controllo su stringhe.
Per riassumere, vorrei ricevere delle stringhe per il comando di un motore passo passo. Le stringhe possono essere Pxxxx per i passi da compiere, Vxxxx per i giri motore, G per il Go, S per lo stop. Ovviamente per ogni carattere devo controllare la lunghezza della stringa, che i caratteri siano numerici e che l', sia al posto corretto.
La prima domanda è se il controllo che tu dici di fare lo debbo eseguire dopo aver ricevuto la stringa o mentre la ricevo. La seconda è che, avendo già sbiaricato qua e là ma non avendo trovato nulla di simile a quello che voglio fare è se tu hai qualche link da suggerire.
Grazie mille