PulseIn
PulseIn e’ il modo piu’ semplice per decodificare un canale PWM in ingresso, puo’ lavorare su qualunque PIN che possa essere utilizzato come INPUT. Il problema e’ che la funzione e’ blocking: mentre viene misurata la lunghezza dell’intervallo il processore non puo’ fare altro.
Quindi possiamo anticipare un blocco di circa 1.5ms (media tra il minimo di 1ms e il massimo di 2ms) ogni 20ms (se la TX manda un impulso a ~50Hz, la FRSky che sto utilizzando ha un periodo di 18ms ma puo’ essere impostata anche a 8ms).
Questo puo’ non avere un grosso effetto su dei lampeggi da 500ms ma e’ influente su dei FADE o ovviamente la lettura di altri eventuali INPUT! Una soluzione potrebbe essere di lanciare la lettura con una frequenza minore, ad es. 5 volte al sec puo’ essere adeguato per leggere un interruttore, vedi esempio di pulseIn con millis.
Soluzione migliore: utilizzare gli interrupts.
Lettura di un canale
/* Lettura di un canale servo della RX
Lettura tramite la funzione pulsein
Utilizzabile su qualunque PIN
Il codice e' blocking fin tanto che il segnale passa da RISE a FALL
quindi blocca per 1-2ms a ogni esecuzione.
Il segnale dalla rx dovrebbe essere ~50hz,
vedere questo sketch $_millis con lettura a intervalli programmabili.
*/
#include <common.h>
// Variabili
const byte chPin = 2; // PIN su cui e' collegato il canale
unsigned int chIn = 1500; // Valore catturato
unsigned int chValue = 1500; // Valore computato
// Attenzione che pulsein e' blocking
// Variabili per autocalibrazione
int mid_point = 1500;
void setup() {
// Funzione relativa a calibrazione:
mid_point = calibraTrim(chPin) ;
Serial.begin(9600); // Warning: interrupts e serial potrebbero dare problemi
};
void loop() {
// Lettura canale
chIn = pulseIn(chPin, HIGH, 25000);
if (chIn > 1000 && chIn <2000) {
// Scartiamo valori fuori range, talvolta pero' alcune RX
// hanno il minimo un po' sotto a 1000
chValue = chIn;
};
// do something with chValue
Serial.print(chIn);
Serial.print(" > chValue= ");
Serial.print(chValue);
Serial.print(" - base: ");
Serial.println(mid_point);
delay(200);
}
Lettura di un canale con millis
/* Lettura di un canale servo della RX
Lettura tramite la funzione pulsein
Utilizzabile su qualunque PIN
Il codice e' blocking fin tanto che il segnale passa da RISE a FALL
quindi blocca per 1-2ms a ogni esecuzione. Con la variabile freq
si imposta ogni quanto fare una lettura.
*/
#define DEBUG
#include <common.h>
unsigned long currentMillis; // timestamp reference per millis per tutto il loop
// Variabili
const byte chPin = 2; // PIN su cui e' collegato il canale
long unsigned chStamp = 0; // Timestamp per
unsigned int chIn = 1500; // Valore catturato
unsigned int chValue = 1500; // Valore computato
unsigned int freq = 200 ; // Ogni quanti millisecondi leggere il valore
int mid_point = 1500; // Punto medio per calibrazione
// Attenzione che pulsein e' blocking
void setup() {
// Funzione relativa a calibrazione: per il throttle si puo' evitare
mid_point = calibraTrim(chPin) ;
#ifdef DEBUG
Serial.begin(9600); // Warning: interrupts e serial potrebbero dare problemi
#endif
} ;
void loop() {
currentMillis = millis(); // Timestamp per tutto il loop
// Lettura ailerons channel ogni 200ms
if (currentMillis - chStamp >= freq) {
chIn = pulseIn(chPin, HIGH, 25000);
if (chIn != 0 && chIn > 1000 && chIn <2000) {
// get only resonable values
chValue = chIn;
chStamp = currentMillis ;
} ;
};
// do something with chValue
#ifdef DEBUG
Serial.print(chValue);
Serial.print(" - base: ");
Serial.println(mid_point);
delay(200);
#endif
}