Custom PIN for interrupt based RemoteReceiver

Dear All,

I have an Arduino Mega 2560, and I have already used the pins that attached to the interrupts. But I'd like to use the RemoteSwitch library, that using interrupts for receiving codes.
I was looking at PinChangeInt, but was confused on how to use it.
Here's my code:

/*
* Demo for RF remote switch receiver.
* For details, see RemoteReceiver.h!
*
* This sketch shows the received signals on the serial port.
* Connect the receiver to digital pin 2.
*/
#include <PinChangeInt.h>
#include <RemoteReceiver.h>

void setup() {
  Serial.begin(115200);
  
  // Initialize receiver on interrupt 0 (= digital pin 2), calls the callback "showCode"
  // after 3 identical codes have been received in a row. (thus, keep the button pressed
  // for a moment)
  //
  // See the interrupt-parameter of attachInterrupt for possible values (and pins)
  // to connect the receiver.
 // PCintPort::attachInterrupt(11, showCode, CHANGE);
 RemoteReceiver::init(0, 3, showCode);
}

void loop() {
  Serial.println("delay 1sec...");
  delay(1000);
//  showCode(); 
}

// Callback function is called only when a valid code is received.
void showCode(unsigned long receivedCode, unsigned int period) {
  // Note: interrupts are disabled. You can re-enable them if needed.
  
  // Print the received code.
  Serial.print("Code: ");
  Serial.print(receivedCode);
  Serial.print(", period duration: ");
  Serial.print(period);
  Serial.println("us.");
}

Can anybody help me attaching my receiver to pin 11?

Thanks!

and I have already used the pins that attached to the interrupts.

There is nothing in that code that uses any of the external interrupt pins.

But I'd like to use the RemoteSwitch library, that using interrupts for receiving codes.

A link to it would be useful. Most likely, you'll need to modify the RemoteSwitch library instead of the sketch.

PaulS:

and I have already used the pins that attached to the interrupts.

There is nothing in that code that uses any of the external interrupt pins.

But I'd like to use the RemoteSwitch library, that using interrupts for receiving codes.

A link to it would be useful. Most likely, you'll need to modify the RemoteSwitch library instead of the sketch.

Sorry, I'm going to use this code in an other project that using TFT screen and some sensors. That is why the interrupts are used.
The library can be found here:

Thanks!

RemoteReceiver.cpp has:

void RemoteReceiver::enable() {
        _state = -1;
        attachInterrupt(_interrupt, interruptHandler, CHANGE);
}

It should be easy enough to change that to use pin change interrupts, instead. Be sure to fix disable() and interruptHandler() to expect pin change interrupts, too.

Thanks for the hint!

I've modified the RemoteReceiver.cpp like this:

/*
 * RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/
 * See RemoteReceiver.h for details.
 *
 * License: GPLv3. See license.txt
 */

#include "RemoteReceiver.h"
#include "PinChangeInt.h"

/************
* RemoteReceiver
************/

int8_t RemoteReceiver::_interrupt;
volatile int8_t RemoteReceiver::_state;
byte RemoteReceiver::_minRepeats;
RemoteReceiverCallBack RemoteReceiver::_callback;
boolean RemoteReceiver::_inCallback = false;
boolean RemoteReceiver::_enabled = false;

void RemoteReceiver::init(int8_t interrupt, byte minRepeats, RemoteReceiverCallBack callback) {
	_interrupt = interrupt;
	_minRepeats = minRepeats;
	_callback = callback;

	enable();
	if (_interrupt >= 0) {
		PCintPort::attachInterrupt(_interrupt, interruptHandler, CHANGE);
	}
}

void RemoteReceiver::enable() {
	_state = -1;
	_enabled = true;
}

void RemoteReceiver::disable() {
	_enabled = false;
}

void RemoteReceiver::deinit() {
	_enabled = false;
	if (_interrupt >= 0) {
		PCintPort::detachInterrupt(_interrupt);
	}
}

void RemoteReceiver::interruptHandler() {
	if (!_enabled) {
		return;
	}

	static unsigned int period;				// Calculated duration of 1 period
	static byte receivedBit;				// Contains "bit" currently receiving
	static unsigned long receivedCode;		// Contains received code
	static unsigned long previousCode;		// Contains previous received code
	static byte repeats = 0;				// The number of times the an identical code is received in a row.
	static unsigned long edgeTimeStamp[3] = {0, };	// Timestamp of edges
	static unsigned int min1Period, max1Period, min3Period, max3Period;
	static bool skip;

	// Filter out too short pulses. This method works as a low pass filter.
	edgeTimeStamp[1] = edgeTimeStamp[2];
	edgeTimeStamp[2] = micros();

	if (skip) {
		skip = false;
		return;
	}

	if (_state >= 0 && edgeTimeStamp[2]-edgeTimeStamp[1] < min1Period) {
		// Last edge was too short.
		// Skip this edge, and the next too.
		skip = true;
		return;
	}

	unsigned int duration = edgeTimeStamp[1] - edgeTimeStamp[0];
	edgeTimeStamp[0] = edgeTimeStamp[1];

	// Note that if state>=0, duration is always >= 1 period.

	if (_state==-1) { // Waiting for sync-signal
		if (duration>3720) { // =31*120 minimal time between two edges before decoding starts.
			// Sync signal received.. Preparing for decoding
			period=duration/31;
			receivedCode=previousCode=repeats=0;

			// Allow for large error-margin. ElCheapo-hardware :(
			min1Period=period*4/10; // Avoid floating point math; saves memory.
			max1Period=period*16/10;
			min3Period=period*23/10;
			max3Period=period*37/10;
		}
		else {
			return;
		}
	} else if (_state<48) { // Decoding message
		receivedBit <<= 1;

		// bit part durations can ONLY be 1 or 3 periods.
		if (duration<=max1Period) {
			receivedBit &= B1110; // Clear LSB of receivedBit
		}
		else if (duration>=min3Period && duration<=max3Period) {
			receivedBit |= B1; // Set LSB of receivedBit
		}
		else { // Otherwise the entire sequence is invalid
			_state=-1;
			return;
		}

		if ((_state%4)==3) { // Last bit part?
			// Shift
			receivedCode*=3;

			// Only 4 LSB's are used; trim the rest.
			switch (receivedBit & B1111) {
				case B0101: // short long short long == B0101
					// bit "0" received
					receivedCode+=0; // I hope the optimizer handles this ;)
					break;
				case B1010: // long short long short == B1010
					// bit "1" received
					receivedCode+=1;
					break;
				case B0110: // short long long short
					// bit "f" received
					receivedCode+=2;
					break;
				default:
					// Bit was rubbish. Abort.
					_state=-1;
					return;
			}
		}
	} else if (_state==48) { // Waiting for sync bit part 1
		// Must be 1 period.
		if (duration>max1Period) {
			_state=-1;
			return;
		}
	} else { // Waiting for sync bit part 2
		// Must be 31 periods.
		if (duration<period*25 || duration>period*36) {
		  _state=-1;
		  return;
		}

		// receivedCode is a valid code!

		if (receivedCode!=previousCode) {
			repeats=0;
			previousCode=receivedCode;
		}

		repeats++;

		if (repeats>=_minRepeats) {
			if (!_inCallback) {
				_inCallback = true;
				(_callback)(receivedCode, period);
				_inCallback = false;
			}
			// Reset after callback.
			_state=-1;
			return;
		}

		// Reset for next round
		receivedCode = 0;
		_state=0; // no need to wait for another sync-bit!
		return;
	}

	_state++;
	return;
}

boolean RemoteReceiver::isReceiving(int waitMillis) {
	unsigned long startTime=millis();

	int waited; // Signed int!
	do {
		if (_state == 48) { // Abort if a valid code has been received in the mean time
			return true;
		}
		waited = (millis()-startTime);
	} while(waited>=0 && waited <= waitMillis); // Yes, clock wraps every 50 days. And then you'd have to wait for a looooong time.

	return false;
}

Now it won't compile I'm receiving a bunch of errors:

RemoteSwitch\RemoteReceiver.cpp.o: In function `PCintPort::enable(PCintPort::PCintPin*, void (*)(), unsigned char)':
C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:366: multiple definition of `PCintPort::enable(PCintPort::PCintPin*, void (*)(), unsigned char)'
sketch_jan19a.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:366: first defined here
c:/3/arduino-1.0.5-r2/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions
RemoteSwitch\RemoteReceiver.cpp.o: In function `PCintPort::detachInterrupt(unsigned char)':
C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:439: multiple definition of `PCintPort::detachInterrupt(unsigned char)'
sketch_jan19a.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:439: first defined here
RemoteSwitch\RemoteReceiver.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:366: multiple definition of `portB'
sketch_jan19a.cpp.o:(.bss.portB+0x0): first defined here
RemoteSwitch\RemoteReceiver.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:366: multiple definition of `portJ'
sketch_jan19a.cpp.o:(.bss.portJ+0x0): first defined here
RemoteSwitch\RemoteReceiver.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:366: multiple definition of `portK'
sketch_jan19a.cpp.o:(.bss.portK+0x0): first defined here
RemoteSwitch\RemoteReceiver.cpp.o: In function `PCintPort::PCint()':
C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:473: multiple definition of `PCintPort::PCint()'
sketch_jan19a.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:473: first defined here
RemoteSwitch\RemoteReceiver.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:366: multiple definition of `PCintPort::curr'
sketch_jan19a.cpp.o:(.bss._ZN9PCintPort4currE+0x0): first defined here
RemoteSwitch\RemoteReceiver.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:366: multiple definition of `PCintPort::pinState'
sketch_jan19a.cpp.o:(.bss._ZN9PCintPort8pinStateE+0x0): first defined here
RemoteSwitch\RemoteReceiver.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:366: multiple definition of `PCintPort::arduinoPin'
sketch_jan19a.cpp.o:(.bss._ZN9PCintPort10arduinoPinE+0x0): first defined here
RemoteSwitch\RemoteReceiver.cpp.o: In function `__vector_9':
C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:563: multiple definition of `__vector_9'
sketch_jan19a.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:563: first defined here
RemoteSwitch\RemoteReceiver.cpp.o: In function `__vector_10':
C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:594: multiple definition of `__vector_10'
sketch_jan19a.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:594: first defined here
RemoteSwitch\RemoteReceiver.cpp.o: In function `__vector_11':
C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:604: multiple definition of `__vector_11'
sketch_jan19a.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:604: first defined here
RemoteSwitch\RemoteReceiver.cpp.o: In function `PCintPort::addPin(unsigned char, void (*)(), unsigned char)':
C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:377: multiple definition of `PCintPort::addPin(unsigned char, void (*)(), unsigned char)'
sketch_jan19a.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:377: first defined here
RemoteSwitch\RemoteReceiver.cpp.o: In function `PCintPort::attachInterrupt(unsigned char, void (*)(), int)':
C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:421: multiple definition of `PCintPort::attachInterrupt(unsigned char, void (*)(), int)'
sketch_jan19a.cpp.o:C:\3\arduino-1.0.5-r2\libraries\PinChangeInt/PinChangeInt.h:421: first defined here

Any idea?

Thanks!

Any idea?

One of these days, someone is going to rewrite the pin change interrupt library so it isn't a piece of shit. There is NO excuse for creating a library that fails to separate the declaration of the class (in the header file) from the implementation of the class (in a source file).

Most of your issues stem from the failure to separate the declaration from the implementation.

just stumbled accross the duplicates symbols problems mentioned above. Looking at the code auf PinChangeInt i would say there is (a lot) of room for improvements.... Is there any better pin change int library available ?