2016-05-24 16 views
0

Ich habe eine Bibliothek MotorIR, die NECIRrcv verwendet, um den IR-Code von einem Sensor zu extrahieren. Zunächst habe ich versucht, es mit zwei Bibliotheken zu tun, aber das scheint nicht so einfach zu sein, wie ich lese, also entscheide ich mich, sowohl die Kopfzeile und die Quelldatei von NECIRrcv in meine Arduino-Bibliothek MotorIR aufzunehmen.Mehrere Klassen in mehreren Dateien - C++/Arduino

Ich habe Probleme mit der Definition NECIRrcv sensor in MotorIR. Wenn ich es mache, wo es im Code platziert wird, ist kein Signal verfügbar (while(sensor.available()) wird nie eingegeben).

Ich kann verstehen, dass das logisch ist, da es Sensor jedes Mal neu definiert, wenn ich motorIR::control() rufe. Mein echtes Problem ist, dass Ich habe keine Ahnung, wo ich sensor, das Objekt der Klasse NECIRrcv, in motorIR erklären sollte.

Ich habe ein wenig Nachforschungen darüber gemacht, und da ich vorher nicht mit externen Klassen gearbeitet habe, bin ich noch mehr verwirrt darüber, wenn man einen benutzt, ist es notwendig.

Ich wäre sehr dankbar, wenn jemand ein paar Minuten investieren könnte, die mir bei diesem Thema helfen. Hoffe, du kannst meine Erklärungen verstehen.

Hier sind Sie die verschiedenen Dateien:

Datei motorIR.h

#ifndef motorIR_h 
#define motorIR_h 

#include "Arduino.h" 
#include "NECIRrcv.h" 


#define STANDBY 999 
#define inputIR 2 

#define PWM_1 3 
#define MI_1 4 
#define MD_1 5 

#define PWM_2 6 
#define MI_2 7 
#define MD_2 8 

#define FORWARD 
#define BACKWARD 

class motorIR 
{ 
public:  // Funciones públicas 

    motorIR(int pPWM_1, int pMI_1, int pMD_1, int pPWM_2, int pMI_2, int pMD_2); 

    void setMotor(int PWM, int MI, int MD); 

    void begin(); 

    void control(); 

    void translate(); 

    void serialPrint(); 

private: // Variables privadas 
    int _PWM= STANDBY; 
    int _MI; 
    int _MD; 
    unsigned long _IRcode; 


    // static NECIRrcv & getSensor() // <--- getSensor() added 
    // { 
     // static NECIRrcv sensor(4); 

     // return sensor; 
    // } 
    // static NECIRrcv & getSensor() 
// { 
    // static NECIRrcv sensor(4); 
    // static bool firstRun(true); 

    // if (firstRun) 
    // { 
     // sensor.begin(); 
     // firstRun = false; 
    // } 

    // return sensor; 
// } 
}; 

#endif 

Datei motorIR.cpp

#include "Arduino.h" 
#include "motorIR.h" 
#include <string.h> 

motorIR::motorIR(int PWM, int MI, int MD)  // Constructor 
{ 
    _MI= MI  +A0; 
    _PWM= PWM  +A0; 
    _MD= MD  +A0; 
} 

void motorIR::beginner() 
{ 
    Serial.begin(9600); 
    Serial.print("Begin"); 
} 


void motorIR::control(int i) 
{ 
    NECIRrcv sensor(4) ;  // I doesn't work as expected if placed here 
    sensor.begin(); 

    Serial.println("Checkpoint");  
    while (sensor.available()) 
    { 
     Serial.print("Detection"); 
     IRcode= sensor.read(); 
     Serial.print(IRcode, DEC); 
     Serial.print(IRcode, HEX); 
     Serial.print(IRcode, BIN); 
    } 
} 

Datei NECIRrcv.h (gegeben)

#ifndef NECIRrcv_h 
#define NECIRrcv_h 

#include <Arduino.h> 
#include "motorIR.h" 

#define USECPERTICK 50 // microseconds per clock interrupt tick 
#define CLKFUDGE 5  // fudge factor for clock interrupt overhead 
#define CLKMAX 256  // max value for clock (timer 2) 
#define PRESCALE 8  // timer2 clock prescale 
#define SYSCLOCK 16000000 // main Arduino clock 
#define CLKSPERUSEC (SYSCLOCK/PRESCALE/1000000) // timer clocks per microsecond 

#define MAXBUF 8  // IR command code buffer length (circular buffer) 

// IR detector output is active low 
#define MARK 0 
#define SPACE 1 

#define NBITS 32   // bits in IR code 

#define BLINKLED 13 

// defines for setting and clearing register bits 
#ifndef cbi 
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 
#endif 
#ifndef sbi 
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) 
#endif 

// clock timer reset value 
#define INIT_TIMER_COUNT2 (CLKMAX - USECPERTICK*CLKSPERUSEC + CLKFUDGE) 
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT2 

// pulse parameters -- nominal usec 
#define STARTNOM  9000 
#define SPACENOM  4500 
#define BITMARKNOM 620 
#define ONESPACENOM 1600 
#define ZEROSPACENOM 480 
#define RPTSPACENOM 2180 

#define TOLERANCE 20 // percent 
#define LTOL (1.0 - TOLERANCE/100.) 
#define UTOL (1.0 + TOLERANCE/100.) 

// pulse parameters (tick counts) 
#define STARTMIN (int)((STARTNOM/USECPERTICK)*LTOL) // start MARK 
#define STARTMAX (int)((STARTNOM/USECPERTICK)*UTOL) 
#define SPACEMIN (int)((SPACENOM/USECPERTICK)*LTOL) 
#define SPACEMAX (int)((SPACENOM/USECPERTICK)*UTOL) 
#define BITMARKMIN (int)((BITMARKNOM/USECPERTICK)*LTOL-2) // extra tolerance for low counts 
#define BITMARKMAX (int)((BITMARKNOM/USECPERTICK)*UTOL+2) 
#define ONESPACEMIN (int)((ONESPACENOM/USECPERTICK)*LTOL) 
#define ONESPACEMAX (int)((ONESPACENOM/USECPERTICK)*UTOL) 
#define ZEROSPACEMIN (int)((ZEROSPACENOM/USECPERTICK)*LTOL-2) 
#define ZEROSPACEMAX (int)((ZEROSPACENOM/USECPERTICK)*UTOL+2) 
#define RPTSPACEMIN (int)((RPTSPACENOM/USECPERTICK)*LTOL) 
#define RPTSPACEMAX (int)((RPTSPACENOM/USECPERTICK)*UTOL) 

// receiver states 
#define IDLE  1 
#define STARTH 2 
#define STARTL 3 
#define BIT  4 
#define ONE  5 
#define ZERO  6 
#define STOP  7 
#define BITMARK 8 
#define RPTMARK 9 

// macros 
#define GETIR(X) ((byte)digitalRead(X)) // used to read IR pin 
#define nextstate(X) (irparams.rcvstate = X) 

// state machine variables irparams 
static volatile struct { 
    byte rcvstate ;   // IR receiver state 
    byte bitcounter ;  // bit counter 
    byte irdata ;   // MARK or SPACE read from IR input pin 
    byte fptr ;    // irbuf front pointer 
    byte rptr ;    // irbuf rear pointer 
    byte irpin ;    // pin for IR data from detector 
    byte blinkflag ;   // TRUE to enable blinking of pin 13 on IR processing 
    unsigned int timer ;  // state timer 
    unsigned long irmask ; // one-bit mask for constructing IR code 
    unsigned long ircode ; // IR code 
    unsigned long irbuf[MAXBUF] ; // circular buffer for IR codes 
} irparams ; 

// main class 
class NECIRrcv 
{ 
    public: 
    NECIRrcv(int irpin); 
    unsigned long read(); 
    void begin(); 
    int available() ; 
    void flush() ; 
    void blink13(int blinkflag) ; 
    private: 
} ; 

extern NECIRrcv sensor; // <-------- declaring object as extern 
#endif 

Datei NECIRrcv.cp p (gegeben)

#include <Arduino.h> 
#include "NECIRrcv.h" 
#include "motorIR.h" 

NECIRrcv::NECIRrcv(int irpin) 
{ 
    irparams.irpin = irpin ; 
} 

void NECIRrcv::begin() { 
//(...) 
} 

unsigned long NECIRrcv::read() 
{ 
    unsigned long ircode ; 

//(...) 
    return((unsigned long)-1) ; 
} 

// (...) 

Eduardo

+1

ich völlig verstehe die Frage tat nicht, aber ich denke, das Problem Sie haben weder mit Arduino noch mit den Details Ihrer Klassen verwandt. Bitte versuchen Sie eine [mcve] (http://stackoverflow.com/help/mcve) und den genauen Compilerfehler (falls es welche gibt) – user463035818

+0

@Eduardo - Sie benötigen einen 'Sensor' für jede 'motorIR'-Eigenschaft oder a einzelner 'Sensor' für Ihr Programm? – max66

+0

Ein 'Sensor' ist genug, @ max66. Was ich nicht weiß ist, wo ich es erklären soll (in welchem ​​Teil von mororIR.h oder motorIR.cpp muss ich 'NECIRrcv sensor (4);' und 'sensor.begin()' platzieren, weil ich die Bibliothek motorIR haben möchte NECIRrcv zu verwenden, so dass ich 'sensor.read()' von 'motorIR :: control' aufrufen kann – eduherminio

Antwort

1

Wenn Sie nur eine sensor für alle Instanzen motorIR müssen, nehme ich an, dass es ein statisches Element der Klasse sein könnte.

Oder eine statische Variable in einer statischen Methode; wie diese

class motorIR 
{ 
public:  // Funciones públicas 

    motorIR(int PWM, int MI, int MD); 

    void beginner(); 

    void control(int i); 


private: // Variables privadas 
    int _PWM= STANDBY; 
    int _MI; 
    int _MD; 
    int pin_IR; 
    unsigned long IRcode; 

    static NECIRrcv & getSensor() // <--- getSensor() added 
    { static NECIRrsv sensor(4); return sensor; } 
}; 

Sie können es auf diese Weise verwenden

void motorIR::control(int i) 
{ 
    // NECIRrcv sensor(4) ; no more here 
    getSensor().begin(); 

    Serial.println("Checkpoint");  
    while (getSensor().available()) 
    { 
     Serial.print("Detection"); 
     IRcode= getSensor().read(); 
     Serial.print(IRcode, DEC); 
     Serial.print(IRcode, HEX); 
     Serial.print(IRcode, BIN); 
    } 
} 

ps: Vorsicht: sorry für mein schlechtes Englisch

--- EDIT: nicht

ps2 getestet ---

Der Fehler ist "NECIRrcv" nicht na mir ein Typ "oder" 'NECIRrcs' nennt keinen Typ "?

In meinem Beispiel habe ich versehentlich "NECIRrcs" anstelle von "NECIRrcv" geschrieben; Es tut uns leid.

über Ihren Bedarf begin() nur einmal der Sensor, können Sie die getSensor() Methode auf diese Weise modifizieren

static NECIRrcv & getSensor() 
{ 
    static NECIRrsv sensor(4); 
    static bool firstRun(true); 

    if (firstRun) 
    { 
     sensor.begin(); 
     firstRun = false; 
    } 

    return sensor; 
} 

Vorsicht: nicht getestet.

+0

Ich denke, ich bekomme Ihre Idee (obwohl der 'sensor.begin' nur gemacht werden muss, wenn 'sensor' erstellt wird), aber ich bekomme den folgenden Compilerfehler: _error: 'NECIRrcv' benennt keinen type_ in der Methode . BTW, ich habe noch nie von statischen Methoden oder Variablen gehört, wofür steht das '&'? – eduherminio

+0

@Eduardo - modifizierte die Antwort, um 'begin()' nur einmal aufzurufen; statische Methode und Variable sind ein wichtiger Teil der C++ - Sprache; Du solltest das Wissen über sie vertiefen. Das '&' Zeichen ist für "Referenz"; Wenn Sie einen Verweis (in diesem Fall auf ein 'NECRrcv') zurückgeben, wird bei der Verwendung von' getSensor() .read(); 'die Methode' read() 'der Instanz von' NECRrcv' aufgerufen, die statisch ist in 'getSensor()'; Wenn 'getMethod()' nur einen 'NECRrcv' zurückgibt (ohne' & '), gibt es nur eine Kopie des' NECRrcv' in 'getSensor()' zurück. – max66

+0

@Eduardo - anstatt eine Antwort zu schreiben, um eine neue Frage zu stellen, sollten Sie (a) eine neue Frage stellen oder (b) Ihre ursprüngliche Frage bearbeiten und ändern – max66

0

Ich liebte die Idee, das Objekt NECIRrcv::sensor als Teil der Klasse deklarieren motorIR zwar, aber versuchen NECIRrcv sensor(4) überall in motorIR.h führt zu definieren, um Fehler: ‚NECIRrcv‘ Name hat keinen Typ; Es wäre also interessant, dieses Problem zu lösen, um die Idee von @max66 zu implementieren (oder einfach nur, um herauszufinden, warum motorIR.h NECIRrcv nicht richtig erkennt).

Trotzdem bin ich auf eine alternative Lösung gestoßen: mit einem externen Objekt (wie es beschrieben wird here).

Es kann implementiert werden, wie es folgt:

In NECIRrcv Header:

#ifndef NECIRrcv_h 
#define NECIRrcv_h 

#include <Arduino.h> 

// (...) 

class NECIRrcv 
{ 
    public: 
    NECIRrcv(int irpin); 

// (...) 

    private: 
} ; 

extern NECIRrcv sensor; // <-------- declaring object as extern 

#endif 

In motorIR Quelldatei:

#include "Arduino.h" 
#include "motorIR.h" 
#include <string.h> 

NECIRrcv sensor(4); // <--------- defining object 

motorIR::motorIR(int PWM, int MI, int MD) 
{ 
    _MI= MI  +A0; 
    _PWM= PWM  +A0; 
    _MD= MD  +A0; 
} 

void motorIR::beginner() 
{ 
    Serial.begin(9600); 
    Serial.print("Begin"); 
    sensor.begin(); // <-------- now I can initialize sensor here 
} 


void motorIR::control(int i) 
{ 
    // NECIRrcv sensor(4) ; 
    // sensor.begin(); 

    Serial.println("Checkpoint");  
    while (sensor.available()) // <-- method 1 
    { 
     Serial.print("Detection"); 
     IRcode= sensor.read(); // <-- method 2 
     Serial.print(IRcode, DEC); 
     Serial.print(IRcode, HEX); 
     Serial.print(IRcode, BIN); 
    } 
}