2013-03-27 10 views
5

Sto scrivendo una semplice libreria per un sensore di distanza a ultrasuoni e ho pensato di provare a utilizzare gli interrupt.Impossibile usare attachInterrupt in una libreria

Tuttavia, non è possibile impostare correttamente le mie funzioni nel metodo attachCallback.

Voglio HCSR04Interrupt::echoHigh() e HCSR04Interrupt::echoLow() chiamato quando il pin va alto e basso rispettivamente.

Ho cercato su Google senza successo. L'Ardiuno IDE dice il seguente:

./Arduino/libraries/HCSR04/HCSR04Interrupt.cpp: In member function 'void HCSR04Interrupt::getDistance()': 
./Arduino/libraries/HCSR04/HCSR04Interrupt.cpp:31: error: argument of type 'void (HCSR04Interrupt::)()' does not match 'void (*)()' 
./Arduino/libraries/HCSR04/HCSR04Interrupt.cpp: In member function 'void HCSR04Interrupt::echoHigh()': 
./Arduino/libraries/HCSR04/HCSR04Interrupt.cpp:47: error: argument of type 'void (HCSR04Interrupt::)()' does not match 'void (*)()' 

Qui è la mia intestazione:

#ifndef _HCSR04Interrupt_ 
#define _HCSR04Interrupt_ 

#include "Arduino.h" 

#define HCSR04_CM_FACTOR 58.0 
#define HCSR04_IN_FACTOR 148.0 
#define HCSR04_CM_MODE 0 
#define HCSR04_IN_MODE 1 

class HCSR04Interrupt { 
    public: 
    double distance; 

    HCSR04Interrupt(int trigger_pin, int echo_pin, void (*callback)()); 

    void setUnits(int units); 

    void getDistance(); 
    private: 
    int _trigger_pin; 
    int _echo_pin; 
    int _units; 
    unsigned long _micros_start; 
    void (*_callback)(); 

    void initialize(); 
    void echoHigh(); 
    void echoLow(); 
}; 

#endif 

E la mia realizzazione (non completa in quanto non posso andare oltre la fase attachInterrupt):

#include "Arduino.h" 
#include "HCSR04Interrupt.h" 

HCSR04Interrupt::HCSR04Interrupt(int trigger_pin, int echo_pin, void (*callback)()) { 
    _trigger_pin = trigger_pin; 
    _echo_pin = echo_pin; 
    _callback = callback; 

    initialize(); 
} 

void HCSR04Interrupt::setUnits(int units) { 
    _units = units; 
} 

void HCSR04Interrupt::initialize() { 
    pinMode(_trigger_pin, OUTPUT); 
    pinMode(_echo_pin, INPUT); 

    digitalWrite(_trigger_pin, LOW); 
} 

void HCSR04Interrupt::getDistance() { 
    //Listen for the RISING interrupt 
    attachInterrupt(_echo_pin - 2, echoHigh, RISING); 

    //The trigger pin should be pulled high, 
    digitalWrite(_trigger_pin, HIGH); 

    //for 10 us. 
    delayMicroseconds(20); 

    //Then reset it. 
    digitalWrite(_trigger_pin, LOW); 
} 

void HCSR04Interrupt::echoHigh() { 
    _micros_start = micros(); 

    detachInterrupt(_echo_pin - 2); 
    attachInterrupt(_echo_pin - 2, echoLow, FALLING); 
} 

void HCSR04Interrupt::echoLow() { 
    detachInterrupt(_echo_pin - 2); 

    unsigned long us = micros() - _micros_start; 

    distance = us; 

    (*_callback)(); 
} 

risposta

2

Arduino i gestori di interrupt possono essere solo funzioni. Si sta tentando di rendere il metodo di un oggetto un gestore di interruzioni. Quindi il compilatore si lamenta.

Per essere più precisi su di esso, i metodi dell'oggetto sono come le funzioni, ma è come se prendessero un parametro "nascosto", che specifica l'istanza dell'oggetto. Pertanto, in realtà hanno diverse firme di tipo da semplici funzioni. Ciò non consente di passare un puntatore al metodo quando ciò che una funzione sta cercando è un puntatore a funzione semplice.

La soluzione è spostare i numeri echoHigh() e echoLow() fuori dalla classe HCSR04Interrupt e renderli semplici funzioni.

5

Così il compilatore (non l'IDE) ti dice esattamente ciò che è sbagliato:

argument of type 'void (HCSR04Interrupt::)()' does not match 'void (*)() 

Così, mentre attachInterrupt() prende un puntatore a funzione di tipo void (*)(), si sta cercando di passare un non funzione membro statico, che non è possibile. Si può provare a fare la funzione di membro static e casting:

static void echoHigh(); 

// ... 

attachInterrupt(_echo_pin - 2, reinterpret_cast<void (*)()>(&echoHigh), RISING); 
+0

attachInterrupt ha requisiti che la funzione a cui punta essere STATICO. e questo fa sì che tutte le funzioni membro verso l'alto di attachInterrupt siano statiche. L'ho fatto, con successo. – mpflaga

0

ho avuto intorno a questo facendo una classe singleton di base che rappresenta l'hardware nel suo complesso (che fa un pò senso in questa situazione in ogni caso).

Eventuali puntatori di funzione possono essere passati alla classe del sottocomponente e gestiti dal singleton, le cui variabili membro e metodi sono tutti statici.

intestazioni Esempio (non testati):

// Sub-component 
class LampButton { 
public: 
    LampButton(int pin, void(*pushHandler)()); 
} 

// Sub-component 
class LampLed { 
public: 
    LampLed(int pin); 
    void toggle(); 
} 

// Singleton represents the hardware in it's entirety 
class Lamp { 
public: 
    // Call this instead of a constructor 
    static void initialize(int buttonPin, int ledPin); 

    // Function implemented inline for clarity - don't do this 
    static void handleButtonPush() { 
     led.toggle(); 
    } 

private: 
    static LampButton button; 
    static LampLed led; 
} 
1

Come mi sono imbattuto su questa domanda e non ha avuto una risposta accettata, scrivo quello che ho trovato, che ha lavorato per me:

L'interrupt deve essere chiamato da un wrapper globale. Questo wrapper deve chiamare una funzione handleInterupt della classe. Quindi deve conoscere la classe. Questo può essere fatto memorizzandolo in una variabile globale. Se devono essere utilizzate più istanze della classe, è necessario utilizzare più variabili globali.Ma, come i perni di interrupt sono solo alcuni si può scrivere una variabile globale e funzione di ogni pin:

MyClass theInstance_pin3 = NULL; 
MyClass theInstance_pin7 = NULL; 

// Somewhere, fill in an initialized copy of MyClass, 
// and set theInstance_pin3 or theInstance_pin7 to it 

void ISR_3() 
{ 
    if (theInstance_pin3) 
     theInstance_pin3->handleInterrupt(); 
} 
void ISR_7() 
{ 
    if (theInstance_pin7) 
     theInstance_pin7->handleInterrupt(); 
} 

come un vedere riferimento: http://forum.arduino.cc/index.php?topic=41713.0 o http://forum.arduino.cc/index.php?topic=160101.0

Problemi correlati