Go Down

Topic: Arduino-Tiny Attiny85 Funzione mills (Read 3072 times) previous topic - next topic

waterseven

Salve ragazzi , ho flashato su attiny uno sketch e ora devo fare il reset dopo 2 secondi dalla non ricezione HIGH di un ingresso. Su arduino si usa mills ma provando qui non funziona...
Ho cambiato i fuse ed uso attiny85 a 8mhz il delay(1000) conta un secondo , ma se ad esempio io metto timer=mills(); if mills == 4000  digitalwrite ec ecc non funziona , dove sbaglio o nel caso come posso fare ilr eset se non ricevo dopo tot tempo su attiny?

nid69ita

#1
Jul 02, 2013, 08:24 am Last Edit: Jul 02, 2013, 08:26 am by nid69ita Reason: 1

... io metto timer=mills(); if mills == 4000  digitalwrite ec ecc non funziona , dove sbaglio o nel caso come posso fare il reset se non ricevo dopo tot tempo su attiny?


Forse è meglio se posti il codice completo, da quel poco che scrivi mi sembra errato. Manca qualcosa nel confronto e difficilmente la differenza tra millis() precedente e l'attuale può dare una cifra esatta come 4000.
Code: [Select]
tempo=0;  nel setup
...
if ( millis()-tempo > 4000 )  
{ tempo=millis();
  // qui codice per quando scatta il tempo
}

O ancora meglio (più completo) guarda l'esempio "blink without delay"
http://arduino.cc/en/Tutorial/BlinkWithoutDelay
my name is IGOR, not AIGOR

leo72

millis() (non mills) funziona perfettamente sui Tiny.
Usa il core Tiny preso da qui:
http://code.google.com/p/arduino-tiny/downloads/list

Il reset come intendi farlo? Spero non collegando un pin digitale direttamente al pin di reset e mettendolo low. Non funziona. Devi usare il watchdog.

waterseven



... io metto timer=mills(); if mills == 4000  digitalwrite ec ecc non funziona , dove sbaglio o nel caso come posso fare il reset se non ricevo dopo tot tempo su attiny?


Forse è meglio se posti il codice completo, da quel poco che scrivi mi sembra errato. Manca qualcosa nel confronto e difficilmente la differenza tra millis() precedente e l'attuale può dare una cifra esatta come 4000.
Code: [Select]
tempo=0;  nel setup
...
if ( millis()-tempo > 4000 )  
{ tempo=millis();
  // qui codice per quando scatta il tempo
}

O ancora meglio (più completo) guarda l'esempio "blink without delay"
http://arduino.cc/en/Tutorial/BlinkWithoutDelay



Grazie funziona, errore mio allora nella sintassi della funzione.

waterseven

Questo è il codice che ho fatto, in pratica si preme il pulsante la prima volta
  •   e la i diventa 1 , si preme una seconda volta per piu' di 2 secondi e la i diventa 2 , quando la i è due il cancello si apre. Solo che non mi funziona dove sbaglio ?

    Code: [Select]

    const int  buttonPin = 4;
    const int cancello = 3;       

    // Variables will change:
    int i=0;
    int buttonState = 0;         
    int lastButtonState = 0;   
    double time;

    void setup() {
      pinMode(buttonPin, INPUT);
      pinMode(cancello, OUTPUT);
    }


    void loop() {
      buttonState = digitalRead(buttonPin);

      if (buttonState != lastButtonState) {

         if (buttonState == HIGH) {
            if(i==0){
               i++;
            }
            else{
               reg();
            }
         }
       
         check();
      }

      lastButtonState = buttonState;

    }

    void reg(){
      time= millis();   
      if ((buttonState == HIGH)&&(millis()-time > 2000 ))  {
       i++;
      }
    }

    void check(){
      if(i == 2){
        digitalWrite(cancello, HIGH);
      }

    }

leo72

Sbagli nel fatto che dentro alla funzione reg() devi continuare a leggere lo stato e solo quando l'utente lo ha premuto per più di 2 secondi, agire di conseguenza.
Tu invece entri in reg() e controlli se la pressione è durata più di 2 secondi ma la pressione non è durata più di 2 secondi perché dal loop, non appena hai premuto il pulsante, vai a verificare i tempi.

waterseven

Rimodificata cosi ma non funziona...
Code: [Select]


void reg(){
  time= millis();   
    buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) {
  if ( (buttonState == HIGH)&&(millis()-time > 2000 ))  {
   i++;
  }
  }
}


leo72

Ti do una dritta. Usa un while da cui esci solo per timeout (quindi pressione maggiore di 2 secondi) oppure per rilascio pulsante.
Dopo la while controlli se sei uscito per timeout (quindi l'utente ha premuto il pulsante per più di 2 secondi) oppure per rilascio del pulsante, in questo caso sicuramente prima dei 2 secondi ed ignori la cosa.
Altra dritta, usa una variabile aggiuntiva da impostare prima del while, modificare dentro al while e controllare dopo il while.

Di più non posso, il programma sennò te lo scrivo io  ;)

waterseven

Ho modificato un po del tutto il codice aggiungendo anche i tempi (Avevo fatto un sketch per il clapper e l ho riadattato) per avere ulteriori precauzioni "antiladro"  :D , Il mio intento è di fare una combinazione ("per ora di 3") quando nel caso non ho le chiavi suonando il citofono si apre da solo. La combo ora è , primo push , secondo push lungo 2 secondi , terzo push.
Ora ho 2 problemi:
1) Posso resettare la funzione di millis facendo ripartire da 0 nuovamente con il reset (è possibile il reset dell' attiny85 da software) ?
2) Non riesco a capire come posso implementare il push del secondo bottone per 2 secondi qui:
Code: [Select]

if ( combo[1]==0 ) {
   combo[1] = time;
   return;
 }



Questo è il codice completo:
Code: [Select]

const int pinButton = 4; // Pin bottone
const int pinGate = 3; // Pin 3 Cancello
int lastState=0;
double combo[3]; // Combinazione di 3 push
double lastPush; // Ultimo push


void setup()
{
 pinMode(pinGate, OUTPUT); // Dichiaro pinGate come OUTPUT
 pinMode(pinButton, INPUT); // Dichiaro pinGate come INPUT
}




void loop()
{
       
 // Leggo stato bottone citofono
 int buttonCit = digitalRead(pinButton);    

 // Se il bottone è in stato diverso dal precedente
 if (buttonCit != lastState)
 {
   //Controllo se è in stato alto
    if (buttonCit == HIGH ){
   Reg(); // Registro in combo il momento in cui viene avvertito il push
   Check(); // Controllo se la sequenza e' completa*/
   delay(400);  // Aspetto per non sovraccaricare il buffer
   }
 }

 // Sequenza cominciata ma oltre 4 secondi di silenzio: resetto
 if ( combo[0] && millis()-lastPush > 4000 ) {
   reset();
 }
 
}


// Registro il momento in cui viene premuto il bottone
void Reg()
{
 double time = millis();
 lastPush = millis();
 
 if ( combo[0]==0 ) {
 combo[0] = time;
 return;
 }
 
 if ( combo[1]==0 ) {  //QUI DEVO AGGIUNGERE IL CODICE DEL PUSH PER 2 SECONDI SE VERO FAI IL RETURN ALTRIMENTI RESET
   combo[1] = time;
   return;
 }
 
 if ( combo[2]==0 ) {
 combo[2] = time;
 return;
}

}


void Check()
{
 // Se c'e' il numero corretto di push registrati
 if ( combo[2] > 0 )
 {  
   // Verifica il "ritmo" della sequenza di battiTO
   if ( combo[1]-combo[0] >= 500 && combo[1]-combo[0] <= 1000 ) // 250{
   if ( combo[2]-combo[1] >= 500 && combo[2]-combo[1] <= 1000 ) // 250
     success();

   // Resetto la combo ogni volta che ha completato la sequenza
   reset();
 }
}



//Resetto tutto
void reset()
{
 for ( int n=0; n<=2; n++ ) { combo[n] = 0; }
 digitalWrite(pinGate,LOW);
 
}


void success()
{
       digitalWrite(pinGate,HIGH);
       delay(1000);
       reset();
}

leo72


Ora ho 2 problemi:
1) Posso resettare la funzione di millis facendo ripartire da 0 nuovamente con il reset (è possibile il reset dell' attiny85 da software) ?

Se resetti il micro, millis riparte da zero. Per resettare il micro puoi usare il watchdog.
Ma perché vuoi resettare il micro? Per far ripartire il programma dall'inizio? Allora il reset è l'ULTIMA delle tue necessità. Io vedo nel tuo caso l'uso del reset come un GOTO, vuoi cioè uscire da un blocco di codice saltando l'esecuzione del resto. Ma allora if..else, do..while a cosa li hanno inventati a fare?  ;)

Quote

2) Non riesco a capire come posso implementare il push del secondo bottone per 2 secondi qui:

Te l'ho spiegato nel post precedente come implementare un controllo per verificare se una pressione avviene per più o meno di un certo tempo (il codice non te lo scrivo, altrimenti non serve a nulla. Sei tu che devi imparare, non io  ;) ).

waterseven

No io voglio resettare solo il millis non riavviare completamente il pic , watchdog non so proprio dover metter mani haha , domani vedo un po online qualche guida ! :smiley-mr-green: :smiley-mr-green:

In poche parole devo perdere una giornata per capire come funziona il push per 2 secondi ho capito hahahahaha :D

leo72

Non serve neanche resettare millis, se fai il programma come si deve.  ;)
Ti passo un link per studiare un pò millis:
http://www.leonardomiliani.com/2013/programmiamo-i-compiti-con-millis/

PaoloP


No io voglio resettare solo il millis non riavviare completamente il pic


AVR!!
:smiley-mr-green: :smiley-mr-green: :smiley-mr-green: :smiley-mr-green:

leo72


waterseven

#14
Jul 04, 2013, 12:20 am Last Edit: Jul 04, 2013, 12:32 am by waterseven Reason: 1
Fatto , ora funziona era una cagata farlo .... Mi ero inceppato con la logica ... Troppe cose per la testa  :D

Ecco il codice completo:
Code: [Select]

const int pinButton = 4; // Pin bottone
const int pinGate = 3; // Pin 3 Cancello
int lastState=0;
double combo[3]; // Combinazione di 3 push
double lastPush; // Ultimo push
long duration;

void setup()
{
 pinMode(pinGate, OUTPUT); // Dichiaro pinGate come OUTPUT
 pinMode(pinButton, INPUT); // Dichiaro pinGate come INPUT
}




void loop()
{
       
 // Leggo stato bottone citofono
 int buttonCit = digitalRead(pinButton);    

 // Se il bottone è in stato diverso dal precedente
 if (buttonCit != lastState)
 {
   //Controllo se è in stato alto
    if (buttonCit == HIGH ){
   Reg(); // Registro in combo il momento in cui viene avvertito il push
   Check(); // Controllo se la sequenza e' completa*/
   delay(400);  // Aspetto per non sovraccaricare il buffer
   }
 }

 // Sequenza cominciata ma oltre 4 secondi di silenzio: resetto
 if ( combo[0] && millis()-lastPush > 4000 ) {
   reset();
 }
 
}


// Registro il momento in cui viene premuto il bottone
void Reg()
{
 double time = millis();
 lastPush = millis();
 
 if ( combo[0]==0 ) {
 combo[0] = time;
 return;
 }
 
 if ( combo[1]==0 ) {  //QUI DEVO AGGIUNGERE IL CODICE DEL PUSH PER 2 SECONDI SE VERO FAI IL RETURN ALTRIMENTI RESET
   combo[1] = time;
  while(digitalRead(pinButton) == HIGH){ // wait while the switch is still pressed
      duration = millis() - combo[1] ;
    }
    if(duration > 1000){
   return;
   }
   else{
     reset();
   }
 }
 
 if ( combo[2]==0 ) {
 combo[2] = time;
 return;
}

}


void Check()
{
 // Se c'e' il numero corretto di push registrati
 if ( combo[2] > 0 )
 {  
   // Verifica il "ritmo" della sequenza di battiTO
   if ( combo[1]-combo[0] >= 500 && combo[1]-combo[0] <= 2000 ) // 250{
   if ( combo[2]-combo[1] >= 500 && combo[2]-combo[1] <= 5000 ) // 250
     success();

   // Resetto la combo ogni volta che ha completato la sequenza
   reset();
 }
}



//Resetto tutto
void reset()
{
 for ( int n=0; n<=2; n++ ) { combo[n] = 0; }
 digitalWrite(pinGate,LOW);
 
}


void success()
{
       digitalWrite(pinGate,HIGH);
       delay(1000);
       reset();
}



Grazie a tutti !!!
leo72   ;)  Non voglio la pappa pronta !  :D

Go Up