Reputation: 1684
I have to code a the library motorIR, which uses NECIRrcv to extract the IR code from a sensor. Initially I tried doing it using two libraries, but that doesn't seem to be easy as I read, so I decide to include both the header and the source file of NECIRrcv in my Arduino library motorIR.
I'm having some trouble with defining NECIRrcv sensor
in motorIR.
If I do it where it's placed in the code, no signal is available (while(sensor.available())
is never entered).
I can understand that's logical, since it redefines sensor every time I call motorIR::control()
.
My real problem is that I have no clue of where I should declare sensor
, the object of NECIRrcv class, in motorIR.
I did a little research about it, and since I haven't worked with extern classes before, I've ended up even more confused about if using one it's necessary.
I'd be very grateful if someone can invest a few minutes helping me with this subject. Hope you can understand my explanations.
Here you are the different files:
File 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
File 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);
}
}
File NECIRrcv.h (given)
#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
File NECIRrcv.cpp (given)
#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
Upvotes: 1
Views: 1966
Reputation: 66200
If you need only a sensor
for all instances of motorIR
, I suppose that it could be a static member of the class.
Or a static variable in a static method; like this
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; }
};
You can use it in this way
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);
}
}
p.s.: caution: not tested
p.s.2: sorry for my bad English
--- EDIT ---
The error is "'NECIRrcv' does not name a type" or "'NECIRrcs' does not name a type"?
In my example I've written, by mistake "NECIRrcs" instead of "NECIRrcv"; sorry.
About your need to begin()
only one time the sensor, you can modify the getSensor()
method in this way
static NECIRrcv & getSensor()
{
static NECIRrsv sensor(4);
static bool firstRun(true);
if ( firstRun )
{
sensor.begin();
firstRun = false;
}
return sensor;
}
Caution: not tested.
Upvotes: 1
Reputation: 1684
I loved the idea of declaring the object NECIRrcv::sensor
as part of class motorIR
though, but trying to define NECIRrcv sensor(4)
anywhere in motorIR.h leads to error: 'NECIRrcv' does not name a type; so it would be interesting to solve this problem in order to be able to implement @max66 's idea (or eve just to figure out why motorIR.h doesn't recognize NECIRrcv
properly).
In spite of that, I think I've run into an alternative solution: using an extern object (as it's described here).
It can be implemented as it follows:
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 source file:
#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);
}
}
Upvotes: 0