Pages: [1]   Go Down
Author Topic: Problema LCD + pulsante (debounce?)  (Read 741 times)
0 Members and 1 Guest are viewing this topic.
Roma
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Buongiorno ragazzi. Premetto che sono alle prime armi; quindi, per favore, non sgridatemi se leggerete corbellerie  smiley-lol

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:
#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  smiley  smiley  smiley  smiley
« Last Edit: April 23, 2013, 05:03:22 am by gabm88 » Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 112
Posts: 7126
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
#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.
« Last Edit: April 23, 2013, 07:56:23 am by PaoloP » Logged

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

Roma
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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  smiley-confuse ).
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  smiley-sad .

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.
« Last Edit: April 24, 2013, 04:16:58 am by gabm88 » Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 112
Posts: 7126
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
byte Button = digitalRead(ButtonPin);
non è altro che una forma compressa di
Code:
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.
Logged

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

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 332
Posts: 22817
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged


Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 112
Posts: 7126
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Per imparare il C ...

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

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

Roma
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley-lol  smiley-lol  smiley-lol ).

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);
}
Logged

Pages: [1]   Go Up
Jump to: