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?
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.
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?
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:
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
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
Intanto, si deve decidere una sintassi valida ... esempio:
il primo carattere DEVE essere sempre un carattere tra 'V', 'P' e ??? definisci quelli validi
i caratteri successivi DEVONO essere numerici (0 .. 9)
il numero minimo di caratteri numerici È 1 ... ovvero DEVI avere almeno un carattere numerico dopo il primo carattere
il numero massimo di caratteri numerici è ... 5 ? ovvero il numero di caratteri che servono per un intero senza segno ... ti bastano ?
Tutto DEVE sempre terminare con il carattere CR (0x0D)
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
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)
... 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;
}
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.
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".
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