2013-03-27 6 views
5

私は超音波距離センサー用の簡単なライブラリを作成しています。私は割り込みを使用しようと考えていました。ライブラリでattachInterruptを使用できません

しかし私はattachCallbackメソッドで自分の機能を正しく設定できません。

ピンがハイとローになるとそれぞれHCSR04Interrupt::echoHigh()HCSR04Interrupt::echoLow()が呼び出されます。

私はこれを無駄にしました。 Ardiuno IDEは、次の言葉:ここ

./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 (*)()' 

は私のヘッダーです:

#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 

そして、私の実装(私は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)(); 
} 

答えて

2

のArduino割り込みハンドラは関数でなければなりません。オブジェクトのメソッドを割り込みハンドラにしようとしています。したがって、コンパイラは不平を言う。

もっと正確に言うと、オブジェクトメソッドは関数に似ていますが、オブジェクトインスタンスを指定する「隠し」パラメータを取るかのようです。したがって、実際にはプレーン関数とは異なる型シグニチャがあります。これは、関数が探しているものがプレーン関数ポインタであるときにメソッドポインタを渡すことを禁止します。

HCSR04InterruptクラスからechoHigh()echoLow()を移動し、それらをプレーンな機能にすることです。

5

のでコンパイラ(ないIDE)が間違っている正確に何を説明します:だから

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

attachInterrupt()はタイプvoid (*)()の関数ポインタをとりながら、あなたはそれを非を渡すためにしようとしています静的メンバー関数できません。あなたは、メンバ関数staticと鋳造を作ってみることができます。

static void echoHigh(); 

// ... 

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

attachInterrupt機能は、それがあることを指すの要件があります静的。その後、すべてのメンバ関数がattachInterruptから上に静的になります。私はこれを成功裏に終えました。 – mpflaga

0

私は(ちょっと、とにかくこのような状況では意味があります)全体としてのハードウェアを表しsingleton基本クラスを作ることによってこの問題を回避ました。

任意の関数ポインタをサブコンポーネントクラスに渡し、メンバ変数とメソッドがすべて静的であるシングルトンによって処理することができます。

例ヘッダ(未テスト):

// 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

私はこの質問につまずいたし、それが受け入れ答えを持っていないとして、私は私のために働いている、見つけたものを書く:

割り込みグローバルラッパーによって呼び出される必要があります。このラッパーはクラスのhandleInterupt関数を呼び出す必要があります。したがって、クラスを知っている必要があります。これはグローバル変数に格納することで可能です。クラスの複数のインスタンスを使用する必要がある場合は、そのようなグローバル変数を複数使用する必要があります。参考見るよう

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(); 
} 

:しかし、割り込みピンはわずか数あるとして、あなたはすべてのピンのためのグローバル変数や関数を書くことができますhttp://forum.arduino.cc/index.php?topic=41713.0 またはhttp://forum.arduino.cc/index.php?topic=160101.0