l'interrupt change, modificando i registri a basso livello o con librerie esterne, lo puoi usare su qualsiasi pin.
Io ti consiglio di usare però la funzione attachInterrupt() che come hai visto ti obbliga all'uso dei pin 2 e/o 3, però la userei sul RAISNG o sul FALLING per il motivo che se la usi sul CHANGE, rilevi sia accensione che spegnimeto, cosa inutile.
con il RISING, conteresti le accensioni del led (ok), però è probabile che ti ritrovi l'effetto "rimbalzo"; nel loop() lo hai aggirato con il delay, ma con gli interrupt non puoi. Però puoi usare la millis(), che però è "congelata", overo all'interno dell'interrupt NON cambia valore.
Quindi all'interrupt prendi il valore di una variabile ad esempio old_millis, e la confronti con il valore della millis(); se la differenza è > 10, allora incrementi una variabile (di tipo "volatile byte", il volatile è perchè è usata sia dal loop che dall'interrupt) di uno, e alla fine assegni ad old_millis il valore di millis attuale, in modo da avere un "antirimbalzo" di 10 ms
nel loop leggi il valore della variabile volatile e la assegni ad una variabile temporanea, e azzeri la volatile.
Ora nella temporanea hai il numero di lampeggi (da 0 a 255), e salvi il valore su SD e/o su database come hai sempre fatto.
Ahhahah non lo conoscevo questo acronimo usato nell'informatica che sta per Keep It Simple, Stupid, ossia "rimani sul semplice, stupido"
allora kiss kiss a tutti
grazie lesto... ho trovato questo esempio di interrupt.. da qui posso iniziare a capirci qualcosa...
volatile double contatore =0; // Totale degli impulsi: volatile perche deve essere forzata in memoria e non nei registri della cpu.
// scatta solo quando su PD2 (INT0) sale il fronte dell'onda quadra
void customISR()
{
contatore++;
}
void setup()
{
// bit banging sul pin 13 (led interno dell'arduino)
pinMode(13, OUTPUT);
//nuova impostazione interrupt per usare INT0 sul fronte di salita
attachInterrupt(0, customISR, RISING); //aggancia INT0 alla ISR "customISR" )
// initialize inputs/outputs
// start serial port
Serial.begin(9600);
}
void loop()
{
digitalWrite(13, HIGH);
delay (20); // l'impulso dura 20 mS
digitalWrite(13, LOW);
delay (1000-20); //attende circa un secondo: simula lampeggio consumo 1 kW/h
Serial.print("Impulsi: ");
Serial.println(contatore);
}
Nell' esempio sopora ho testato lo sketch di esempio... ho fatto una prova collegando la fotoresistenza al pin digitale 2 con solita R da 10 K
questo il risultato... ho simulato degli impulsi.. ora dovrò capire come conteggiare correttamente
Con il codice postato sotto dovrei riuscire a monitorare in base al conteggio impulsi sia la potenza KW e l’ energia KWh.
Ho collegato la foto resistenza al pin digitale 3 per l’interrupt e ho provato a simulare degli impulsi. I valori da seriale sono alquanto strani, dov’è l’errore?
Se poi volessi contare gli impulsi ogni minuto da inviare con il get uso comunque sempre MsTimer2::set(timer, flushCounter); ?
Grazie
//Number of pulses, used to measure energy.
long pulseCount = 0;
//Used to measure power.
unsigned long pulseTime,lastTime;
//power and energy
double power, elapsedkWh;
//Number of pulses per wh - found or set on the meter.
int ppwh = 1; //1000 pulses/kwh = 1 pulse per wh
void setup()
{
Serial.begin(115200);
// KWH interrupt attached to IRQ 1 = pin3
attachInterrupt(1, onPulse, FALLING);
}
void loop()
{
}
// The interrupt routine
void onPulse()
{
//used to measure time between pulses.
lastTime = pulseTime;
pulseTime = micros();
//pulseCounter
pulseCount++;
//Calculate power
power = (3600000000.0 / (pulseTime - lastTime))/ppwh;
//Find kwh elapsed
elapsedkWh = (1.0*pulseCount/(ppwh*1000)); //multiply by 1000 to pulses per wh to kwh convert wh to kwh
//Print the values.
Serial.print(power,4);
Serial.print(" ");
Serial.println(elapsedkWh,3);
}
NON USARE LA SERIAL, DELAY O ALTRE FUNZIONI CHE RALLENTANO L?ESECUZIONE ALL'INTERNO DELLE FUNZIONI DI INTERRUPT!
nell'uinterrupt setti delle varibili che poi stampi/elabori nel loop (ricordati che le variabili usate sia dagli interrupt che dal loop DEVONO essere dichiarate ateponendo "volatile", per una questione di come viene gestita la ram (se ti interessa avere più particolari... google!)
La configurazione per collegare la fotoresistenza al pin digitale da sfruttare per l'interrupt è corretta? Utilizzo un condensatore ceramico da 0,1 uF Allego l'immagine
Grazie
Ciao, mi sapete dire se questo fototransistor è adatto per rilevare gli impulsi?
Modello TSL257
Converts Light Intensity to Output Voltage
Monolithic Silicon IC Containing
Photodiode, Operational Amplifier, and
Feedback Components
High Sensitivity
Single Voltage Supply Operation (2.7 V to
5.5 V)
Low Noise (200 ?Vrms Typ to 1 kHz)
Rail-to-Rail Output
High Power-Supply Rejection (35 dB at
1 kHz)
Compact 3-Leaded Plastic Package
RoHS Compliant (?LF Package Only)
ankamacha:
Ciao, mi sapete dire se questo fototransistor è adatto per rilevare gli impulsi?
Modello TSL257
Gli impulsi sono dei lampeggi di un led rosso quindi siamo sui 620–750 nm, il fototransistor ha un picco di sensibilità proprio su queste lunghezze d'onda ma è anche vero che rileva tutto lo spettro luminoso e gli infrarossi e debolmente gli ultravioletti.
In poche parole non può "distinguere" la luce rossa ed inevitabilmente, come le fotoresistenze, è sensibile a qualsiasi luce ambientale
Domanda: perché vuoi utilizzare un fototransistor? Il lampeggio del contatore non è così rapido da richiedere per forza questo componente
Chi mi aiuta a gestire l'antirimbalzo? Non ho capito bene come fare
Non ti serve gestire l'antirimbalzo come per i pulsanti, al limite per evitare doppie letture dovresti verificare se sono passati almeno N millisecondi dove N è la durata di un lampeggio
mi han consigliato questo modello TSL257 per la gestione dei lampeggi da interrupt... tra qualche giorno mi arriva faccio dei test e vi faccio sapere se funziona o meno. avevo provato a contare gli impulsi con una semplice fotoresistenza ma mi da dei valori di conteggio sballati. non credo sia il componente ideale da collegare su un ingresso digitale, cosa ne pensate?
grazie lesto per le dritte, dopo tanti test finalmente son riuscito a metter giù sto benedetto programmino
Se hai le condizioni luminose costanti (es. il contatore è al chiuso in una cassetta), la fotoresistenza ben piazzata sui led ed isolata ai lati, una soglia ed uno sketch corretto dovrebbe funzionare tutto senza problemi.
In genere il problema è la fotoresistenza non centrata sul led e non isolata (otticamente parlando)
Un ingresso digitale con un LDR richiede un transistor per poter convertire in un valore HIGH/LOW il lampeggio del led ma anche qui ci possono essere delle insidie se la soglia (impostata con un potenziometro) non è corretta, si potrebbero avere dei valori intermedi tra HIGH e LOW che possono essere interpretati incertamente dal micro.
In alternativa puoi utilizzare il comparatore analogico dell' ATMega assieme agli interrupt se non vuoi utilizzare il transistor o puoi usare l'ADC invece dei pin digitali.
Col TSL257 hai comunque in uscita, dopo aver messo un'amplificatore operazionale in configurazione convertitore corrente-tensione, una tensione che devi discriminare ad esempio con un transistor (o con un altro operazionale se ne hai più nello stesso package) se vuoi utilizzare un ingresso digitale per lo stesso discorso di prima.
Nel codice che hai postato hai la variabile volatile "state" ma "conta" non volatile.. è voluta come cosa?
lesto:
Io ti consiglio di usare però la funzione attachInterrupt() che come hai visto ti obbliga all'uso dei pin 2 e/o 3, però la userei sul RAISNG o sul FALLING per il motivo che se la usi sul CHANGE, rilevi sia accensione che spegnimeto, cosa inutile.
con il RISING, conteresti le accensioni del led (ok), però è probabile che ti ritrovi l'effetto "rimbalzo"...
E perchè mai dovrebbe avere problemi di rimbalzo se conta i RISING o i FALLING ??
Il fototransistor/fotodiodo è sempre un componente ottico, non magnetico/meccanico , non lo vedo molto soggetto a disturbi.
Mi sfugge qualcosa?
il problema è che lo usi come ricevitore, e la sua uscita non è HIGH o LOW ma un valore nel mezzo. Si sta comportando da "pannello solare" e quindi la potenza generata è molto variabile in base alle condizioni, come temperatura e umidità.. questo può creare un valore intorno ai 3V, che è la soglia dell'HIGH logico, quidi arduino ogni tanto legge 1 e ogni tanto 0 (anche quì in base a vari fattori), generando un bounce
c'erto è un avvenimento raro e dovrebbe bastare quello detto da flz
Se hai le condizioni luminose costanti (es. il contatore è al chiuso in una cassetta), la fotoresistenza ben piazzata sui led ed isolata ai lati, una soglia ed uno sketch corretto dovrebbe funzionare tutto senza problemi.
però sarebbe interessante contare gli eventuali bounce rilevati e vedere se davvero è così
Nel codice che hai postato hai la variabile volatile "state" ma "conta" non volatile.. è voluta come cosa?