buongiorno a tutti
ne capisco poco di programmazione e ora avendo del tempo a disposizione sto cercando di imparare con un arduino, acquistato da diverso tempo ma mai preso in considerazione più del dovuto
capito da esempi come accendere un led, accenderlo e spegnerlo con lo stesso pulsante come passo-passo e ora voglio provare con timer
nella breadboard ho cablato2 pulsanti che devono accendere 2 led e spegnersi dopo N tempo anche se non rilascio il pulsante realizzandolo con delay.
li ho chiamati pulsante A e led A, pulsante B e led B e il mio scopo è quello di 2 circuiti separati: il pulsante A accende il led A e il pulsante B il led B
dovrebbe funzionare cosi:
premo pulsanteA accende led A, inizia conteggio tempo N si spegne il led A anche se ancora non ho rilasciato il pulsante
durante tutto questo tempo di led A acceso o pulsante A premuto se premo il pulsante B il secondo circuito deve comportarsi nello stesso modo.
prendendo in esame gia solo pulsanteA non riesco a far spegnere il led A dopo N tempo se il pulsante rimane premuto. si accende premendo il pulsante, ma spegne dopo N tempo aver rilasciato il pulsanteA
poi provando anche il secondo circuito questo si accende solo allo scadere del primo delay premuto
qualcuno puo aiutarmi?
allego mio sketch
/*
- LED collegato fra pin e negativo
- pulsante collegato fra pin e +5V
- resistenza 10k collegata fra pin e negativo
*/
const int pulsanteA = 7; // pulsanteA
const int pulsanteB = 8; // pulsanteB
const int ledA = 2; // ledA
const int ledB = 3; // ledB
int statopulsanteA = 0; // variabile per lettura del pulsanteA non premuto
int statopulsanteB = 0; // variabile per lettura del pulsanteB non premuto
void setup() {
pinMode(pulsanteA, INPUT); // il pulsanteA è un ungresso
pinMode(pulsanteB, INPUT); // il pulsanteB è un ungresso
pinMode(ledA, OUTPUT); //il ledA è una uscita
pinMode(ledB, OUTPUT); //il ledB è una uscita
}
void loop() {
statopulsanteA = digitalRead(pulsanteA);// qui definisco lo stasto del pulsanteA
if (statopulsanteA == HIGH) { //se il pulsanteA è premuto
digitalWrite(ledA, HIGH); // accendo il ledA
delay(2000); //questo è il tempo di accensione dopo aver rilasciato il pulsanteA
} else { // se rilascio il pulsanteA
digitalWrite(ledA, LOW); // spengo il ledA
}
statopulsanteB = digitalRead(pulsanteB);// qui definisco lo stasto del pulsanteB
if (statopulsanteB == HIGH) { //se il pulsanteB è premuto
digitalWrite(ledB, HIGH); // accendo il ledB
delay(2000); //questo è il tempo di accensione dopo aver rilasciato il pulsanteB
} else { // se rilascio il pulsanteB
digitalWrite(ledB, LOW); // spengo il ledB
}
}
lampadina915:
prendendo in esame gia solo pulsanteA non riesco a far spegnere il led A dopo N tempo se il pulsante rimane premuto. si accende premendo il pulsante, ma spegne dopo N tempo aver rilasciato il pulsanteA.
poi provando anche il secondo circuito questo si accende solo allo scadere del primo delay premuto
1a) Il primo problema deriva dal fatto di testare il livello attuale del pulsante e non sua variazione che avviene solo nell'istante della pressione. Per rilevare l'istante di pressione basta fare il controllo con la lettura precedente, quindi: se lettura attuale diversa da precedente E corrisponde al livello premuto (in questo caso HIGH) allora abbiamo rilevato l'istante di pressione (che non si verifica più finché non si rilascia e si ripreme). Naturalmente alla fine di ogni giro la lettura precedente va aggiornata con il valore di quella attuale.
1b) In parallelo alla resistenza di ogni pulsante va collegato anche un condensatore 100nF per eliminare i rimbalzi di chiusura e apertura che verrebbero letti come pressioni multiple. In alternativa la via più spiccia (ma non sempre applicabile) è aggiungere un delay(50) alla fine del loop in modo da rallentarne l'esecuzione a circa venti giri al secondo (i rimbalzi si esauriscono in pochi millisecondi o anche in uno solo).
- Il secondo problema invece nasce direttamente dall'uso di lunghi delay che interrompono completamente l'esecuzione del programma fino allo scadere del tempo, per cui nel frattempo non si può fare niente altro. Temporizzare con lunghi delay va bene solo nei programmi che devono compiere una e una sola operazione alla volta. Quando si devono eseguire almeno due compiti la logica va ripensata in altro modo. Ad esempio:
leggi stato pulsante A
SE diverso da stato precedente E stato attuale == HIGH:
attiva timer A // imposta una variabile a 1)
memorizza tempo inizio A // salva il valore letto con millis)
aggiorna variabile stato precedente = stato attuale
se timer A attivo:
se timeout: // se valore attuale millis - tempo inizio > periodo voluto
disattiva timer A // imposta variabile a 0
spegni LED A
altrimenti:
accendi LED A
ci sto provando da più di 2 ore ma senza risultati con i millis pulsante rilasciato si spegne n secondi dopo il rilascio
pulsante premuto blinka
ci sto perdendo la testa
Prova a postare lo sketch attuale.
posto lo sketch per 1 solo pulsante e led
const int pulsante = 8;
const int led = 2;
unsigned long tempoledacceso;
bool ledacceso;
void setup() {
pinMode(led, OUTPUT);
pinMode(pulsante, INPUT);
ledacceso = false;
}
void loop() {
if (digitalRead(pulsante) == HIGH) {
digitalWrite(led, HIGH);
ledacceso = true;
tempoledacceso = millis();
}
if (ledacceso)
if (millis() - tempoledacceso > 2000) {
digitalWrite(led, LOW);
ledacceso = false;
}
}
L'uso di millis è corretto. Il problema come detto prima è che testi il livello del pulsante (sempre HIGH finché premuto) e non la sua variazione (passaggio da LOW precedente a HIGH attuale), quindi il timer viene "avviato" ad ogni giro, e il tempo parte dal momento in cui si rilascia il pulsante.
si questo dopo tante prove ci sono arrivato ma non capisco come fare la variazione
La variabile 'onPress' va a 1 per un ciclo di loop nel momento in cui il pulsante viene premuto:
in = digitalRead(pulsante);
onPress = ((in == HIGH) && (inPrec == LOW));
inPrec = in;
Abbreviabile in:
in = digitalRead(pulsante);
onPress = in && !inPrec;
inPrec = in;
grazie per i tuoi consigli ma non so proprio cosa devo fare
non ho le basi per capire certe programmazioni
è da stamattina che sono sopra sto sketch senza ricavarne nulla
mi son proprio demoralizzato
ho utilizzato plc di diverse marche utilizzando ladder ma questo arduino ha una progammazione per me difficile da comprendere, specialmente se non si ha nessuna base
mi sto proprio demoralizzando
lampadina915:
ho utilizzato plc di diverse marche utilizzando ladder
Allora pensa in ladder 
| pulsante in |
|----] [----------------------( )------| in = digitalRead(pulsante);
| |
| in inPrec onPress |
|----] [-------]/[------------( )------| onPress = in & !inPrec;
| |
| in inPrec |
|----] [----------------------( )------| inPrec = in;
| |
| T1 |
| .-----. |
| onPress | | |
|----] [-----------------|Toff |-------| if (onPress) { T1 = 1; inizio = millis(); }
| | | | else if (millis()-inizio > 2000) { T1 = 0; }
| '-----' |
| |
| T1 led |
|----] [----------------------( )------| digitalWrite(led, T1);
| |
PS: non so in ladder come si indica esattamente un timer che si avvia con un impulso.
PS2: il bello di un linguaggio general purpose è che può essere usato per codificare qualsiasi tipo di logica (a contatti, a stati, ad algoritmo, misto di tutte ecc).
grazie Cludio vedrò di darmi da fare
sono riuscito a a fare questo. Non capisco la funzione del timer:
se metto il byte !in nel comando del timer è giusto che si fermi perchè rilasciando il pulsante si diseccita
ho creato allora una autoritenuta A quindi mettendo nel timer !A dovrebbe rimanere attivo.
Invece si comporta al contrario, si accende ma si spegne dopo aver rilasciato il pulsante
questo schema con autoritenuta
in T1 A
|----] [---------|-]/[-----------( )------|
| |
| A |
|----] [-----|
|
| A T1
|----] [-------------------------( )------|
|
|
|
| A led
|----] [-------------------------( )------|
lo sketch scritto che allego al mio caso dovrebbe andare bene in quanto si presuppone che fra pulsante premuto e pulsante rilasciato intercorra piu di T1
ora ho provato ad associare un buzzer ma questo non ne vuole proprio sapere di funzionare
#define pulsante 8 // pulsante
#define led 2 // led
#define buzzer 6 //buzzer
byte A = 0;
byte T1 = 0;
uint32_t t1 = 0;
void setup()
{
Serial.begin (9600);
pinMode(pulsante, INPUT);
pinMode(led, OUTPUT);
pinMode(buzzer, OUTPUT);
digitalWrite (pulsante, LOW);
digitalWrite (led, LOW);
digitalWrite (buzzer, LOW);
}
void loop(){
byte in = digitalRead(pulsante);
A = (in | A ) & !T1 ;
// Accendo il led
digitalWrite(led, A );
//digitalWrite(buzzer, A );
//tone (buzzer,3500,1000);
// --------------------------------------------------------------------------------------
// ritardo all'eccitazione
// pulsante premuto si accende immediatamente il led e si spegne dopo il tempo
// se il pulsante viene rilasciato prima del tempo il timer si blocca e non spegne il led
T1 = 0;
if (!in )
{
t1 = millis();
}
else if (millis() - t1 >= 1500) T1 = 1;
// --------------------------------------------------------------------------------------
}
lampadina915:
quindi mettendo nel timer !A dovrebbe rimanere attivo.
Hai scritto un timer tipo Ton (ritardo in attivazione) quasi giusto, l'azzeramento di T1 però va sotto condizione:
if (!A) { T1 = 0; t1 = millis(); } else if (millis() - t1 >= 1500) T1 = 1;
Quello che avevo scritto io è un timer Toff (ritardo in disattivazione) retriggerabile:
if (A) { T1 = 1; t1 = millis(); } else if (millis() - t1 >= 1500) T1 = 0;
Se si vuole un Toff non retriggerabile (ma che comunque si riattiva se alla fine del periodo A vale ancora 1):
if (A & !T1) { T1 = 1; t1 = millis(); } else if (millis() - t1 >= 1500) T1 = 0;
Per non farli riavviare, i Toff basta comandarli con una variabile/coil/condizione impulsiva (come la 'onPress' del post #10).
ho provato ad associare un buzzer ma questo non ne vuole proprio sapere di funzionare
Cosa dovrebbe fare? Un beep alla partenza? Mi sembra che la soluzione più semplice sia avviare tone con una condizione impulsiva:
| A B .------. |
|----] [--------]/[------|buzzer|------| if (A & !B) tone(buzzer,3500,1000); // beep avvio
| '------' |
| |
| A B |
|----] [----------------------( )------| B = A;
| |
chiaro quello che hai scritto
non capisco comunque perchè lo sketch che ho scritto io con temporizzatore
T1 = 0; if (!in ) { t1 = millis(); } else if (millis() - t1 >= 1500) T1 = 1;
se tengo premuto il pulsante funziona
se metto autoritenuta no
A = (in | A ) & !T1 ;
T1 = 0; if (!A ) { t1 = millis(); } else if (millis() - t1 >= 1500) T1 = 1;
in questo nel mio progetto va bene anche cosi ma in altre condizioni l' autoritenuta è fondamentale
ho provato anche il buzzer come dicevi ma non va
il suo scopo è di rimanere acceso per un tempo
ora voglio risolvere il problema della condizione del pulsante/autoritenuta per evitare eventuale anomalia in future installazioni, poi vedo anche per il buzzer
questo progetto lo voglio installare su una serranda.
Il suo lampeggiante di segnalazione inizia a lampeggiare 3 secondi prima che la serranda inizi a muoversi.
voglio aggiungerci un cicalino per far capire che la serranda inizierà a muoversi
il led mi serve solo per capire lo sketch, nella realtà poi non servira ma ora per me utile a capire il funzionamento
sicuramente se acquistavo un temporizzatore avevo già risolto il problema senza perderci tanto tempo, ma dopo 2 giorni che ci perdo la testa devo continuare
grazie Claudio del tuo aiuto
ho creato queste condizioni, naturalmente con PULSANTE PREMUTO perchè la ritenuta non mi funziona
A= (in | A) & !T1 ;
B = (A);
digitalWrite(ledprova, A ); // Il led si accende e si spegne dopo T1
if ( A & !B ) tone (buzzer,3500,1000 ); il buzzer suona e smette 1 secondo dopo aver rilasciato il pulsante
T1 = 0;
if (!in )
{
t1 = millis();
}
else if (millis() - t1 >= 1000) T1 = 1;
eccomi di nuovo
il buzzer non riesco proprio a farlo funzionare
ho eliminato la ritenuta di A in quanto il segnale che arriva dalla centrale allarme è continuo quindi inutile
il led prova è solo per prova
il buzzer o suona sempre o non suona
allego sketck
A= in & !T1 ;
digitalWrite(ledprova, A ); // Accendo il led solo per verificare che il buzzer segue il led e che lo sketch funzioni
// poi verra eliminato
tone ( buzzer, 3500 );
T1 = 0;
if (!in )
{
t1 = millis();
}
else if (millis() - t1 >= 2000) T1 = 1;
}
Come già detto nel post #13, e ripetuto nel #16, l'azzeramento di T1 va sotto condizione, altrimenti ti ritrovi con 'A' che può andare alta per due secondi ogni 1193 ore (il massimo tempo gestibile direttamente con millis).
Poi tone, essendo un processo che va avanti per i fatti suoi, va attivato e disattivato su condizione, non attivato sempre, quindi se vogliamo che suoni solo quando 'A' è alta bisogna rilevare i momenti di salita o discesa di 'A'
| A B .----------. |
|----] [-----]/[------|buzzer on |------| if (A & !B) { tone(buzzer, 3500); }
| '----------' |
| A B .----------. |
|----]/[-----] [------|buzzer off|------| if (!A & B) { noTone(buzzer); }
| '----------' |
| A B |
|----] [-------------------------( )----| B = A;
O in alternativa, se vuoi che faccia solo un beep quando 'A' diventa alta, e si fermi da solo dopo un certo tempo indipendentemente da tutto il resto:
| A B .----------. |
|----] [-----]/[------|buzzer on |------| if (A & !B) { tone(buzzer, 3500, 500); } // beep avvio 0,5s
| '----------' |
| A B |
|----] [-------------------------( )----| B = A;