Skip to content

Instantly share code, notes, and snippets.

@ArminJo
Created September 2, 2020 08:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ArminJo/f5a5a93600a84ab1087c5daf7dedaab4 to your computer and use it in GitHub Desktop.
Save ArminJo/f5a5a93600a84ab1087c5daf7dedaab4 to your computer and use it in GitHub Desktop.
3 protocols for RF remote controls for Arduino. 2262 / 2272 + EIM-826 + Intertechno
#include <Arduino.h>
#include <digitalWriteFast.h>
/*
* HX2262/2272 Stuff
*/
// measured 33.91 kHz receiver clock => Data sheet says: Transmitter clock has to be 2.5 to 8 times slower
// https://cdn-shop.adafruit.com/datasheets/PT2262.pdf
//const int HX2272_FUNDAMENTAL_CLOCK_PERIOD_X4_MICROS = 118;
const int HX2272_FUNDAMENTAL_CLOCK_PERIOD_X4_MICROS = 440;
const int HX2272_DURATION4 = HX2272_FUNDAMENTAL_CLOCK_PERIOD_X4_MICROS;
const int HX2272_DURATION12 = HX2272_FUNDAMENTAL_CLOCK_PERIOD_X4_MICROS * 3; // 1320
const int HX2272_DURATION128 = HX2272_FUNDAMENTAL_CLOCK_PERIOD_X4_MICROS * 32;
/*
* Sender IC HX2262
* Receiver IC HX2272
*/
#define HX2272_0 0 // DIP switch on 0
#define HX2272_1 1
#define HX2272_FLOAT 3 // Code input pin floating - DIP switch on 0
#define HX2272_SYNC 4
#define HX2272_FLOAT_MASK 0x02
void sendBitForHX2272(uint8_t aCode) {
switch (aCode) {
case HX2272_0: // Bit"0" 4 high + 12 low + 4 high + 12 low
case 2:
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(HX2272_DURATION4);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(HX2272_DURATION12);
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(HX2272_DURATION4);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(HX2272_DURATION12);
break;
case HX2272_1: // Bit"1" 12 high + 4 low + 12 high + 4 low
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(HX2272_DURATION12);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(HX2272_DURATION4);
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(HX2272_DURATION12);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(HX2272_DURATION4);
break;
case HX2272_FLOAT: // Bit"f" Floating 4 high + 12 low + 12 high + 4 low
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(HX2272_DURATION4);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(HX2272_DURATION12);
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(HX2272_DURATION12);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(HX2272_DURATION4);
break;
case HX2272_SYNC: // Sync 4 high + 128 low
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(HX2272_DURATION4);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(HX2272_DURATION128);
break;
default:
break;
}
}
/*
* A Frame consists of 4 repeats of (address, data + sync) aka word
* a1MeansFloating true send floating code instead of code for a 1.
* This is required for DIP switches which left the pin float at position 1
*/
void sendFrameForHX2272(uint16_t aAddress, uint8_t aSwitchState, bool a1MeansFloating) {
// 4 words
for (uint8_t i = 0; i < 4; ++i) {
// 10 bit address
for (uint8_t j = 0; j < 10; ++j) {
uint8_t tValue = aAddress & 0x01;
aAddress = aAddress >> 1;
if (a1MeansFloating) {
sendBitForHX2272(tValue | HX2272_FLOAT_MASK);
} else {
sendBitForHX2272(tValue);
}
}
// 2 bit data
if (aSwitchState == HIGH) {
// Set both bits here.
sendBitForHX2272(HX2272_1);
sendBitForHX2272(HX2272_1);
} else {
sendBitForHX2272(HX2272_0);
sendBitForHX2272(HX2272_0);
}
// sync
sendBitForHX2272(HX2272_SYNC);
}
}
/*
* Unitec EIM-826 stuff
*/
#define EIM826_FRAMEREPEAT 4 // >= 1
/*
* Values measured at remote control with 13560 crystal
* ZERO 208.5 H + 625 L = 833.5;
* ONE 610,5 H + 223 L = 833.5;
* INTER FRAME 6287 (- 625 (low time of last Zero)) = 5662
* 15 Frame repeats - But it works with 1 frame (if received correctly)
*
* https://forum.pimatic.org/topic/139/unitec-protocol-request
* https://github.com/pimatic/rfcontroljs/commit/ee2fe5997c393cb15facc849f3270f8890830fac
*/
const int EIM826_SHORT_MICROS = 218; // 210
const int EIM826_LONG_MICROS = 615; // 624
const int EIM826_INTER_FRAME_MICROS = 5662; // 6280?
void sendBitForUnitec_EIM826(bool aSendaOne) {
if (aSendaOne) {
digitalWriteFast(OUT_433_SIGNAL_PIN, HIGH);
delayMicroseconds(579);
digitalWriteFast(OUT_433_SIGNAL_PIN, LOW);
delayMicroseconds(EIM826_SHORT_MICROS);
} else {
digitalWriteFast(OUT_433_SIGNAL_PIN, HIGH);
delayMicroseconds(EIM826_SHORT_MICROS);
digitalWriteFast(OUT_433_SIGNAL_PIN, LOW);
delayMicroseconds(EIM826_LONG_MICROS);
}
}
/*
* aSwitchNumber from 0 to 3. 4 means ALL
* Frame:
* 00000000000000000000| 11 | 0 |0
* ID |Unit|!All|State
*/
void sendFrameForUnitec_EIM826(uint8_t aSwitchNumber, bool aSwitchToOn) {
uint8_t tSwitchNumber = aSwitchNumber ^ 0x03; // complement switch number bits
for (uint8_t i = 0; i < EIM826_FRAMEREPEAT; i++) {
noInterrupts();
/*
* 20 preamble bits - always 0
*/
for (byte i = 0; i < 20; i++) {
sendBitForUnitec_EIM826(0);
}
/*
* Send switch number code.
*/
if (tSwitchNumber & 0x01) {
sendBitForUnitec_EIM826(1);
} else {
sendBitForUnitec_EIM826(0);
}
if (tSwitchNumber & 0x02) {
sendBitForUnitec_EIM826(1);
} else {
sendBitForUnitec_EIM826(0);
}
// "All" switch pressed
if (aSwitchNumber == 4) {
sendBitForUnitec_EIM826(0);
} else {
sendBitForUnitec_EIM826(1);
}
/*
* ON/OFF
*/
sendBitForUnitec_EIM826(aSwitchToOn);
/*
* Stopbit always 0
*/
sendBitForUnitec_EIM826(0);
interrupts();
delayMicroseconds(EIM826_INTER_FRAME_MICROS); // interFrame delay
}
}
/*
* Intertechno stuff
*/
const int INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS = 280;
const int INTERTECHNO_DURATION5 = INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS * 5;
const int INTERTECHNO_DURATION10 = INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS * 10;
#define INTERTECHNO_0 0
#define INTERTECHNO_1 1
#define INTERTECHNO_2 2
#define INTERTECHNO_BEGIN 3
#define INTERTECHNO_END 4
void sendBitForINTERTECHNO(uint8_t aCode) {
switch (aCode) {
case INTERTECHNO_0: // Bit"0"
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(INTERTECHNO_DURATION5);
break;
case INTERTECHNO_1: // Bit"1"
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS);
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(INTERTECHNO_DURATION5);
break;
case INTERTECHNO_2: // Bit"F"
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS);
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(INTERTECHNO_DURATION5);
break;
case INTERTECHNO_BEGIN: //
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(INTERTECHNO_DURATION10);
break;
case INTERTECHNO_END: // Sync 4 high
digitalWriteFast(OUT_433_SIGNAL_PIN, 1);
delayMicroseconds(INTERTECHNO_FUNDAMENTAL_CLOCK_PERIOD_MICROS);
digitalWriteFast(OUT_433_SIGNAL_PIN, 0);
delayMicroseconds(INTERTECHNO_DURATION5);
break;
default:
break;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment