Go Down

Topic: millis()....maledetto millis() (Read 11058 times) previous topic - next topic

elrospo

Salve a tutti

Il progetto che ho intenzione di realizzare è un semplice azionamento di un motore passo passo senza
usare le librerie.

Premesso che sono alle prime armi con la programmazione,ma ho gia affrontato millis(),
il mio problema è durante la programmazione .....millis() in pratica non fà quel che vorrei.

metto i pezzi di schetc......il problema è all'ultimo
Code: [Select]

int pulsante=2;
int bobina1=8;
int bobina2=9;
int bobina3=10;
int bobina4=11;
int bob1=0;
int bob2=0;
int bob3=0;
int bob4=0;
int conteggiopassi=0;
int girocompleto=512;
int partenza=0;
int rotazione;


fin quì tutto OK

Code: [Select]

void setup()
{
Serial.begin(9600);
pinMode(pulsante,INPUT);  
pinMode(bobina1,OUTPUT);
pinMode(bobina2,OUTPUT);
pinMode(bobina3,OUTPUT);
pinMode(bobina4,OUTPUT);
}


anche qui tutto ok

Code: [Select]

void loop()
{
 if(bob1==1){digitalWrite(bobina1,HIGH);}else{digitalWrite(bobina1,LOW);}
 if(bob2==1){digitalWrite(bobina2,HIGH);}else{digitalWrite(bobina2,LOW);}
 if(bob3==1){digitalWrite(bobina3,HIGH);}else{digitalWrite(bobina3,LOW);}
 if(bob4==1){digitalWrite(bobina4,HIGH);}else{digitalWrite(bobina4,LOW);}
 if(partenza==0){bob1=0;bob2=0;bob3=0;bob4=0;Serial.println("Motore Fermo");}
 Serial.print(bob1);
 Serial.print(bob2);
 Serial.print(bob3);
 Serial.print(bob4);
 Serial.println("");
  
 if(digitalRead(pulsante))
  {
  while(digitalRead(pulsante)){Serial.println("Senso Orario Via");}
  partenza=1;
  rotazione=0;
  Serial.print(partenza);
  Serial.print(rotazione);
  Serial.println("");
  }


anche qui tutto OK



i problemi cominciano QUI
Code: [Select]

if((partenza==1)&&(rotazione==0))
  {
  int velocita(1000);
  unsigned TEMPO=0;
  
  if(millis()>=TEMPO+velocita){bob1=1;bob2=0;bob3=0;bob4=0;}
  TEMPO=millis();
  if(millis()>=TEMPO+2000){bob1=1;bob2=1;bob3=0;bob4=0;}
  TEMPO=millis();
  if(millis()>=TEMPO+velocita){bob1=0;bob2=1;bob3=0;bob4=0;}
  TEMPO=millis();
  if(millis()>=TEMPO+velocita){bob1=0;bob2=1;bob3=1;bob4=0;}
  
  if(millis()>=TEMPO+velocita){bob1=0;bob2=0;bob3=1;bob4=0;}
  
  if(millis()>=TEMPO+velocita){bob1=0;bob2=0;bob3=1;bob4=1;}
  
  if(millis()>=TEMPO+velocita){bob1=0;bob2=0;bob3=0;bob4=1;}
  
  if(millis()>=TEMPO+velocita){bob1=1;bob2=0;bob3=0;bob4=1;}
  }        

}



In pratica "partenza e rotazione" li legge correttamente,
credo che il problema stia nel "TEMPO=millis()", oppure nella Variabile "velocita".

Ovunque sposto "TEMPO=millis()" mi legge solo la riga sopra poi si blocca ho provato pure ad a mettere 2000 millisecondi al posto di"velocita", ma niente da fare.

Non so più cosa provare per saltarci fuori....mi sono arenato nuovamente sto "millis()" e utilissimo,ma mi fà dannare.
che senso ha reinventare la ruota?  se devi muovere uno stepper devi avere il motore e e devi avere il driver che ti costa 30 volte meno che fartelo da solo
ci sono talmente tanti "parametri" che mette in atto un driver che quello che stai cercando di fare tu e solo una piccola parte,
con un driver stepper   solo con i comandi dir & step fai già girare il motore

 :smiley-confuse: e mi pare che non ci sono stepper pilotabili direttamente dalle uscite di arduino
per ultimo scrivere software senza ardware collegato è una gran vaccata (il 99.9% delle volte)

Puso

#16
Aug 25, 2017, 08:27 pm Last Edit: Aug 25, 2017, 08:33 pm by Puso
OK OK

intanto scusate il ritardo nelle risposte,ma questa settimana è stata impegnativa nella vita personale e non ho avuto tempo per la parte hobbistica.

Appena riesco ci riprovo ( ho capito la scrittura da ominide....sto comprendendo le variabili e ringrazio per i consigli che appena riesco  provo a tentare di risolvere).


PS

Reinventare la ruota......ha senso......almeno per capire il perchè gira.
il mio problema non è far girare un motore passo passo...il mio problema è farlo senza librerie o schede elettroniche gia fatte.......voglio solo comprendere( in questo caso, la programmazione).

Puso

Leggendo i vostri consigli ho capito che mi state insegnando e ne faccio tesoro.......ammetto che caratterialmente a volte faccio come i bambini......finche non cado e mi sbuccio un ginocchio, non mi rendo conto di quato faccia male.

Puso

#18
Aug 27, 2017, 02:11 pm Last Edit: Aug 27, 2017, 02:27 pm by Puso
 ;D  ;D  ;D
Ok
ci sono riuscito sia su seriale sia con i led al posto delle bobine,
sia attaccandoci un passo passo direttamente su arduino(anche se non come vorrei,ma credo che il problema sia che non do il negativo alle bobine) infatti va lentissimo anche se abbasso il tempo od inverto le bobine....appena riesco ci metto in mezzo un L293D, teoricamente dopo dovrebbe funzionare bene.

Comunque credo di aver capito il mio errore con millis(). praticamente mi servono 2 variabili.

A meno che non me lo chiedete per autolesionismo,,,,,evito di postare lo schetc che ho fatto,,,,,se no mi sgridate.

Comunque funziona.

Prossimo passo comprendere le variabili e le funzioni void cavallo()

e provare a riscrivere lo schetch usandole.

Puso

#19
Aug 28, 2017, 07:46 pm Last Edit: Aug 28, 2017, 08:01 pm by Puso
cavallo per dare un nome a caso

intendo quelle tipo "void mostra" e "void avanti"e che hai richiamato dopo nel loop.

ma un passo alla volta.

prima voglio fare altre cose utilizzando il millis()......per ora era questo il mio problema.....nella speranza di averlo capito come si deve ora lo devo provare e riprovare e spremerlo finche non mi diventa automatico........come fare uno starnuto.

Puso

Salve a tutti
Premesso che il mio schetc che metto giusto per farvi inorridire dalla mia scrittura
funziona correttamente sia in teoria che in pratica il motore parte da fermo se schiaccio il pulsante la prima volta gira in un senso,la seconda volta gira nell'altro, la terza si fema e mantiene la posizione (il conteggiopassi lo avevo messo per saper in che posizione si trova il motore.....anche se adesso non serve
Code: [Select]

byte pulsante=2;
int bobina1=8;
int bobina2=9;
byte bobina3=10;
byte bobina4=11;

byte bob1=0;
byte bob2=0;
byte bob3=0;
byte bob4=0;

int conteggiopassi=0;
int girocompleto=512;
int ciclo=0;
int rotazione=0;
int partenza=0;
unsigned velocita=50;
unsigned tempo=0;

void setup()
{
//Assegno i pin
pinMode(pulsante,INPUT); 
pinMode(bobina1,OUTPUT);
pinMode(bobina2,OUTPUT);
pinMode(bobina3,OUTPUT);
pinMode(bobina4,OUTPUT);
Serial.begin(9600);
}

void loop()
{
 //Letture serial monitor
 Serial.print("Ciclo  ");
 Serial.println(ciclo);
 Serial.println("");
 Serial.print(bob1);
 Serial.print(bob2);
 Serial.print(bob3);
 Serial.print(bob4);
 Serial.println("");
 
 
 if(ciclo==0){Serial.println("Motore Fermo");}
 Serial.println("");
 if(digitalRead(pulsante)){Serial.println("Motore Pronto");}
 Serial.println("");
 if(ciclo!=0)
   {
    if(partenza==1){Serial.println("Partenza");}
    if(rotazione==0){Serial.println("Senso Orario");}
    if(rotazione==1){Serial.println("Senso Antiorario");}
    Serial.print("Passi  ");
    Serial.println(conteggiopassi);
   }
 
 //Comandi bobine
 if(bob1==1){digitalWrite(bobina1,HIGH);}else{digitalWrite(bobina1,LOW);}
 if(bob2==1){digitalWrite(bobina2,HIGH);}else{digitalWrite(bobina2,LOW);}
 if(bob3==1){digitalWrite(bobina3,HIGH);}else{digitalWrite(bobina3,LOW);}
 if(bob4==1){digitalWrite(bobina4,HIGH);}else{digitalWrite(bobina4,LOW);}

 //Condizione pulsante
 if((digitalRead(pulsante))&&(rotazione==0))//Dice Avanti
   {
    while(digitalRead(pulsante)){}
    rotazione=1;
   }
 
  if((digitalRead(pulsante))&&(rotazione==1))//Dice Indietro
   {
    while(digitalRead(pulsante)){}
    rotazione=2;
   }
 
  if((digitalRead(pulsante))&&(rotazione==2))//Dice Stop
   {
    while(digitalRead(pulsante)){}
    rotazione=0;
   }
   
 //Senso di rotazione
 
 if(rotazione==1)// Esegue Avanti
   {
    if(millis()>=tempo+velocita)
      {
       conteggiopassi++;
       ciclo++;
       tempo=millis();
      }
     if(ciclo>8){ciclo=1;}
   }
 
  if(rotazione==2)//Esegue Indietro
    {
     if(millis()>=tempo+velocita)
       {
        conteggiopassi--;
        ciclo--;
        tempo=millis();
       }
     if(ciclo<1){ciclo=8;}
    } 
  else //Esegue Stop
    {
     digitalRead(ciclo);
     digitalRead(conteggiopassi);
     ciclo=ciclo;
    }
     
 
 //Sequenza fasi
 if(ciclo==0){bob1=0;bob2=0;bob3=0;bob4=0;}
 if(ciclo==1){bob1=1;bob2=0;bob3=0;bob4=0;}
 if(ciclo==2){bob1=1;bob2=1;bob3=0;bob4=0;}
 if(ciclo==3){bob1=0;bob2=1;bob3=0;bob4=0;}
 if(ciclo==4){bob1=0;bob2=1;bob3=1;bob4=0;}
 if(ciclo==5){bob1=0;bob2=0;bob3=1;bob4=0;}
 if(ciclo==6){bob1=0;bob2=0;bob3=1;bob4=1;}
 if(ciclo==7){bob1=0;bob2=0;bob3=0;bob4=1;}
 if(ciclo==8){bob1=1;bob2=0;bob3=0;bob4=1;}
}


Ho provato a mettere fuori dal LOOP giusto per renderlo piu semplice alcuni argomenti,come ad esempio "sequenza fasi"oppure"letture serial monitor",,,,,,ma non mi è ben chiaro il concetto di come richiamarle nel LOOP.

giovepluvio

Le funzioni "inventate" si dichiarano esattamente come le altre. Ad un certo punto della loop(), o della setup(), o di un'altra funzione (si, una funzione può richiamare un'altra funzione, e il ciclo può avere lunghezze paurose, basta che sia finito, ovvero che una funzione chiamata da una chiamata da una chiamata... dia un risultato che possa far funzionare la funzione precedente e via così)
Una funzione la puoi richiamare tutte le volte che vuoi e puoi buttare via o meno il valore di ritorno. In pratica una funzione tua é uguale ad una funzione esistente. Chiaro?

Claudio_FF

#22
Sep 10, 2017, 08:54 pm Last Edit: Sep 10, 2017, 08:56 pm by Claudio_FF
Quote from: Puso
funziona correttamente sia in teoria che in pratica
Fino a 50 giorni, poi millis() torna a zero.

Il controllo millis()>x+y può fallire in diversi modi, in un caso (se x+y<2^32-1 e millis è tornato a zero) il programma potrebbe bloccarsi per sempre (tocca aspettare altri 50 giorni per scoprirlo), nell'altro (se millis()<2^32-1 e x+1>=2^32) invece non attende il tempo previsto (finché sia millis() che x+y non hanno superato lo zero, poi torna a funzionare regolarmente).

Se ne era già parlato qui.

La soluzione era già stata detta il primo Agosto, qualche post prima.
********* IF e SWITCH non sono cicli ! *********
**** Una domanda ben posta è già mezza risposta ****
*** La corrente si misura in mA, la quantità di carica in mAh ***

Puso

Per le funzioni inventate ancora non le ho chiare di mio ci devo ancora studiare, ci ho provato un pò poi ho fatto un gran casino è mi è venuto il nervoso, credo di aver capito come dichiararle ma non come richiamarle.

Per la fine del millis() dopo i 50 giorni me lo ricordavo ed un pò me lo sono studiato ma non ci avevo dato peso nello schetc perche non mi serviva ti ringrazio comunque per la correzione è giusto farlo diventare un'abitudine.


Giuro che la prossima volta che mi trovo un hobby.....faccio il pensionato che va ha guardare i lavoratori in cantiere

gpb01

Per le funzioni inventate ancora non le ho chiare di mio ci devo ancora studiare, ci ho provato un pò poi ho fatto un gran casino è mi è venuto il nervoso, credo di aver capito come dichiararle ma non come richiamarle.
Guarda, è veramente banale ...
... facciamo un caso semplice semplice ... prima di loop() e di setup(), crei una tua funzione :

Code: [Select]
void miaFunzione(void) {
   Serial.print("Messaggio dalla mia funzione");
}

... dentro il tuo programma, DOVE VUOI, quando la vuoi richiamare basta che scrivi : miaFunzione();

Esempio

Code: [Select]
void setup() {
   Serial.begin(9600);
   miaFunzione();
}

... qui è stata chiamata nel setup() (quindi una sola volta). Se ti serve di chiamarla da altre parti, basta che ripeti quella riga. :D

Guglielmo
Search is Your friend ... or I am Your enemy !

Puso

#25
Sep 11, 2017, 07:46 pm Last Edit: Sep 11, 2017, 07:54 pm by Puso
Grazie ancora.....mo ci riprovo

appena riesco lo posto cosi potete autoflagellarvi leggendo i miei tentativi

Puso

 :smiley-grin:
Ecco fatto che ve ne pare?

Qui ho messo le variabili che dorebbero essere quelle più adatte, ed il setup
Code: [Select]
//VARIABILI PER RICORDARE I PIN
byte pulsante=2;
byte bobina1=8;
byte bobina2=9;
byte bobina3=10;
byte bobina4=11;

//VARIABILI PER COMANDARE I PIN
byte bob1=0;
byte bob2=0;
byte bob3=0;
byte bob4=0;

//VARIABILI PER RICORDARE LA POSIZIONE
int conteggiopassi=0;
int girocompleto=512;

//VARIABILI PER I COMANDI
int ciclo=0;
int rotazione=0;
int partenza=0;

//VARIABILI PER GESTIRE IL MILLIS()
unsigned velocita=50;
unsigned tempo=0;
extern unsigned long timer0_millis;

void setup()
{
 //ASSEGNO TIPO DI PIN
 pinMode(pulsante,INPUT); 
 pinMode(bobina1,OUTPUT);
 pinMode(bobina2,OUTPUT);
 pinMode(bobina3,OUTPUT);
 pinMode(bobina4,OUTPUT);
 
 //ASSEGNO VELOCITA SERIAL MONITOR
 Serial.begin(9600);
}


Subito dopo ho "inventato" le funzioni cosi da vedere meglio se c'erano errori, compresa quella per resettare il millis.
Code: [Select]
//INVENTO FUNZIONE DA RICHIAMARE NEL LOOP()
void  LEGGI_MONITOR()
{
 Serial.print("MILLIS ");
 Serial.println(millis());
 
 Serial.print("TEMPO ");
 Serial.println(tempo);
 
 Serial.print("CICLO  ");
 Serial.println(ciclo);
 Serial.print(bob1);
 Serial.print(bob2);
 Serial.print(bob3);
 Serial.print(bob4);
 Serial.println("");
 
 if(rotazione==0)
   {
    Serial.println("");
    Serial.println("FERMO");
   }
 if(rotazione==1)
   {
    Serial.println("");
    Serial.println("AVANTI");
   }
 if(rotazione==2)
   {
    Serial.println("");
    Serial.println("INDIETRO");
   }
 Serial.print("PASSI  ");
 Serial.println(conteggiopassi);
}


//INVENTO FUNZIONE DA RICHIAMARE NEL LOOP()
void LEGGI_PULSANTE()
{   
 if((digitalRead(pulsante))&&(rotazione==0))//Dice Avanti
   {
    while(digitalRead(pulsante)){}
    rotazione=1;
   }
 
  if((digitalRead(pulsante))&&(rotazione==1))//Dice Indietro
   {
    while(digitalRead(pulsante)){}
    rotazione=2;
   }
 
  if((digitalRead(pulsante))&&(rotazione==2))//Dice Stop
   {
    while(digitalRead(pulsante)){}
    rotazione=0;
   }
}

//INVENTO FUNZIONE DA RICHIAMARE NEL LOOP()
void DECIDI_ROTAZIONE()
{
 //COMANDA AVANTI
 if(rotazione==1)
   {
    if(millis()>=tempo+velocita)
      {
       conteggiopassi++;
       ciclo++;
       tempo=millis();
      }
    if(ciclo>8){ciclo=1;}
   }
 
 //COMANDA INDIETRO
 if(rotazione==2)
   {
    if(millis()>=tempo+velocita)
      {
       conteggiopassi--;
       ciclo--;
       tempo=millis();
      }
    if(ciclo<1){ciclo=8;}
   }
 
 //COMANDA STOP
 //MANTIENE LA POSIZIONE
 //RICORDA LA POSIZIONE
 else
    {
     digitalRead(ciclo);
     digitalRead(conteggiopassi);
     ciclo=ciclo;
    }
}     

//INVENTO FUNZIONE DA RICHIAMARE NEL LOOP()
void ISTRUISCI_BOBINE()
{
 if(ciclo==0){bob1=0;bob2=0;bob3=0;bob4=0;}
 if(ciclo==1){bob1=1;bob2=0;bob3=0;bob4=0;}
 if(ciclo==2){bob1=1;bob2=1;bob3=0;bob4=0;}
 if(ciclo==3){bob1=0;bob2=1;bob3=0;bob4=0;}
 if(ciclo==4){bob1=0;bob2=1;bob3=1;bob4=0;}
 if(ciclo==5){bob1=0;bob2=0;bob3=1;bob4=0;}
 if(ciclo==6){bob1=0;bob2=0;bob3=1;bob4=1;}
 if(ciclo==7){bob1=0;bob2=0;bob3=0;bob4=1;}
 if(ciclo==8){bob1=1;bob2=0;bob3=0;bob4=1;}
}

//INVENTO FUNZIONE DA RICHIAMARE NEL LOOP()
void COMANDA_BOBINE()
{
 if(bob1==1){digitalWrite(bobina1,HIGH);}else{digitalWrite(bobina1,LOW);}
 if(bob2==1){digitalWrite(bobina2,HIGH);}else{digitalWrite(bobina2,LOW);}
 if(bob3==1){digitalWrite(bobina3,HIGH);}else{digitalWrite(bobina3,LOW);}
 if(bob4==1){digitalWrite(bobina4,HIGH);}else{digitalWrite(bobina4,LOW);}
}

//INVENTO FUNZIONE DA RICHIAMARE NEL LOOP()
void RESETTA_MILLIS()
{
  timer0_millis=0;
  tempo=millis();
}



Infine lancio il LOOP veramente cortissimo.
Code: [Select]
//SCRIVO IL LOOP()
void loop()
{
 LEGGI_MONITOR();
 LEGGI_PULSANTE();
 DECIDI_ROTAZIONE();
 ISTRUISCI_BOBINE();
 COMANDA_BOBINE();
 RESETTA_MILLIS();
}


Sembra funzionare tutto correttamente,che dite sono sulla strada giusta????????

Puso

#27
Sep 16, 2017, 11:45 am Last Edit: Sep 16, 2017, 11:52 am by Puso
le rotazioni le ho messe appositamente fuori dalle graffe,per evitare di dover mettere un delay in attesa di levare il dito dal pulsante, ho voluto dire apposta

finche lo senti premuto non fare nulla,,poi rotazione= ect

Claudio_FF

#28
Sep 16, 2017, 01:08 pm Last Edit: Sep 16, 2017, 01:21 pm by Claudio_FF
La dichiarazione di queste due variabili mi sembra un po' strana
Quote from: Puso
Code: [Select]
unsigned velocita=50;
unsigned tempo=0;

Questa parte cosa fa?
Quote
Code: [Select]

 //COMANDA STOP
 //MANTIENE LA POSIZIONE
 //RICORDA LA POSIZIONE
 else
    {
     digitalRead(ciclo);
     digitalRead(conteggiopassi);
     ciclo=ciclo;
    }
}    

Quote
Sembra funzionare tutto correttamente,che dite sono sulla strada giusta????????
Vediamo... se fossi il committente del lavoro guarderei con soddisfazione il motore che gira, ma a questo punto chiederei una piccola e davvero insignificante modifica, vorrei vedere anche il led on board (pin 13) che lampeggia costante a 1 Hz, per avere l'indicazione visiva del sistema in funzione anche a motore fermo. Si può fare vero?

Quote
Per la fine del millis() dopo i 50 giorni me lo ricordavo ed un pò me lo sono studiato ma non ci avevo dato peso nello schetc perche non mi serviva ti ringrazio comunque per la correzione è giusto farlo diventare un'abitudine.
Ma perseverare nell' "errore"... :smiley-twist:

Perché continuare a scrivere:
Code: [Select]
if(millis() >= tempo + velocita)
che richiede alchimie come l'azzeramento del contatore millis e impedisce di usare millis per qualsiasi altra operazione?

Quando basta scrivere come detto qui?
Code: [Select]
if(millis() - tempo >= velocita)
********* IF e SWITCH non sono cicli ! *********
**** Una domanda ben posta è già mezza risposta ****
*** La corrente si misura in mA, la quantità di carica in mAh ***

Puso

Questa parte l'ho utilizzata per dare più o meno velocità al motore
Code: [Select]
unsigned velocita=50;
unsigned tempo=0;


Qui invece ho voluto il motore fermo in una posizione qualsiasi con le bobine attive in modo che l'albero mantenga quella posizione e non sia libero di girare per inerzia, in più ho voluto ricordare in quale posizione "PASSO" si trova per poterlo sfruttare come un encoder
Code: [Select]
//COMANDA STOP
 //MANTIENE LA POSIZIONE
 //RICORDA LA POSIZIONE
 else
    {
     digitalRead(ciclo);
     digitalRead(conteggiopassi);
     ciclo=ciclo;
    }
}     


Effettivamente mi sono scervellato un po col millis, comunque adesso provo ad aggiungere il led 13 che lampeggia per ogni secondo anzi 2 volte al secondo(2Hz) cosi provo di capire la differenza con if(millis() - tempo >= velocita)

Go Up