Ciao ragazzi, vi scrivo perchè ho un piccolo domanda/problema.
Ho un circuito che, oltre ad altre cose, gestisce 8 ventole pc con controllo velocità tramite pwm della ventola, accensione e lettura del numero di giri di ognuna.
Appunto è nella lettura del numero di giri delle ventole che vorrei migliorare. Il codice che uso è questo (ha ancora molte cose per il debug):
long readPulse(uint8_t fanteca1) {
unsigned long timeout;
boolean salta;
unsigned long pulseDuration;
unsigned long rpmfan;
unsigned long time;
rpmfan=0;
salta=false;
timeout=micros();
while (digitalRead(fanteca1) == LOW ){
if (micros() >= (timeout+100000)) {
salta=true;
rpmfan=0;
Serial.println("salta1");
break;
}
continue;//wait to be LOW
}
timeout=micros();
while (digitalRead(fanteca1) == HIGH ){
if (micros() >= (timeout+100000)) {
salta=true;
rpmfan=0;
Serial.println("salta2");
break;
}
continue;//wait to be HIGH
}
timeout=micros();
time=micros();
while (digitalRead(fanteca1) == LOW ){
if (micros() >= (timeout+100000)) {
salta=true;
rpmfan=0;
Serial.println("salta3");
break;
}
continue;//wait to be LOW
}
if ( salta==false) {
Serial.println("calcolo");
pulseDuration = micros()-time;
double frequency = 1000000.0/pulseDuration;
rpmfan=(frequency/2*60);
}
else {
rpmfan = 0;
}
return rpmfan;
}
Il problema è che quando le ventole sono spente, o anche solo alcune, il ciclo del loop del programma diventa troppo lungo (nell' ordine di 2-3 secondi)
Purtroppo io ho delle funzioni nel mio progetto che richiedono tempi molto minori. Come ad esempio delle azioni fatte eseguire da un telecomando.
La domanda è: Non è che c'è un modo di leggere i numero di giri delle ventole tramite hardware e non software e poi magari passare i valori tramite ad esempio i2c o altro? Oppure tramite un secondo atmel standalone, oppure tramite interrupt, ma non penso di averne a disposizione 8 per gestirli nei pin. E anche se fosse, il codice che ho testato negli interrupt presuppone comunque un delay.
In poche parole, vi chiedo un consiglio per poter slegare la procedura principale dalla routine di lettura e così avere un codice snello senza tempi lunghi.
Si.. infatti come ho scritto, posso usare degli interrupt ma comunque anche per questi devo fare dei delay all' interno per contare i cambi in HIGH e LOW.
Inoltre.. nel mega ci sono 8 interrupt che posso gestire ?
leggiti come funziona la storia del "multitasking" con arduino ovvero l'utilizzo della funzione millis();
inoltre giusto per correttezza ti dico che il double in arduino in raltà non esiste, evitane l'utilizzo..
EDIT:
la mega ha 6 interrupt esterni, si possono attivare non solo quando passa da high a low o viceversa ma anche al change ovvero che si attiva in entrambi i casi per intenderci, quindi con una lettura sei a posto
superzaffo:
Si.. infatti come ho scritto, posso usare degli interrupt ma comunque anche per questi devo fare dei delay all' interno per contare i cambi in HIGH e LOW.
Inoltre.. nel mega ci sono 8 interrupt che posso gestire ?
grazie
no! niente delay egli interrupt! un interrupt viene generato al cambio stato del pin, quindi non solo niente delay, ma sei sicuro di non mancare neanche un colpo
l'interrupt incrementa una variabile, che poi leggi dal loop usando un sistema stile blink without delay
Grazie a tutti e due per le risposte. @Superlol: Si so come funziona il millis() provo buttar giù qualche cosa. Comunque se guardi nella rete trovi già qualche cosa con l' uso degli interrupt ma usano il delay.
Il problema è che io avrei bisogno di 8 interrupt
@Lesto:Ok.. penso che anche tu proponi una cosa come Superlol. Rimane il problema del numero degli interrupt. So che oltre i 6 esterni si possono usare anche altri, ma non so se può essere la stessa cosa.
Ma non è che ci possa essere una soluzione hw con qualche chip che intercetta lui il cambio di stato con un incremento ? (magari ho detto una stronzata)
tutti i pin possono avere interrupt, se usati a basso livello, la differenza è che a basso livello haisolo l'interrupt change, mentrequello "precotti" posso scremare "RISING" e "LOWERING"... cosa che comunque puoi imitare via software avendo l'interrupt di cambio stato.
edit: se il chip intercetta, poi come fai a sapere su che pin? puoi usare un mux e quindi leggere un ingresso alla volta..
superzaffo:
Rimane il problema del numero degli interrupt. So che oltre i 6 esterni si possono usare anche altri, ma non so se può essere la stessa cosa.
Gli interrupt a cui penso ti riferisca tu sono i PCINT, che però vengono "sentiti" per porta, quindi quando sui pin di una stessa porta sono attivi 2 PCINT e su quei pin arrivano contemporaneamente i segnali, si attiva comunque un solo flag.
Per risolvere più interrupt bisogna lavorare un pò a livello software.
La libreria PinChangeInt cerca di fare questo. Non mi ricordo quanti interrupt riesce a gestire contemporaneamente, ma puoi fare dei test. https://code.google.com/p/arduino-pinchangeint/
Grazie leo, darò subito un occhiata. @Lesto: Bhè certo il mux potrebbe essere un idea... sinceramente mi basterebbe avere il tempo di un paio di cambi per fare poi dei calcoli per trovare poi rpm.
Per cui forse anche a basso livello potrei provare... altrimenti al massimo vado con un stand alone in + dedicato.