Pages: [1]   Go Down
Author Topic: Aiuto su codice base pulsante-led  (Read 934 times)
0 Members and 1 Guest are viewing this topic.
Italy
Offline Offline
Newbie
*
Karma: 1
Posts: 6
Newbie Programmer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salve a tutti,
sono appena arrivato in questo forum e solo da qualche giorno sto utilizzando Arduino (con precisione Arduino Duemilanove). Seguendo vari tutorial online ho svolto vari esercizietti che mi hanno fatto capire alcune meccaniche di Arduino, subito interessanti.

Ecco però che sorge il primo problema: seguendo una guida sull'interazione di un pulsante con un led, dovevo far in modo di attivare il pulsante e fa andare in lampeggiamento il led e al secondo tocco del pulsante il led dovrebbe spegnersi. Il mio problema sorge nel secondo momento, lo spegnimento, che non avviene istantaneamente.

Posto il codice per capirci meglio:
Code:
// Il led lampeggia se premo il pulsante 
// premendo una seconda volta il pulsante si spegne il led 
 
#define LED 13                // LED collegato al pin digitale 13 
#define BUTTON 7              // pin di input dove è collegato il pulsante 
int val = 0;                  // val per conservare lo stato del pin di input 
int vecchio_val = 0;          // vecchio_val per conservare lo stato del pin di input al passo precedente 
int stato = 0;                // ricorda lo stato in cui si trova il led, stato = 0 led spento, stato = 1 led acceso 
 
void setup() { 
  pinMode(LED, OUTPUT);       // imposta il pin digitale come output 
  pinMode(BUTTON, INPUT);     // imposta il pin digitale come input 

 
void loop() { 
  val = digitalRead(BUTTON);  // legge il valore dell'input e lo conserva 
 
  // controlla se è accaduto qualcosa 
  if ((val == HIGH) && (vecchio_val == LOW)){ 
    stato = 1 - stato; 
    delay(15);                // attesa di 15 millisecondi 
  }   
 
  vecchio_val = val;          // ricordiamo il valore precedente di val 
 
    if (stato == 1) { 
    digitalWrite(LED, HIGH);  // accende il LED 
    delay(1000);              // aspetta un secondo 
    digitalWrite(LED, LOW);   // spegne il LED 
    delay(1000);              // aspetta un secondo 
  } 
  else { 
    digitalWrite(LED, LOW);    //spegne il led 
  } 

Il problema è appunto che per spegnere il led in pratica devo tener premuto per qualche secondo il pulsante, al contrario io invece vorrei che il pulsante funzionasse all'istante e facendo quindi tornare, in un istante, il led allo stato 0, ossia spento.

Spero di essere stato chiaro nella spiegazione del problema e spero altrettanto che qualcuno possa darmi una mano! Grazie mille in anticipo smiley-grin
Logged

Torino
Offline Offline
God Member
*****
Karma: 3
Posts: 766
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao il tuo problema è determinato da questo passaggio
Code:
if (stato == 1) { 
    digitalWrite(LED, HIGH);  // accende il LED 
    delay(1000);              // aspetta un secondo 
    digitalWrite(LED, LOW);   // spegne il LED 
    delay(1000);              // aspetta un secondo 
  } 
Una volta entrato nella if hai due delay che devono essere eseguiti e solo dopo trascorso tale tempo il tuo programma potrà andare a controllare lo stato del pulsante e spegnere il led se il pulsante é premuto.
Logged

Italy
Offline Offline
Newbie
*
Karma: 1
Posts: 6
Newbie Programmer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Molto interessante. C'è un modo per ovviare al problema evitando di togliere quei ritardi che mi danno il lampeggiamento del led?
Logged

Torino
Offline Offline
God Member
*****
Karma: 3
Posts: 766
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Non si può ovviare al problema senza togliere i delay perchè come hai capito sono bloccanti cioè bloccano l'esecuzione del codice.
Un modo per aggirare il problema è quello di usare il millis().
Trovi tutte le informazioni necessarie nel reference e c'è un esempio di lampeggio del led che non utilizza i delay ma appunto la funzione millis(),dagli un'occhiata e vedrai che ti sarà utile.

Edit. reference è una cartella che trovi all'interno del pacchetto che hai scaricato per l'ide  smiley
« Last Edit: November 21, 2012, 12:14:57 pm by tonid » Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 115
Posts: 7265
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Il Reference lo trovi anche on line sul sito di Arduino: http://arduino.cc/en/Reference/HomePage
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Italy
Offline Offline
Newbie
*
Karma: 1
Posts: 6
Newbie Programmer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sapevo di poter contare sul vostro aiuto e infatti sono riuscito ad ottenere ciò che volevo smiley-grin

Ecco, adesso non vorrei essere troppo palloso, ma è sorto un altro piccolo problema che penso e spero sia di facile risoluzione.
In pratica adesso ho un ritardo, probabilmente di 1 o 2 secondi massimo all'accensione dell led dopo aver premuto il pulsante.
Posto nuovamente il codice in modo da capire anche se ho manomesso troppo con la funzione milliss:

Code:
// Il led lampeggia se premo il pulsante  
// premendo una seconda volta il pulsante si spegne il led  
  
#define LED 13                  
#define BUTTON 7                
int val = 0;                    
int vecchio_val = 0;            
int stato = 0;
int ledState = LOW;            
long previousMillis = 0;        
long interval = 800;


void setup() {  
  pinMode(LED, OUTPUT);        
  pinMode(BUTTON, INPUT);      
}  
  
void loop() {  
  val = digitalRead(BUTTON);    
  
  // controlla se è accaduto qualcosa  
  if ((val == HIGH) && (vecchio_val == LOW)){  
    stato = 1 - stato;  
                  
  }  
  
  vecchio_val = val;          
  
    if (stato == 1) {
      unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    
    previousMillis = currentMillis;  

    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    
    digitalWrite(LED, ledState);
  }
    }  
  else {  
    digitalWrite(LED, LOW);    
  }  
}  


Considerate che sono alle primissime armi, quindi per la funzione milliss mi sono limitato a capire dove dovevo copiare le varie parti dall'esempio nel reference.
« Last Edit: November 21, 2012, 02:27:30 pm by LasaleFamine » Logged

Torino
Offline Offline
God Member
*****
Karma: 3
Posts: 766
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
In pratica adesso ho un ritardo
Se non vuoi il ritardo all'accensione devi accendere il led subito dopo aver controllato la variabile stato
Code:
if (stato == 1) {
      unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
se stato ==1 accendi subito il led e poi procedi con la millis e trascorso il tempo lo spegni....tu invece stai aspettando che sia passato il tempo da te impostato e poi accendi il led.
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao, i miei 2 cents non c'entrano col tuo problema, ma... Visto che sei alle prime armi abituati ad indentare correttamente il codice. CTRI+T nell'IDE ti sarà d'aiuto. L'indentazione non è una questione estetica, serve a capire il flusso di esecuzione "a occhio".

Non aggiungo altro perché ti hanno già risposto esaurientemente gli altri. smiley
Logged

Italy
Offline Offline
Newbie
*
Karma: 1
Posts: 6
Newbie Programmer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Innanzitutto grazie tuxduino per il consiglio sull'indentazione del codice, spero di tenerlo sempre a mente. smiley

Ritornando al mio stupido problema, ma che ahimè non sono riuscito a risolvere.
Ho riflettuto sul consiglio datomi, tonid, ma non riesco a capire come far accendere il led prima di mettere il Millis; mi spiego:

Code:
// Il led lampeggia se premo il pulsante  
// premendo una seconda volta il pulsante si spegne il led  

#define LED 13                  
#define BUTTON 7                
int val = 0;                    
int vecchio_val = 0;          
int stato = 0;
int ledState = LOW;            
long previousMillis = 0;      
long interval = 1000;


void setup() {  
  pinMode(LED, OUTPUT);        
  pinMode(BUTTON, INPUT);      
}  

void loop() {  
  val = digitalRead(BUTTON);    


  if ((val == HIGH) && (vecchio_val == LOW)){  
    stato = 1 - stato;  
    delay(15);                  
  }  

  vecchio_val = val;          

  if (stato == 1) {

    digitalWrite(LED, ledState);
    unsigned long currentMillis = millis();

    if(currentMillis - previousMillis > interval) {

      previousMillis = currentMillis;  


      if (ledState == LOW)
        ledState = HIGH;
      else
        ledState = LOW;


      digitalWrite(LED, ledState);
    }
  }  
  else {  
    digitalWrite(LED, LOW);      
  }  
}  



Come potete vedere ho aggiunto il comando, stupidamente penso, digitalWrite [che è l'unico che conosco per accendere il LED] con la variabile ledState; ho fatto ciò perché aggiungendo digitalWrite (LED, HIGH) [come per accendere il LED] avevo come risultato un normale circuito con tocco di pulsante - led accesso, tocco di pulsante - led spento.
Ho notato il cambiamento, ma ovviamente come ben sapete non è assolutamente ciò di cui avevo bisogno :-/
Mi stimola risolvermi questi piccoli problemi; scusate, ma cerco di apprendere quanto più possibile queste nozioni base!
Grazie ancora per i consigli!
« Last Edit: November 21, 2012, 06:51:56 pm by LasaleFamine » Logged

Torino
Offline Offline
God Member
*****
Karma: 3
Posts: 766
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Mi stimola risolvermi questi piccoli problemi; scusate, ma cerco di apprendere quanto più possibile queste nozioni base!
Per accendere subito il led appena entri nella if la variabile ledState deve essere inizializzata HIGH e non LOW
Code:
#define LED 13                 
#define BUTTON 7               
int val = 0;                   
int vecchio_val = 0;         
int stato = 0;
int ledState = LOW;             
long previousMillis = 0;     
long interval = 1000;
In questo modo....
Code:
if (stato == 1) {

    digitalWrite(LED, ledState);
    unsigned long currentMillis = millis();

    if(currentMillis - previousMillis > interval) {

      previousMillis = currentMillis;   


      if (ledState == LOW)
        ledState = HIGH;
      else
        ledState = LOW;


      digitalWrite(LED, ledState);
    }
  } 
accendi subito il led,aspetti che il tempo da te impostato con interval venga raggiunto ed entri nella if aggiornandoti il valore su previousMillis,subito dopo controlli lo stato del led ovvero lo cambi da HIGH a LOW e viceversa e dai al led il valore attuale con il digitalWrite.
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Compila, ma non l'ho provato:

Code:
// Il led lampeggia se premo il pulsante 
// premendo una seconda volta il pulsante si spegne il led 

#define LED 13                 
#define BUTTON 7               
int val = 0;              // stato attuale del pulsante
int vecchio_val = 0;      // stato del pulsante nella lettura precedente
int stato = 0;            // 0 = led spento, 1 = led lampeggiante
int ledState = LOW;       // stato attuale del led
long previousMillis = 0;     
long interval = 1000;     // semiperiodo di lampeggio del led

void setup() { 
    pinMode(LED, OUTPUT);         
    pinMode(BUTTON, INPUT);       


void loop() { 
    val = digitalRead(BUTTON);   

    if ((val == HIGH) && (vecchio_val == LOW)) {
        // inverto il flag di abilitazione al lampeggio
        stato = 1 - stato;
       
        // non appena cambia il flag di abilitazione al lamepggio
        // aggiorniamo lo stato del led
       
        if (stato == 0) {
            // se il lampeggio è stato disabilitato, spegnamo subito il led
            ledState = LOW;
            digitalWrite(LED, ledState);
        }
        else {
            // se il lampeggio è stato abilitato, accendiamo subito il led
            // e inizializziamo il timer del lampeggio
            ledState = HIGH;
            digitalWrite(LED, ledState);
            previousMillis = millis();    // il led cambierà stato dopo interval ms da ora
        }
       
        delay(15);
    }   

    vecchio_val = val;

    if (stato == 1) {
        unsigned long currentMillis = millis();

        if(currentMillis - previousMillis > interval) {

            previousMillis = currentMillis;   

            if (ledState == LOW)
                ledState = HIGH;
            else
                ledState = LOW;

            digitalWrite(LED, ledState);
        }
    } 
    else {
        // probabilmente questo ora non serve
        digitalWrite(LED, LOW);     
    } 


L'idea è che se vuoi reagire immediatamente alla pressione del pulsante, allora devi pilotare il led non appena ha rilevato tale evento.
Logged

Italy
Offline Offline
Newbie
*
Karma: 1
Posts: 6
Newbie Programmer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Veramente esaustivo, grazie mille! E il codice funziona anche su base pratica smiley-grin

Avevo già intuito da ciò che mi avevi spiegato in precedenza che dovevo dividere in due casi il codice, una parte a LED spento e l'altra a LED lampeggiante ma non ho afferrato subito l'idea di poter usare "stato == 0" per spegnerlo in pratica o in caso contrario accenderlo e "stato == 1" per farlo lampeggiare. Se ho capito bene è questo che hai fatto nel codice.

Funziona perfettamente, l'ultimo "digitalWrite" non è necessario come sostenevi già tu e inoltre mi ritengo soddisfatto di aver appreso di più sulla funzione Millis e anche sulla stesura totale del codice con le varie parti.

Grazie mille a tutti!
Logged

Pages: [1]   Go Up
Jump to: