Go Down

Topic: Problema LCD + pulsante (debounce?) (Read 885 times) previous topic - next topic

gabm88

Apr 23, 2013, 11:10 am Last Edit: Apr 23, 2013, 12:03 pm by gabm88 Reason: 1
Buongiorno ragazzi. Premetto che sono alle prime armi; quindi, per favore, non sgridatemi se leggerete corbellerie  XD

Il progetto è abbastanza semplice, adatto alla mia esperienza. Esso consiste in un led IR, un pulsante e uno schermo LCD (e Arduino Uno Rev3, ovviamente!). La pressione del pulsante attiva il led, che funge da scatto remoto per la mia reflex Nikon. Al momento dello scatto lo schermo visualizza la dicitura "Scatto!" per un secondo. Vorrei in futuro implementare questo piccolo progetto per poter automatizzare la reflex con altri sensori come fotoresistenze.

Nella pratica, il progetto funziona ma non capisco delle cose:
- Appena alimento arduino, noto (con la fotocamera del mio cellulare) che il led IR rimane acceso per circa 8 secondi. In quel lasso di tempo, se premo il pulsante, non mi viene riconosciuto il cambio di stato del pulsante e perciò non viene visualizzato "Scatto!" sul display LCD. E' forse l'inizializzazione del programma che rende inutilizzabile il sistema per quei secondi? Purtroppo non riesco a capire molto bene la programmazione dello scatto remoto (che ho copiato da internet), perchè forse è spiegato tutto li. O forse è un problema di debounce?
- Ho notato che il led L presente sul mio arduino, durante l'esecuzione del programma, rimane sempre acceso, anche se non menziono minimamente il pin 13 sullo sketch. Ho letto che è un problema di "corrente parassita" che afflige questa Rev di Arduino. Infatti, piazzando una resistenza da 4700 ohm tra il pin 13 e Ground, il led si spegne. Come posso rimediare a questo, anche se non intacca l'esecuzione dello sketch?

ecco il codice:
Code: [Select]
#define LEDPin 12
#define ButtonPin 11
#define FREQ 38400  // IR frequence
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
unsigned long sequence[] = {2000,27830,390,1580,410,3580,400,63200,2000,27830,390,1580,410,3580,400,0};
int seq_l;
int oscd;

void oscillate(int pin, unsigned long n, int shine){
int ir_status=0;
while(n>0){
n--;
delayMicroseconds(oscd);
ir_status  =  !ir_status;
digitalWrite(pin,  ir_status && shine); 
}
}

void snap(){
int i;
for(i=0;i<seq_l;i++){
oscillate(LEDPin, sequence[i], i%2==0);
}
digitalWrite(LEDPin,  0);
}

void setup() {
  lcd.begin(16,2);
  lcd.print("Scatto remoto");
  pinMode(ButtonPin, INPUT);   
                int min=1, max=100, i;
int last_oscd=0;
unsigned long before, intervalle;
oscd=max;

seq_l = sizeof(sequence)/sizeof(unsigned long);

pinMode(LEDPin, OUTPUT);

while(last_oscd!=oscd){
last_oscd=oscd;
oscd=(min+max)>>1;

before=millis();
oscillate(LEDPin, FREQ, 1);
intervalle=millis()-before;

if(intervalle >= 1000) max=oscd;
else min=oscd;
}

for(i=0;i<seq_l;i++){
sequence[i] = (sequence[i] * FREQ) / (intervalle * 1000);
}
}


void loop() {
                if (digitalRead(ButtonPin)==HIGH){
                  snap();    // take a photo when button pressed.
                  lcd.clear();
                  lcd.print("Scatto!");
                  delay(1000);
                  lcd.clear();
                  lcd.print("Pronto...");
                  }
                delay(100);

}

Grazie in anticipo per le risposte, e se non sono stato chiaro, o se ho scritto stupidaggini, abbiate pietà di me  :)  :)  :)  :)

PaoloP

#1
Apr 23, 2013, 02:33 pm Last Edit: Apr 23, 2013, 02:56 pm by PaoloP Reason: 1
min e max sono due #define utilizzati da Arduino.
Dovresti cambiare nome alle variabili.

Code: [Select]
#define LEDPin 12
#define ButtonPin 11
#define FREQ 38400  // IR frequence
#include <LiquidCrystal.h>

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

unsigned long sequence[] = {
 2000,27830,390,1580,410,3580,400,63200,2000,27830,390,1580,410,3580,400,0};
int seq_l;
int oscd;

void setup() {
 pinMode(ButtonPin, INPUT);  
 pinMode(LEDPin, OUTPUT);
 digitalWrite(LEDpin, LOW);

 lcd.begin(16,2);
 lcd.print("Scatto remoto");

 int Min=1, Max=100, i;
 int last_oscd=0;
 unsigned long before, intervalle;

 oscd=Max;
 seq_l = sizeof(sequence)/sizeof(unsigned long);

 while(last_oscd != oscd){
   last_oscd = oscd;
   oscd = (Min+Max)>>1;
   before=millis();
   oscillate(LEDPin, FREQ, 1);
   intervalle=millis()-before;
   if(intervalle >= 1000)
     Max=oscd;
   else
     Min=oscd;
 }

 for(i=0; i<seq_l; i++){
   sequence[i] = (sequence[i] * FREQ) / (intervalle * 1000);
 }
    lcd.clear();
    lcd.print("Pronto...");
}

void loop() {
 byte Button = digitalRead(ButtonPin);
 delay(10);

 if (Button){
   snap();    // take a photo when button pressed.
   lcd.clear();
   lcd.print("Scatto!");
   delay(1000);
   lcd.clear();
   lcd.print("Pronto...");
 }
}

void oscillate(byte pin, unsigned long n, int shine){
 int ir_status=0;
 while(n>0){
   n--;
   delayMicroseconds(oscd);
   ir_status != ir_status;
   digitalWrite(pin,  ir_status && shine);  
 }
}

void snap(){
 int i;
 for(i=0; i<seq_l; i++){
   oscillate(LEDPin, sequence[i], i%2==0);
 }
 digitalWrite(LEDPin,  0);
}


Ricorda di mettere una resistenza di limitazione sui led e una pull-down per il pulsante.

gabm88

#2
Apr 24, 2013, 11:10 am Last Edit: Apr 24, 2013, 11:16 am by gabm88 Reason: 1
Buongiorno PaoloP, ti ringrazio della risposta e del tempo dedicatomi.

Ho usato il tuo sketch, molto più pulito del mio (anzi mi scuso se era un po caotico  :~ ).
Ho visto lcd.print del setup a cui non avevo pensato, che mi avverte quando l'Arduino è pronto a scattare, molto utile. Ho visto anche il comando Byte che hai aggiunto a void loop, di cui non mi è molto chiara la funzione  :( .

Ho notato però che il led IR rimane sempre spento, anche quando dovrebbe scattare, e ne deduco che il problema sia sulla modifica apportata a void oscillate, riga 66, da "ir_status  =  !ir_status;"  a "ir_status  !=  ir_status; ". Se ri "risistemo", torna tutto pressochè come prima e il LED ha quei 7 o 8 secondi di inattività iniziale in cui rimane acceso. 

Grazie in anticipo per eventuali chiarimenti. Buona giornata!


min e max sono due #define utilizzati da Arduino.
Dovresti cambiare nome alle variabili.

Ricorda di mettere una resistenza di limitazione sui led e una pull-down per il pulsante.

PaoloP

byte è la definizione di un tipo di variabile che può avere valori compresi tra 0 e 254.
Poichè digitalRead(ButtonPin); restituisce come valore o 0 o 1 puoi tranquillamente utilizzate questo tipo perché non avrai mai problemi di overflow (quanto tenti di assegnare un numero maggiore della capienza massima della variabile)

l'istruzione
Code: [Select]
byte Button = digitalRead(ButtonPin);
non è altro che una forma compressa di
Code: [Select]
byte Button;
Button = digitalRead(ButtonPin);

dove la prima riga definisca la variabile Button di tipo byte e la seconda assegna alla variabile Button il risultato della lettura del pin chiamato Buttonpin.
Mettendo tutto in una riga crei la variabile e gli assegni un valore con una sola istruzione. Più compatto ma a volte più complicato da capire.

Riguardo ir_status  =  !ir_status; e ir_status  !=  ir_status; ritengo che non dovrebbero esserci differenze.
Infatti nel promo caso assegni alla variabile ir_status la variabile !ir_status, mentre nel secondo assegni a ir_status l'opposto di ir_status.

Se non funziona ci deve essere qualche problema col codice, ma non potendolo testare dal vivo perché non ho un led IR non so che dirti.

Speriamo che passi qualcun altro da queste parti.  :smiley-mr-green:

Per imparare il C (il linguaggio con cui si programma Arduino) puoi leggere varie guide disponibili su internet (ad esempio: http://www.html.it/guide/guida-c/, http://www.science.unitn.it/~fiorella/guidac/indexc.html) ricordando che sono pensate per la programmazione su PC e non su Microcontrollore.
Oppure potresti pensare all'acquisto di un libro su Arduino. C'è ne sono diversi.

leo72


byte è la definizione di un tipo di variabile che può avere valori compresi tra 0 e 254.

255

Quote

Riguardo ir_status  =  !ir_status; e ir_status  !=  ir_status; ritengo che non dovrebbero esserci differenze.

C'è differenza perché ir_status = !ir_status non è un confronto ma un'assegnazione. Il confronto usa 2 segni ==, per cui:
ir_status  ==  !ir_status


gabm88



Per imparare il C ...


Mi sa che lo devo imparare io.  :smiley-mr-green: :smiley-mr-green: :smiley-mr-green:


Ahahah grazie ragazzi, siete stati d'aiuto! Ora ho un altro piccolo problema, il programma lo sto mandando avanti, e comanda:
display, led IR, fotoresistenza, pulsante, tre led (troppe cose per me  :smiley-eek: )
Lo sketch al quale sono arrivato (grazie a voi) mi fa questo: quando premo il pulsante il led IR fa da scatto remoto per la mia Nikon, il contatore degli scatti mi segna su display il numero di scatti eseguiti. Nel display visualizzo anche il valore letto dalla fotoresistenza e lo stato del programma (caricamento - pronto). I tre led mi indicano l'intensità della luce (sono puramente decorativi XD  XD  XD ).

Il mio obiettivo è:
Riuscire a fare un programma che attivi il LED IR solo per il primo scatto, a una data quantità di luce ricevuta dalla fotoresistenza. Il programma dovrà poi disattivare la lettura della luce, in modo tale che il secondo scatto remoto sarà deciso da me, alla pressione del pulsante. E con la pressione del pulsante, a sua volta, il programma dovrà ricominciare a leggere i valori di luce ed eventualmente a scattare in caso dei valori di luce appropriati. E così via per l'infinito!

Io ho pensato di "semplificare" così: la fotoresistenza legge la luce; ad un dato valore di luce, parte lo scatto remoto. Il contatore segna 1 scatto (valore disparo). Ad ogni valore disparo viene disattivato il controllo della luce e lo scatto remoto automatico, ed entra in funzione il pulsante che, se premuto, manualmente, esegue un nuovo scatto remoto, e il contatore segna 2 scatti (valore paro), per cui rientra in funzione la lettura della luce, e così via, in loop.

Grazie ragazzi, spero di essere stato chiaro!

ecco lo sketch:
Quote
#define LEDPin 12
#define ButtonPin 11
#define FREQ 38400
#include <LiquidCrystal.h>
int ledPin1 = 8;
int ledPin2 = 9;
int ledPin3 = 10;
int a = 0;
int FotoPin = 1;
int FotoValue;
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

unsigned long sequence[] = {
  2000,27830,390,1580,410,3580,400,63200,2000,27830,390,1580,410,3580,400,0};
int seq_l;
int oscd;

void setup() {
  pinMode(LEDPin, OUTPUT);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(ButtonPin, INPUT);
  digitalWrite(ledPin1, LOW);
  digitalWrite(LEDPin, LOW);
 
  lcd.begin(16,2);
  lcd.print("Caricamento");
 
  int Min=1, Max=100, i;
  int last_oscd=0;
  unsigned long before, intervalle;
 
  oscd=Max;
  seq_l = sizeof(sequence)/sizeof(unsigned long);
 
  while(last_oscd != oscd){
    last_oscd = oscd;
    oscd = (Min+Max)>>1;
    before=millis();
    oscillate(LEDPin, FREQ, 1);
    intervalle=millis()-before;
    if(intervalle >= 1000)
      Max=oscd;
    else
      Min=oscd;
  }

  for(i=0;i<seq_l;i++){
    sequence = (sequence * FREQ) / (intervalle * 1000);
  }
  lcd.clear();
}

void loop() {
  FotoValue = analogRead(FotoPin);
  byte Button = digitalRead(ButtonPin);
  lcd.setCursor(13,0);
  lcd.print(FotoValue);
  delay(50); 
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Pronto"); //alla fine del caricamento del SETUP, il display avverte;
  lcd.setCursor(0, 1);
  lcd.print("Scatto n.: ");
  lcd.setCursor(7,0);
  lcd.print("Luce:");
  lcd.setCursor (12,1);
  lcd.print(a);
  if (Button){
    snap();
    a=a+1; delay(500);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Scatto!"); //alla fine del caricamento del SETUP, il display avverte;
    lcd.setCursor(0, 1);
    lcd.print("Scatto n.: ");
    lcd.setCursor (12,1);
    lcd.print(a);
    delay(500);
    lcd.clear();
  }
    if (FotoValue< 20) {
    digitalWrite(ledPin1, LOW);
    digitalWrite(ledPin2, LOW);
    digitalWrite(ledPin3, LOW);
} else if (FotoValue< 50) {
    digitalWrite(ledPin1, HIGH);
    digitalWrite(ledPin2, LOW);
    digitalWrite(ledPin3, LOW);
} else if (FotoValue< 150) {
    digitalWrite(ledPin1, HIGH);
    digitalWrite(ledPin2, HIGH);
    digitalWrite(ledPin3, LOW);
} else {
    digitalWrite(ledPin1, HIGH);
    digitalWrite(ledPin2, HIGH);
    digitalWrite(ledPin3, HIGH);
}
delay(1);
}


void oscillate(byte pin, unsigned long n, int shine){
  int ir_status=0;
  while(n>0){
    n--;
    delayMicroseconds(oscd);
    ir_status  =  !ir_status;
    digitalWrite(pin,  ir_status && shine); 
  }
}

void snap(){
  int i;
  for(i=0;i<seq_l;i++){
    oscillate(LEDPin, sequence, i%2==0);
  }
  digitalWrite(LEDPin,  0);
}

Go Up