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

}