Skip to content

Commit

Permalink
Initial commit from @mattwire github repo
Browse files Browse the repository at this point in the history
/arduino-dev/tree/master/libraries/RemoteSwitch
  • Loading branch information
latchdevel committed Feb 2, 2024
0 parents commit 1627b8f
Show file tree
Hide file tree
Showing 13 changed files with 1,804 additions and 0 deletions.
81 changes: 81 additions & 0 deletions README.TXT
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
RemoteSwitch library v2.3.0 (20121229) for Arduino 1.0
Made by Randy Simons http://randysimons.nl/

This library provides an easy class for Arduino, to send and receive signals
used by some common "old style" 433MHz remote control switches.

There are two styles of remote:
- "old style", which uses switches or a dial to set the house code. Use this
library.
- "new style", which use a button on the receivers to "learn" a signal. Use
the NewRemoteSwitch library instead.

See RemoteTransmitter.h and RemoteReceiver.h for details!

License: GPLv3. See ./RemoteSwitch/license.txt

Latest source and wiki: https://bitbucket.org/fuzzillogic/433mhzforarduino


Installation of library:
- Make sure Arduino is closed
- Copy the directory RemoteSwitch to the Arduino library directory (usually
<Sketchbook directory>/libraries/)
See http://arduino.cc/en/Guide/Libraries for detailed instructions.

Default installation sender & demo:
- Connect tha data-in-pin of a 433MHz transmitter to digital pin 11. See
docs/hardware setup.jpg.
(Note: your hardware may have a different pin configuration!)
- Start Arduino, and open the example: File -> Examples -> RemoteSwitch ->
LightShow
- Alter addresses/devices to reflect your own setup. Otherwise nothing will
happen.
- Compile, upload and run!

Default installation receiver & demo:
- Connect the data-out-pin of a 433MHz receiver to digital pin 2. See photo.
(Note: your hardware may have a different pin configuration!)
- Start Arduino, and open the example: File -> Examples -> RemoteSwitch ->
ShowReceivedCode or ShowReceivedCodeNewKaku, depending on your remote.
- Compile, upload and run
- Open serial monitor in Arduino (115200 baud)
- Press buttons on a 433MHz-remote, and watch the serial monitor

Notes:
- These transmitters often use the PT2262 IC, or equivalent. For details about
the waveforms used by these remotes, the datasheet of the PT2262 is provided.
Page 4 and 5 will be of most interest.


Changelog:
RemoteSwitch library v2.3.0 (20121229) for Arduino 1.0
- Improved reception quality by filtering too short pulses.
- Dropped pre-v1.0 Arduino support.
- Added RemoteReceiver::deinit()

RemoteSwitch library v2.2.1 (20120314) for Arduino 0022/1.0
- Fixed Elro code, it caused memory corruption.
- Renamed old-style .pde files to new-style .ino

RemoteSwitch library v2.2.0 (20120213) for Arduino 0022/1.0
- Added support for Elro switches (http://www.elro.eu/en/m/products/category/home_automation/home_control)
(untested; I don't have these kind of devices)
- Allowed the number of repeated signals transmitted by RemoteTransmitter to be
changed.
- By default, 16 instead of 8 repeats are sent.
- Support for Arduino 1.0.
- Added Datasheet PT2262, which (or equivalent) is often used in the transmitters.
- RemoteReceiver::isReceiving timeout changed to 150ms; 100ms was too short.

RemoteSwitch library v2.1.1 (20110920) for Arduino 0022
- Improved RemoteReceiver::isReceiving

RemoteSwitch library v2.1.0 (20110919) for Arduino 0022
- Changed classnames from *Switch to *Transmitter
- Added RemoteTransmitter::sendCode. See example "retransmitter".
- RemoteReceiver::interruptHandler() is now public, for use with InterruptChain

RemoteSwitch library v2.0.0 (20100130) for Arduino 0017
- Complete rewrite; can now receive and decode signals directly from
the receiver's digital out.
193 changes: 193 additions & 0 deletions RemoteReceiver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/*
* 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"


/************
* 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) {
attachInterrupt(_interrupt, interruptHandler, CHANGE);
}
}

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

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

void RemoteReceiver::deinit() {
_enabled = false;
if (_interrupt >= 0) {
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;
}
88 changes: 88 additions & 0 deletions RemoteReceiver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/
*
* License: GPLv3. See license.txt
*/

#ifndef RemoteReceiver_h
#define RemoteReceiver_h

#include <Arduino.h>

typedef void (*RemoteReceiverCallBack)(unsigned long, unsigned int);

/**
* See RemoteSwitch for introduction.
*
* RemoteReceiver decodes the signal received from a 433MHz-receiver, like the "KlikAanKlikUit"-system
* as well as the signal sent by the RemoteSwtich class. When a correct signal is received,
* a user-defined callback function is called.
*
* Note that in the callback function, the interrupts are still disabled. You can enabled them, if needed.
* A call to the callback must b finished before RemoteReceiver will call the callback function again, thus
* there is no re-entrant problem.
*
* When sending your own code using RemoteSwich, disable() the receiver first.
*
* This is a pure static class, for simplicity and to limit memory-use.
*/

class RemoteReceiver {
public:
/**
* Initializes the decoder.
*
* If interrupt >= 0, init will register pin <interrupt> to this library.
* If interrupt < 0, no interrupt is registered. In that case, you have to call interruptHandler()
* yourself whenever the output of the receiver changes, or you can use InterruptChain.
*
* @param interrupt The interrupt as is used by Arduino's attachInterrupt function. See attachInterrupt for details.
If < 0, you must call interruptHandler() yourself.
* @param minRepeats The number of times the same code must be received in a row before the callback is calles
* @param callback Pointer to a callback function, with signature void (*func)(unsigned long, unsigned int). First parameter is the decoded data, the second the period of the timing.
*/
static void init(int8_t interrupt, byte minRepeats, RemoteReceiverCallBack callback);

/**
* Enable decoding. No need to call enable() after init().
*/
static void enable();

/**
* Disable decoding. You can re-enable decoding by calling enable();
*/
static void disable();

/**
* Deinitializes the decoder. Disables decoding and detaches the interrupt handler. If you want to
* re-enable decoding, call init() again.
*/
static void deinit();

/**
* Tells wether a signal is being received. If a compatible signal is detected within the time out, isReceiving returns true.
* Since it makes no sense to transmit while another transmitter is active, it's best to wait for isReceiving() to false.
* By default it waits for 150ms, in which a (relative slow) KaKu signal can be broadcasted three times.
*
* Note: isReceiving() depends on interrupts enabled. Thus, when disabled()'ed, or when interrupts are disabled (as is
* the case in the callback), isReceiving() will not work properly.
*
* @param waitMillis number of milliseconds to monitor for signal.
* @return boolean If after waitMillis no signal was being processed, returns false. If before expiration a signal was being processed, returns true.
*/
static boolean isReceiving(int waitMillis = 150);

static void interruptHandler();

private:

static int8_t _interrupt; // Radio input interrupt
volatile static int8_t _state; // State of decoding process. There are 49 states, 1 for "waiting for signal" and 48 for decoding the 48 edges in a valid code.
static byte _minRepeats;
static RemoteReceiverCallBack _callback;
static boolean _inCallback; // When true, the callback function is being executed; prevents re-entrance.
static boolean _enabled; // If true, monitoring and decoding is enabled. If false, interruptHandler will return immediately.

};

#endif
Loading

0 comments on commit 1627b8f

Please sign in to comment.