Go Down

Topic: Problema lettura stato pulsanti, con digitalRead e delay (Read 1 time) previous topic - next topic

manuelc

May 06, 2012, 12:53 pm Last Edit: May 06, 2012, 01:07 pm by manuelc Reason: 1
Ciao a tutti,
sono nuovo. Ho un passato da programmatore e nessuna conoscenza elettronica.
Mi sto studiando questo bellissimo oggetto (Arduino UNO) cimentandomi nella realizzazione di un po' di prototipi, per ora, didattici.

Ho un po' di probemi con i pulsanti.

Il seguente codice non funziona se non inserisco un delay dopo la lettura dello stato del pulsante.... mi aiutate a capire il perché? Ho cercato sul forum e su internet ma essendo nuovissimo di questo mondo ho pure difficoltà a fare le giuste domande/ricerche...

Potreste indicarmi quando è necessario usare il delay per questo tipo di INPUT? Per caso si può risolvere/velocizzare la lettura tramite particolari accortezze sul circuito elettrico?

Il circuito che uso per il pulsante è quello allegato.

Di seguito il mio programma
Code: [Select]


#define TEST
//#define BUILD


// Definizione PIN per i componenti
#define BUTTON_ONOFF 7
#define LED_ON 13
#define LED_ALARM 12
#define TILT_SENSOR 8
#define BUZZER 4
#define VOLUME_BUZZER A0
/* QUI SOTTO SONO DEFINITI I SENSORI DI TEST PER SIMULAZIONE */
#if defined(TEST)
#define DOOR_SENSOR 2
#endif

// inizializzo variabili globali
bool ON = false; /* false: OFF; true: ON */
bool ALARM = false; /* false: ALARM OFF; true: ALARM ON */
int VOLUME; /* volume buzzer interno*/
unsigned long PREVIOUS_MILLIS;

// =========================================================================
void setup()
{
 // inizializzo i dati in ingresso
 Serial.begin(9600);

 /* riservo e definisco i PIN */
 pinMode(LED_ON, OUTPUT);
 pinMode(LED_ALARM, OUTPUT);
 pinMode(BUZZER, OUTPUT);
 pinMode(TILT_SENSOR, INPUT);
#if defined(TEST)
 pinMode(DOOR_SENSOR, INPUT);
#endif

 /* inizializzo i LED */
 digitalWrite(LED_ON, HIGH);
 digitalWrite(LED_ALARM, LOW);

 /* imposto il volume del BUZZER*/
 VOLUME = (analogRead(VOLUME_BUZZER)/ 4.015686275); //1024÷255 = 4,015686275

}
// =========================================================================
void loop()
{
// put your main code here, to run repeatedly:


/* controllo attivazione/disattivazione monitoraggio allarme*/
if (digitalRead(BUTTON_ONOFF) == HIGH)
{
delay(250);
switch (ON)
{
case false:
ON = true;
Serial.println("Allarme attivato");
break;
case true:
ON = false;
Serial.println("Allarme disattivato");
break;
}
}


/* monitoro i sensori solo se l'allarme è inserito*/
if (ON)
{
Serial.println("Controllo i sensori...");
/* controllo il sensore di TILT*/
Serial.println("\tSensore TILT: ");
if (digitalRead(TILT_SENSOR) == HIGH)
{
ALARM = true;
Serial.println("\tSensore TILT: ATTIVATO");
}
#if defined(TEST)
if (digitalRead(DOOR_SENSOR) == LOW)
{
ALARM = true;
Serial.println("\tSensore DOOR_SENSOR: ATTIVATO");
}
#endif
if (ALARM)
{
Serial.println("Procedura allarme...");
/* in caso di allarme attivo un clock con intervallo di 1000 millisecondi */
int interval = 1000; //clock interval
unsigned long currentMillis = millis();

if((currentMillis - PREVIOUS_MILLIS) > interval)
{

PREVIOUS_MILLIS = currentMillis;

if (digitalRead(LED_ALARM) == HIGH)
{
digitalWrite(LED_ALARM, LOW);
Serial.println("\tLED_ALARM: SPENTO");
noTone(BUZZER);
Serial.println("\tBUZZER: SPENTO");
}
else
{
digitalWrite(LED_ALARM, HIGH);
Serial.println("\tLED_ALARM: ACCESO");
tone(BUZZER, 50000);
Serial.println("\tBUZZER: ACCESO");
}
}

} //ALARM

}
else
{
digitalWrite(LED_ALARM, LOW);
noTone(BUZZER);
} // ON
}

sciorty

Premetto di non aver letto attentamente il tuo codice ma il delay per il pulsanti lo si usa per dare all'utente il tempo di rilasciarlo, altrimenti ad un certo punto del codice ti risulterebbe ancora HIGH

manuelc

Grazie Sciorty,
ma l'uso del delay in questo modo non mi torna per questi 2 motivi:
1. non posso sapere a priori per quanto tempo sarà premuto il pulsante, quindi il valore preciso di delay è indeterminabile.
2. non trovo corretto bloccare tutta l'esecuzione del programma in attesa della lettura del pulsante.

sono disperato... :) non trovo una soluzione..... :((

paolo_fiorini3

#3
May 06, 2012, 01:36 pm Last Edit: May 06, 2012, 01:44 pm by paolo_fiorini3 Reason: 1
Solitamente il delay dopo la lettura di un pulsante viene utilizzato come contromisura software ai "rimbalzi" che il pulsante stesso ha al momento della pressione...
Prova a dare un'occhiata qui: http://www.maffucci.it/2011/06/13/arduino-alcune-precisazioni-sullantirimbalzo/

Per la gestione del pulsante ti consiglio di provare ad usare questa libreria...implementa l'anti-rimbalzo e io mi sono trovato molto bene...

http://www.arduino.cc/playground/Code/Bounce

edit : hai messo una resistenza di troppo sul pulsante... controlla qui: http://arduino.cc/en/Tutorial/Button


pablos

#4
May 06, 2012, 02:04 pm Last Edit: May 06, 2012, 02:29 pm by pablos Reason: 1
Non disperare,

1) togli la resistenza in più seguendo il link postato da paolo_fiorini3
2) togli tutti i delay selle letture dei contatti sensori volumetrici e magnetici
3) metti questo in parallelo ai contatti http://italian.alibaba.com/product-gs/the-best-selling-ceramic-capacitor-104-302506208.html
4) non usare librerie bounce in questo test

però dovresti farmi sapere il risultato

grazie ciao
no comment

manuelc

Grazie a tutti per l'aiuto!

Allora,
la resistenza in più era nel vano tentativo di ridurre il rumore abbassando l'intensità della corrente...  :smiley-red:
Ho provato le libreria Bounce ma con scarsissimi risultati.... macchinosa da gestire nel codice e comunque applica dei delay definiti dall'utente.

Grazie al consiglio di pablos ho iniziato a intuire a cosa servono i condensatori ... (anche grazie a questo link: http://digilander.libero.it/nick47/cond.htm) :)

Non ho disponibile il condensatore ceramico che mi hai indicato, ma quelli in dotazione del kit base dell'arduino UNO, quindi ho usato quello da 100nF in poliestere  (tra parentesi sulla scatola c'è scritto "ceramic").
Da solo il condensatore non risolve, ma insieme ad un delay di 250msec rende la lettura leggermente più stabile.

Non risolve completamente ma mette una pezza abbastanza grande.

Ho provato anche gli altri condensatori ma è come se non ci fossero.

Ma voi come risolvete nei vostri progetti? Se avete una centralina e volete comandare l'avvio di un servizio tramite pressione di un pulsante, come fate a gestire in modo CERTO la pressione per far partire e poi fermare il servizio?

Grazie,
M.



pablos

#6
May 06, 2012, 04:12 pm Last Edit: May 06, 2012, 04:14 pm by pablos Reason: 1
Guarda gli esempi dentro al tuo IDE riguardante il pulsante
File > Examples > Digital > Button

oppure

File > Examples > Digital > Debounce
in questo esempio il delay è fatto con un millis() che non interrompe lo svolgimento del programma

oppure

File > Examples > Digital > State change detection

comunque io uso solo un condensatore senza delay, sarò fortunato io :)
Condensatore cermico da 100.000pF ovvero 100nF: è scritto: 104. Per questo chiedevo un riscontro su altri progetti

ciao
no comment

manuelc

Grazie ancora del suupporto.
Per ora userò il delay.... in attesa di metabolizzare bene le varie tecniche di debounce.

Vi ringrazio soprattutto per avermi fatto conoscere il problema del RIMBALZO che mi era completamente sconosciuto, che da quello che posso intuire dipende anche dalla componentistica utilizzata. Immagino che un pulsante digitale meccanico con una semplice molla ed un paio di contatti avrà più problemi rispetto ad un pulsante digitale con un circuito di filtro dedicato... esiste?


Go Up