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
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.
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);
}
}
Related
I'm writing library for smart home arduino DIY project.
i want to use another library(not written by me).
here is the code:
boiler.cpp
#include "Boiler.h"
Boiler::Boiler(int pin)
{
_pin = pin;
dev.setDevice(_pin); // Set Device Output (on/off)
turnOff();
}
boiler.h
#ifndef BOILER_H_
#define BOILER_H_
// include RF24 libs
#include "RF24.h"
#include "RF24Network.h"
#include "RF24Mesh.h"
#include <SPI.h>
// SmartHome Lib Includes
#include "Device.h"
#include "TimerOne.h"
#include "timeSet.h"
class Boiler
{
private:
RF24 radio(7, 8);
RF24Network network(radio);
RF24Mesh mesh(radio, network);
int _pin ;
void timerIsr();
void DrawSCR();
public:
.
.
.
Boiler (int pin );
void turnOn();
void turnOff();
};
The problem is it's not compiling
the error I get is :
Boiler.h: 32:14: error: expected identifier before numeric constant
RF24 radio(7, 8)
What am i doing wrong?
Thanks,
I Have found the answer (by mistake)
i have added the includes to Boiler.cpp file
and moved the
RF24 radio(7, 8); // Init RF24 Radio
RF24Network network(radio); // Init RF24 Network
RF24Mesh mesh(radio, network); // Init RF24 Mesh
this is the new code :
#include "RF24.h"
#include "RF24Network.h"
#include "RF24Mesh.h"
#include <SPI.h>
.
.
.
#include "Boiler.h"
RF24 radio(7, 8); // Init RF24 Radio
RF24Network network(radio); // Init RF24 Network
RF24Mesh mesh(radio, network); // Init RF24 Mesh
Boiler::Boiler(int pin ,float Rev , String Last )
{
_pin = pin;
dev.setDevice(_pin); // Set Device Output (on/off)
turnOff();
}
void Boiler::init( char nodeID)
{
_nodeID = nodeID;
// Connect to the mesh and set Node ID
mesh.setNodeID(_nodeID);
if (_DEBUG) Serial.println(F("Connecting to the mesh..."));
mesh.begin();
// init LCD and print init data on LCD
myGLCD.InitLCD(60); // Init LCD 55 contrast
myGLCD.setFont(SmallFont); // Set small font
myGLCD.clrScr(); // clr screen
myGLCD.print("Boiler Device",0,0); //Print init Data on screen
myGLCD.print("Rev :" , 0 , 10);
myGLCD.printNumF(_rev,1 ,35,10,'.',1,'0');
myGLCD.print(_last,0,40);
myGLCD.update(); // Update display
turnOff();
}
and now it compiles ;-)
I am writing code for the Azure IoT Hub, which requires the use of c-functions in the Arduino loop(). The issue that I'm having is that if I pass a pointer to a float created in the c-file to a c++ file and modify the value, what is seen in the c-file after the c++ function returns is gibberish.
Here's a psuedocode example, and a working example is included below:
loop() in ino file:
runs runInLoop(), defined in the c-file RunTest.c
runInLoop() in RunTest.c:
create a float
pass the address to modifyFloat(float *address) defined in FloatTest.cpp
print the value of the float after modifyFloat() returns.
modifyFloat(float *address) in FloatTest.cpp:
assign a vale to *address
print the value
return
I've executed this pseudocode in the working example below and the result in the serial monitor is:
Value assigned in modifyFloat: 22.55
The value that was returned is: 1077316812
I'm using an Adafruit Huzzah Feather, configured exactly as they indicate in their documentation.
Here is a working example:
azure_troubleshoot.ino
#include "RunTest.h"
void setup()
{
initSerial();
}
void loop()
{
Serial.println("Starting main loop!\r\n");
runInLoop();
}
void initSerial()
{
Serial.begin(9600);
}
RunTest.c
#include "FloatTest.h"
void runInLoop(void)
{
while(1)
{
float testValue;
modifyFloat(&testValue);
(void)printf("The value that was returned is: %d\r\n", testValue);
delay(1000);
}
}
RunTest.h
#ifndef RUNTEST_H
#define RUNTEST_H
#ifdef __cplusplus
extern "C" {
#endif
void runInLoop(void);
#ifdef __cplusplus
}
#endif
#endif // RUNTEST_H
FloatTest.cpp
#include <Arduino.h>
#include "FloatTest.h"
void modifyFloat(float *address)
{
*address = 22.55;
Serial.print("Value assigned in modifyFloat: ");
Serial.println(*address);
}
FloatTest.h
#ifndef FLOATTEST_H
#define FLOATTEST_H
#ifdef __cplusplus
extern "C" {
#endif
void modifyFloat(float* address);
#ifdef __cplusplus
}
#endif
#endif // FLOATTEST_H
The issue was the use of the %d in the printf string in RunTest.c. Updating the code to that shown below fixes the issue and makes the output:
Value seen in modifyFloat: 22.55
The value that was returned is: 22.55
RunTest.c
#include "FloatTest.h"
void runInLoop(void)
{
while(1)
{
float testValue;
modifyFloat(&testValue);
char str_tmp[6];
dtostrf(testValue, 4, 2, str_tmp);
(void)printf("The value that was returned is: %s\r\n", str_tmp);
delay(1000);
}
}
It's telling me that "accelerometer" and "lcd" were not declared in this scope when they're used in PIT0_IRQHandler. None of the solutions I've found online have worked as of yet so I figured I'd just post it up. I'm pretty new to this as well so feel free to point out any and every error included
#include <stdio.h>
#include "system.h"
#include "derivative.h"
#include "hardware.h"
#include "delay.h"
#include "lcd.h"
#include "i2c.h"
#include "level.h"
#include "mma845x.h"
#include "tone.h"
#include "accel.h"
/// LCD dimensions and centerpoint
#define LCD_WIDTH (LCD_X_MAX-LCD_X_MIN)
#define LCD_HEIGHT (LCD_Y_MAX-LCD_Y_MIN)
#define CENTRE_X ((LCD_X_MAX-LCD_X_MIN)/2)
#define CENTRE_Y ((LCD_Y_MAX-LCD_Y_MIN)/2)
#define BACKGROUND_COLOUR (RED)
#define FOREGROUND_COLOUR (WHITE)
#define CIRCLE_RADIUS (20)
using namespace USBDM;
void initialisePIT(int channel, uint32_t interval) {
// Enable clock to PIT
SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;
// Enable PIT module
PIT->MCR = PIT_MCR_FRZ_MASK;
// Set reload value
PIT->CHANNEL[channel].LDVAL = interval-1;
// Enable this channel with interrupts
PIT->CHANNEL[channel].TCTRL = PIT_TCTRL_TEN_MASK|PIT_TCTRL_TIE_MASK;
// Enable PITn interrupts in NVIC
NVIC_EnableIRQ((IRQn_Type)(PIT0_IRQn+channel));
// Set arbitrary priority level
NVIC_SetPriority((IRQn_Type)(PIT0_IRQn+channel), 8);
}
void initialiseLCD(){
// Instantiate SPI interface class
Spi *spi = new Spi0();
// Instantiate LCD interface class
Lcd *lcd = new Lcd(spi);
// Clear Background and set to a preset (Set above) colour
lcd->clear(BACKGROUND_COLOUR);
// Draw crosshairs and initial circle on the screen
lcd->drawLine(LCD_WIDTH/2,LCD_WIDTH/2,0,LCD_HEIGHT,BLACK);
lcd->drawLine(0,LCD_WIDTH,LCD_HEIGHT/2,LCD_HEIGHT/2,BLACK);
lcd->drawCircle(CENTRE_X, CENTRE_Y, 20, WHITE);
}
void initialiseAccel()
{
I2c *i2c = new I2c0();
MMA845x *accelerometer = new MMA845x(i2c, MMA845x::ACCEL_2Gmode);
}
void PIT0_IRQHandler(void) {
int accelStatus;
int16_t accelX,accelY,accelZ;
accelerometer->readAccelerometerXYZ(&accelStatus, &accelX, &accelY, &accelZ);
lcd->clear(BACKGROUND_COLOUR);
lcd->drawCircle(accelX,accelY,20,WHITE);
// Clear the interrupt request from PIT
PIT->CHANNEL[0].TFLG = PIT_TFLG_TIF_MASK;
}
accelerometer is declared in initialiseAccel. It will go out of scope at the end of that function, and is not a known name in PIT0_IRQHandler. You should probably create a class to hold those variables and functions, or you'll have to use global variables (possibly in a namespace) to hold those values.
I am trying to create a student response system for a Jeopardy-like game using cheap tv remote controls. They are infrared, NEC protocol. A serial monitor displays button press from students in order they respond.
I'm using a TSOP 4838 receiver connected to an Arduino Uno with a capacitor and so far just the serial monitor that comes with the Arduino IDE software. My code appears below.
All is working well as long as 2 or more students do not press buttons within a half-second of each other. If that happens, I get no output on the serial monitor. I'm hoping there is some change I can make to my sketch or to the IRremote.h or IRremoteInt.h files to discern the signals quicker so my display lists who clicked first.
IRremote.h:
*/
* IRremote v1.1
* By Chris Targett
* November 2011
*
* Based on Ken Shirriff's Version 0.11 of his IR-Remote library August, 2009
* https://github.com/shirriff/Arduino-IRremote
*/
#ifndef IRremote_h
#define IRremote_h
// The following are compile-time library options.
// If you change them, recompile the library.
// If DEBUG is defined, a lot of debugging output will be printed during decoding.
// TEST must be defined for the IRtest unittests to work. It will make some
// methods virtual, which will be slightly slower, which is why it is optional.
// #define DEBUG
// #define TEST
// Results returned from the decoder
class decode_results {
public:
int decode_type; // NEC, SONY, RC5, RC6, DISH, SHARP, SAMSUNG, JVC, UNKNOWN
unsigned long value; // Decoded value
unsigned long address; // address for panasonic codes
int bits; // Number of bits in decoded value
volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks
int rawlen; // Number of records in rawbuf.
};
// Values for decode_type
#define NEC 1
#define SONY 2
#define RC5 3
#define RC6 4
#define DISH 5
#define SHARP 6
#define SAMSUNG 7
#define JVC 8
#define PANASONIC 9
#define UNKNOWN -1
// Decoded value for NEC when a repeat code is received
#define REPEAT 0xffffffff
// main class for receiving IR
class IRrecv
{
public:
IRrecv(int recvpin);
void blink13(int blinkflag);
int decode(decode_results *results);
void enableIRIn();
void resume();
private:
// These are called by decode
int getRClevel(decode_results *results, int *offset, int *used, int t1);
long decodeNEC(decode_results *results);
long decodeSony(decode_results *results);
long decodeSamsung(decode_results *results);
long decodeRC5(decode_results *results);
long decodeRC6(decode_results *results);
long decodeJVC(decode_results *results);
long decodeHash(decode_results *results);
long decodePanasonic(decode_results *results);
int compare(unsigned int oldval, unsigned int newval);
}
;
// Only used for testing; can remove virtual for shorter code
#ifdef TEST
#define VIRTUAL virtual
#else
#define VIRTUAL
#endif
class IRsend
{
public:
IRsend() {}
void sendNEC(unsigned long data, int nbits);
void sendSony(unsigned long data, int nbits);
void sendSamsung(unsigned long data, int nbits);
void sendRaw(unsigned int buf[], int len, int hz);
void sendRC5(unsigned long data, int nbits);
void sendRC6(unsigned long long data, int nbits);
void sendDISH(unsigned long data, int nbits);
void sendSharp(unsigned long data, int nbits);
void sendJVC(unsigned long data, int nbits, int repeat);
void sendPanasonic(unsigned long address, unsigned long data);
// private:
void enableIROut(int khz);
VIRTUAL void mark(int usec);
VIRTUAL void space(int usec);
}
;
// Some useful constants
#define USECPERTICK 50
#define RAWBUF 76
// Marks tend to be 100us too long, and spaces 100us too short
// when received due to sensor lag.
#define MARK_EXCESS 100
#endif
Here is the IRremoteInt.h
/*
* IRremote v1.1
* By Chris Targett
* November 2011
*
* Based on Ken Shirriff's Version 0.11 of his IR-Remote library August, 2009
* https://github.com/shirriff/Arduino-IRremote
*/
#ifndef IRremoteint_h
#define IRremoteint_h
#include <Arduino.h>
#define CLKFUDGE 5 // fudge factor for clock interrupt overhead
#define CLK 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 ERR 0
#define DECODED 1
#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 (CLK - USECPERTICK*CLKSPERUSEC + CLKFUDGE)
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT2
// pulse parameters in usec
#define NEC_HDR_MARK 9000
#define NEC_HDR_SPACE 4500
#define NEC_BIT_MARK 560
#define NEC_ONE_SPACE 1600
#define NEC_ZERO_SPACE 560
#define NEC_RPT_SPACE 2250
#define SONY_HDR_MARK 2400
#define SONY_HDR_SPACE 600
#define SONY_ONE_MARK 1200
#define SONY_ZERO_MARK 600
#define SONY_RPT_LENGTH 45000
#define RC5_T1 889
#define RC5_RPT_LENGTH 46000
#define RC6_HDR_MARK 2666
#define RC6_HDR_SPACE 889
#define RC6_T1 444
#define RC6_RPT_LENGTH 46000
#define SAMSUNG_HDR_MARK 4500
#define SAMSUNG_BITS 32
#define SAMSUNG_HDR_SPACE 4500
#define SAMSUNG_BIT_MARK 560
#define SAMSUNG_ONE_SPACE 1600
#define SAMSUNG_ZERO_SPACE 600
#define SHARP_BIT_MARK 245
#define SHARP_ONE_SPACE 1805
#define SHARP_ZERO_SPACE 795
#define SHARP_GAP 600000
#define SHARP_TOGGLE_MASK 0x3FF
#define SHARP_RPT_SPACE 3000
#define DISH_HDR_MARK 400
#define DISH_HDR_SPACE 6100
#define DISH_BIT_MARK 400
#define DISH_ONE_SPACE 1700
#define DISH_ZERO_SPACE 2800
#define DISH_RPT_SPACE 6200
#define DISH_TOP_BIT 0x8000
#define SHARP_BITS 15
#define DISH_BITS 16
#define JVC_HDR_MARK 8000
#define JVC_HDR_SPACE 4000
#define JVC_BIT_MARK 600
#define JVC_ONE_SPACE 1600
#define JVC_ZERO_SPACE 550
#define JVC_RPT_LENGTH 60000
#define PANASONIC_HDR_MARK 3502
#define PANASONIC_HDR_SPACE 1750
#define PANASONIC_BIT_MARK 502
#define PANASONIC_ONE_SPACE 1244
#define PANASONIC_ZERO_SPACE 370
#define TOLERANCE 25 // percent tolerance in measurements
#define LTOL (1.0 - TOLERANCE/100.)
#define UTOL (1.0 + TOLERANCE/100.)
#define _GAP 5000 // Minimum map between transmissions
#define GAP_TICKS (_GAP/USECPERTICK)
#define TICKS_LOW(us) (int) (((us)*LTOL/USECPERTICK))
#define TICKS_HIGH(us) (int) (((us)*UTOL/USECPERTICK + 1))
#ifndef DEBUG
#define MATCH(measured_ticks, desired_us) ((measured_ticks) >= TICKS_LOW(desired_us) && (measured_ticks) <= TICKS_HIGH(desired_us))
#define MATCH_MARK(measured_ticks, desired_us) MATCH(measured_ticks, (desired_us) + MARK_EXCESS)
#define MATCH_SPACE(measured_ticks, desired_us) MATCH((measured_ticks), (desired_us) - MARK_EXCESS)
// Debugging versions are in IRremote.cpp
#endif
// receiver states
#define STATE_IDLE 2
#define STATE_MARK 3
#define STATE_SPACE 4
#define STATE_STOP 5
// information for the interrupt handler
typedef struct {
uint8_t recvpin; // pin for IR data from detector
uint8_t rcvstate; // state machine
uint8_t blinkflag; // TRUE to enable blinking of pin 13 on IR processing
unsigned int timer; // state timer, counts 50uS ticks.
unsigned int rawbuf[RAWBUF]; // raw data
uint8_t rawlen; // counter of entries in rawbuf
}
irparams_t;
// Defined in IRremote.cpp
extern volatile irparams_t irparams;
// IR detector output is active low
#define MARK 0
#define SPACE 1
#define TOPBIT 0x80000000
#define NEC_BITS 32
#define SONY_BITS 12
#define JVC_BITS 32
#define MIN_RC5_SAMPLES 11
#define MIN_RC6_SAMPLES 1
#endif
and here's my sketch:
#include <IRremote.h>
#include <IRremoteInt.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
void loop()
{
if (irrecv.decode(&results))
{
if (results.value == 551520375) { //1
Serial.println("Team 1");
}
if (results.value == 551504055) { //2
Serial.println("Team 2");
}
if (results.value == 551536695) { //3
Serial.println("Team 3");
}
if (results.value == 551495895) { //4
Serial.println("Team 4");
}
if (results.value == 551528535) { //5
Serial.println("Team 5");
}
if (results.value == 551512215) { //6
Serial.println("Team 6");
}
if (results.value == 551544855) { //7
Serial.println("Team 7");
}
if (results.value == 551491815) { //8
Serial.println("Team 8");
}
if (results.value == 551524455) { //9
Serial.println("Team 9");
}
if (results.value == 551487735) { //10
Serial.println("Team 10");
}
// Serial.println(results.value);
irrecv.resume(); // Receive the next value
}
}
In short - Not really and not reliably. The problem is that your system is effectively multi-dropped. The receiver is the seeing the sum of both transmitters. Where the modulation and encoded signal are summed up and thus corrupted.
I have IR toy magic wands, for dueling I have a the winner keep transmitting as to JAM the looser latter signal.
You could try to use TWO different modulation frequencies. One remote at 36K and the other at 60K. 38K is typical and there is significant overlap. I have seen 36 and 40 get heard or corrupt 38K. So I would got to the farthest ends of available demodulator chips; being 36K and 60K. However, I suspect you are using provided transmitters which may not be changed. So you will have to find some or build one.
Additionally using pre-built ones, you are at the mercy of its behavior. You stated 1/2 second. That is likely because they are re-transmitting retries and have start delays and pauses beyond that of the NEC frame being sent.
You could also implement RX/TX pairs that are different IR wavelength. However, most purchasable demodulator IC's are on standard wavelength. I also recommend not building a discrete RX when possible, as they integrated RX/Demodulators have Auto GAIN, stuff like that.
I'm trying to write a function that can Shift out data to 74HC595 shift registers which can shift out 8, 16, and 32 bit values.
Using an overloaded function, I have this:
/**********************************************************************************
* Software SPI Pin Settings
*********************************************************************************/
#define SPIPINPORT PORTB //The Port that the Pins are on.
#define LatchPin 2 //_RCLK Shift register clock pin
#define DataPin 3 //SER DS Serial data input
#define ClockPin 5
/**********************************************************************************
* Preproccesor PIN to PIN Mask
*********************************************************************************/
#define LATCHMASK (1 << LatchPin)
#define MOSIMASK (1 << DataPin)
#define CLOCKMASK (1 << ClockPin)
/**********************************************************************************
* Macros
*********************************************************************************/
#define tggl(port,bit) (port)^=(1<<(bit))
#define LATCH (SPIPINPORT &=~ LATCHMASK)
#define unLATCH (SPIPINPORT |= LATCHMASK)
#define PULSE { tggl(SPIPINPORT,ClockPin); tggl(SPIPINPORT,ClockPin); }
void zShiftClass::ShiftOut(uint8_t value)
{
LATCH;
for (uint8_t i = 0; i <= 7; i++)
{
if( !!(value&(1<<i)) == true) //If value is not a 1, turn off MOSIMASK
{ SPIPINPORT |= MOSIMASK; }
else
{ SPIPINPORT &= ~MOSIMASK; }
PULSE; //Pulse the Clock
}
unLATCH;
}
void zShiftClass::ShiftOut(uint16_t value)
{
LATCH;
for (uint8_t i = 0; i <= 15; i++)
{
if( !!(value&(1<<i)) == true) //If value is not a 1, turn off MOSIMASK
{ SPIPINPORT |= MOSIMASK; }
else
{ SPIPINPORT &= ~MOSIMASK; }
PULSE; //Pulse the Clock
}
unLATCH;
}
void zShiftClass::ShiftOut(uint32_t value)
{
LATCH;
for (uint8_t i = 0; i <= 31; i++)
{
if( !!(value&(1<<i)) == true) //If value is not a 1, turn off MOSIMASK
{ SPIPINPORT |= MOSIMASK; }
else
{ SPIPINPORT &= ~MOSIMASK; }
PULSE; //Pulse the Clock
}
unLATCH;
}
And I want to use this template to replace these functions:
template<typename TYPE>void Shift(TYPE value)
{
uint8_t loops = (( 8 * sizeof(value) ) - 1 );
LATCH;
for (uint8_t i = 0; i <= loops; i++)
{
if( !!(value&(1<<i)) == true) //If value is not a 1, turn off MOSIMASK
{ SPIPINPORT |= MOSIMASK; }
else
{ SPIPINPORT &= ~MOSIMASK; }
PULSE; //Pulse the Clock
}
unLATCH;
}
When I compile, I get the following errors:
Compiling 'zLEDArray' for 'Arduino Uno'
zLEDArray.ino : variable or field 'Shift' declared void
zLEDArray.ino : 'TYPE' was not declared in this scope
Error compiling
What am I doing wrong?
Okay, this falls in the category of "beware of dev tools bearing gifts". The Arduino sketch tool is your problem. If you turn on verbose compiler output on the preferences menu, you will get some insight into what happens. With your code, I can duplicate your error. When compiling a test project called template1, the same error is reported, but now can see the compiler command line:
D:\arduino-dev\arduino-1.0.3\hardware\tools\avr\bin\avr-g++ -c ...yada yada
more yada... e:\Temp\build3528223623599856131.tmp\template1.cpp ...
template1:14: error: variable or field 'Shift' declared void
template1:14: error: 'TYPE' was not declared in this scope
The key point is that .CPP file. That is a file that the dev environment constructs from your .INO and is what is the actual input to the compiler. If you go grab that file, you will see all your code with some bonus lines included:
#include "Arduino.h"
void Shift(TYPE value);
void setup();
void loop();
The build tool added for you, 4 lines:
the Arduino header (because nobody remembers this)
3 forward declarations for functions that it figured out by parsing code
The attempt at producing a forward declaration from the function template is incorrect, and produces the code that results in the compiler error.
The solution is to move the template out from the .INO file.
Create a library folder, say T1.
Create a .H file in that folder with the template code, say tspi.h.
Import the library to your project.
Make sure the #include line is after the first line of code in your .INO (more weirdness - the tool will insert a #include "Arduino.h" after all the comments but before first line of code. If you leave your include at the top of the .INO file, it will be processed before the Arduino header)
You can get rid of the error by adding the correct forward declaration in your ino file. The inuntuitive thing is that you must also do this if you define the function before you use it:
template <typename TYPE> void Shift(TYPE value);
// you may use the function here or you can have the declaration
// immediately before the definition
template<typename TYPE>void Shift(TYPE value)
{
// your implementation
}
The explanation why this is the case is in jdr5ca's answer. Thanks for clarifying, I found this out by trial and error.