Go Down

Topic: Misurare pressione bottone (Read 1 time) previous topic - next topic

wild91

Allora prima di tutto vi metto il circuito fatto con fritzing:
https://www.dropbox.com/s/ebc5xxgxaaep5lw/Schema_fritz.jpg
adesso vi spiego il mio "problema".
Quello che voglio provare a fare è accendere i led in sequenza a distanza di un secondo l'uno dall'altro,se e solo se il bottone rimane premuto.
Con questo codice:
Code: [Select]
const int v = 2;
const int r1=3;
const int r2 = 4;
const int r3=5;
const int g = 6;
const int bottone = 12;
int statoBottone;
void setup(){
  pinMode(v,OUTPUT);
  pinMode(r1,OUTPUT);
  pinMode(r2,OUTPUT);
  pinMode(r3,OUTPUT);
  pinMode(g,OUTPUT);
  pinMode(bottone,INPUT);
}
void loop(){
  statoBottone=digitalRead(bottone);
  if(statoBottone==HIGH){
    delay(1000);
    digitalWrite(v,HIGH);
    delay(1000);
    digitalWrite(r1,HIGH);
    delay(1000);
    digitalWrite(r2,HIGH);
    delay(1000);
    digitalWrite(r3,HIGH);
    delay(1000);
    digitalWrite(g,HIGH);
  }
  if(statoBottone==LOW){
    for(int i=2;i<=6;i++) digitalWrite(i,LOW);
  }
}

Più o meno ottengo quello che voglio,però ovviamente quando smetto di schiacciare il bottone non è detto che i Led si spengano subito..
Qui http://arduino.cc/playground/Code/HoldButton e qui http://arduino.cc/playground/Code/AvoidDelay ho letto un po' sulla funzione millis() che forse è quella che mi serve,ma non riesco ad utilizzarla,ho provato così,ma non funziona:
Code: [Select]

const int v = 2;
const int r1=3;
const int r2 = 4;
const int r3=5;
const int g = 6;
const int bottone = 12;
unsigned long int timer;
int statoBottone;
void setup(){
  pinMode(v,OUTPUT);
  pinMode(r1,OUTPUT);
  pinMode(r2,OUTPUT);
  pinMode(r3,OUTPUT);
  pinMode(g,OUTPUT);
  pinMode(bottone,INPUT);
}
void loop(){
  statoBottone=digitalRead(bottone);
  if(statoBottone==HIGH){
    timer = millis();
    if(millis()-timer >=1000) digitalWrite(v,HIGH);
    if(millis()-timer >=2000) digitalWrite(r1,HIGH);
    if(millis()-timer >=3000) digitalWrite(r2,HIGH);
    if(millis()-timer >=4000) digitalWrite(r3,HIGH);
    if(millis()-timer >=5000) digitalWrite(g,HIGH);
  }
  if(statoBottone==LOW){
    for(int i=2;i<=6;i++) digitalWrite(i,LOW);
  }
}

Ho provato in questo modo perchè se ho ben capito millis() restituisce i millisecondi passati dal momento in cui si avvia il microprocessore della scheda arduino,quindi se a timer assegno i millisecondi che sono passati quando premo il bottone millis()-timer dovrebbe essere il tempo in cui il bottone rimane schiacciato.
Sicuramente è sbagliato perchè non funziona:)
Grazie in anticipo per l'aiuto e chiedo scusa per il messaggio un po' lungo..

lucadentella

Ciao

devi cambiare un po' l'approccio:

1) parti dalla condizione bottone non premuto, il loop() continuerà ad essere eseguito senza far nulla;
2) non appena rilevi che il bottone è premuto, salvati in una variabile il valore in quel momento di millis(), in questo modo sai quando il bottone ha iniziato ad essere premuto, nel caso accendi anche un led (se uno va acceso subito). Salvati anche in una variabile che hai rilevato il bottone premuto
3) se ora sei nella condizione "ho rilevato il bottone premuto" e il bottone è ancora premuto, confronta il millis() attuale con quello salvato, se è maggiore di 1000 la differenza (= trascorso un secondo) accendi il led; se invece il bottone non è più premuto torna alla condizione iniziale
lucadentella.it

wild91

Ho seguito il tuo consiglio,ma ancora non riesco a capire una cosa;dato che non riesco ancora a farlo andare ho provato a stampare a video il valore di millis()-timer in questo modo(scrivo in pseudo-codice):
if(bottone_premuto)
      timer=millis;
      if(bottone ancora premuto) serial.println(millis-timer)
Quando eseguo il codice così però ottengo che millis-timer è sempre uguale a 0,non dovrebbe invece crescere misurando appunto la durata della pressione del pulsante?I am confused! :smiley-roll-sweat:
Grazie mille per l'aiuto e la pazienza comunque :)

Michele Menniti


Ho seguito il tuo consiglio,ma ancora non riesco a capire una cosa;dato che non riesco ancora a farlo andare ho provato a stampare a video il valore di millis()-timer in questo modo(scrivo in pseudo-codice):
if(bottone_premuto)
      timer=millis;
      if(bottone ancora premuto) serial.println(millis-timer)
Quando eseguo il codice così però ottengo che millis-timer è sempre uguale a 0,non dovrebbe invece crescere misurando appunto la durata della pressione del pulsante?I am confused! :smiley-roll-sweat:
Grazie mille per l'aiuto e la pazienza comunque :)

intanto dopo millis devi sempre mettere ()temo che il processore vada un po' più veloce della funzione millis :) Se imposti timer=millis e all'istruzione successiva vuoi leggere millis-timer per me è naturale aspettarmi 0; per capirci prova a mettere (anche se non ti serve) un delay (100) subito dopo la riga timer=millis; in questo caso dovresti ottenere un valore prossimo a 100.
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

PaoloP

Prova così:
Code: [Select]
const int v = 2;
const int r1=3;
const int r2 = 4;
const int r3=5;
const int g = 6;
const int bottone = 12;
unsigned long int timer;
int statoBottone;

void setup(){
  pinMode(v,OUTPUT);
  pinMode(r1,OUTPUT);
  pinMode(r2,OUTPUT);
  pinMode(r3,OUTPUT);
  pinMode(g,OUTPUT);
  pinMode(bottone,INPUT);
}

void loop(){
  statoBottone=digitalRead(bottone);
  if(statoBottone==HIGH){
  // quando è premuto il pulsante calcola la differenza tra timer e millis.
    if(millis()-timer >=1000) digitalWrite(v,HIGH);
    if(millis()-timer >=2000) digitalWrite(r1,HIGH);
    if(millis()-timer >=3000) digitalWrite(r2,HIGH);
    if(millis()-timer >=4000) digitalWrite(r3,HIGH);
    if(millis()-timer >=5000) digitalWrite(g,HIGH);
  }
  if(statoBottone==LOW){
  //quando non è premuto nessun pulsante memorizza timer
    timer = millis();
    for(int i=2;i<=6;i++) digitalWrite(i,LOW);
  }
}


Ho spostato solamente "timer = millis();" dalla condizione HIGH alla condizione LOW.

wild91

PaoloP ho provato il tuo codice e così funziona esattamente come volevo io:)Non mi è chiaro il motivo però XD :~

wild91

Ragionandoci un po' forse ci sono arrivato,correggimi se sbaglio.In pratica finchè il bottone è LOW timer e millis assumono lo stesso valore,poi una volta che il pulsante viene premuto millis continua a scorrere mentre timer rimane "bloccato" al valore di prima e quindi millis-timer misura correttamente quanto il pulsante rimane premuto..Comunque grazie a tutti per l'aiuto:)

PaoloP


Ragionandoci un po' forse ci sono arrivato,correggimi se sbaglio.In pratica finchè il bottone è LOW timer e millis assumono lo stesso valore,poi una volta che il pulsante viene premuto millis continua a scorrere mentre timer rimane "bloccato" al valore di prima e quindi millis-timer misura correttamente quanto il pulsante rimane premuto..Comunque grazie a tutti per l'aiuto:)

Esatto.  XD

wild91

Ottimo:) Adesso voglio spingermi anche più in là!:)
Con questo codice:
Code: [Select]

const int v = 2;
const int r1=3;
const int r2 = 4;
const int r3=5;
const int g = 6;
const int bottone = 12;
unsigned long int timer;
int statoBottone;

void setup(){
  pinMode(v,OUTPUT);
  pinMode(r1,OUTPUT);
  pinMode(r2,OUTPUT);
  pinMode(r3,OUTPUT);
  pinMode(g,OUTPUT);
  pinMode(bottone,INPUT);
}

void loop(){
  statoBottone=digitalRead(bottone);
  if(statoBottone==HIGH){
  // quando è premuto il pulsante calcola la differenza tra timer e millis.
    if(millis()-timer==1000) digitalWrite(v,HIGH);
    if(millis()-timer ==2000) digitalWrite(r1,HIGH);
    if(millis()-timer ==3000) digitalWrite(r2,HIGH);
    if(millis()-timer ==4000) digitalWrite(r3,HIGH);
    if(millis()-timer ==5000) digitalWrite(g,HIGH);
    if(millis()-timer ==6000) digitalWrite(g,LOW);
    if(millis()-timer ==7000) digitalWrite(r3,LOW);
    if(millis()-timer ==8000) digitalWrite(r2,LOW);
    if(millis()-timer ==9000) digitalWrite(r1,LOW);
    if(millis()-timer ==10000)digitalWrite(v,LOW);
  }
  if(statoBottone==LOW){
  //quando non è premuto nessun pulsante memorizza timer
    timer = millis();
    for(int i=2;i<=6;i++) digitalWrite(i,LOW);
  }
}

Ottengo un effetto a scala,nel senso che i led si accendono uno dopo l'altro e poi si spengono in ordine inverso(sempre e solo se tengo il bottone premuto).
Io vorrei provare a rendere la cosa ciclica,nel senso che una volta che si sono accesi e poi spenti tutti se io continuo a tenere premuto ricominciato ad accendersi,il problema è che avendo tenuto premuto il pulsante millis()-timer supera i 10 secondi.
Pensavo ad un if((millis()-timer)%1000==0) ma ovviamente non può andare bene..Ho pensato anche di provare ad usare goto,ma sembra anche peggio:)Aiutino:)?

PaoloP

Nooooooooooooooo i goto... noooooooooooo. Non li sopporto.  ]:D ]:D ]:D

Aggiungi questo dopo l'ultimo if
Code: [Select]
if(millis()-timer == 11000) timer = millis(); // Resetto la variabile timer e reinizio il ciclo dopo 11 secondi

wild91

Perfetto e più semplice non poteva essere:)Grazie mille:)Ecco il codice conclusivo comunque:
Code: [Select]

const int v = 2;
const int r1=3;
const int r2 = 4;
const int r3=5;
const int g = 6;
const int bottone = 12;
unsigned long int timer;
int statoBottone;

void setup(){
  pinMode(v,OUTPUT);
  pinMode(r1,OUTPUT);
  pinMode(r2,OUTPUT);
  pinMode(r3,OUTPUT);
  pinMode(g,OUTPUT);
  pinMode(bottone,INPUT);
}

void loop(){
  statoBottone=digitalRead(bottone);
  if(statoBottone==HIGH){
  // quando è premuto il pulsante calcola la differenza tra timer e millis.
    if(millis()-timer==1000) digitalWrite(v,HIGH);
    if(millis()-timer ==2000) digitalWrite(r1,HIGH);
    if(millis()-timer ==3000) digitalWrite(r2,HIGH);
    if(millis()-timer ==4000) digitalWrite(r3,HIGH);
    if(millis()-timer ==5000) digitalWrite(g,HIGH);
    if(millis()-timer ==6000) digitalWrite(g,LOW);
    if(millis()-timer ==7000) digitalWrite(r3,LOW);
    if(millis()-timer ==8000) digitalWrite(r2,LOW);
    if(millis()-timer ==9000) digitalWrite(r1,LOW);
    if(millis()-timer ==10000){digitalWrite(v,LOW);timer=millis();}
  }
  if(statoBottone==LOW){
  //quando non è premuto nessun pulsante memorizza timer
    timer = millis();
    for(int i=2;i<=6;i++) digitalWrite(i,LOW);
  }
}


leo72


Nooooooooooooooo i goto... noooooooooooo. Non li sopporto.  ]:D ]:D ]:D

Viva Edsger Dijkstra  :D

Go Up