Created
September 12, 2020 09:17
-
-
Save ArminJo/3664e7638ce5e6c3936915dc097530dd to your computer and use it in GitHub Desktop.
Arduino 433 MHz sender for PT2262/PT2272 sender/receiver chip combinations.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 433MHzSenderPT2262.cpp | |
* | |
* 433 MHz sender for PT2262/PT2272 sender/receiver chip combinations. | |
* https://cdn-shop.adafruit.com/datasheets/PT2262.pdf | |
* | |
* Copyright (C) 2020 Armin Joachimsmeyer | |
* [email protected] | |
* | |
* 433MHzSenderPT2262 is free software: you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation, either version 3 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>. | |
* | |
*/ | |
#include <Arduino.h> | |
//#define USE_DIGITAL_WRITE_FAST_LIBRARY | |
#ifdef USE_DIGITAL_WRITE_FAST_LIBRARY | |
// https://github.com/watterott/Arduino-Libs/tree/master/digitalWriteFast | |
#include "digitalWriteFast.h" | |
#else | |
// otherwise replace all calls to digitalWriteFast() with digitalWrite() | |
#define digitalWriteFast(a,b) digitalWrite(a,b) | |
#endif | |
#define VERSION_EXAMPLE "1.0" | |
const int OUT_433_SIGNAL_PIN = 5; | |
/* | |
* Debounced button library | |
*/ | |
#define USE_BUTTON_0 // Enable code for button at INT0 / pin 2 | |
#include "EasyButtonAtInt01.cpp.h" | |
void handleButtonPress(bool aButtonToggleState); | |
EasyButton Button1AtPin2(&handleButtonPress); // Button is connected to INT0 / pin 2 | |
// Forward declarations | |
void sendFrameForPT2262(uint16_t a10BitAddress, uint8_t a2BitData); | |
void sendFrameForPT2262(uint16_t a5BitSenderAddress, uint16_t a5BitReceiverAddressExtension, uint8_t a2BitData); | |
/* | |
* The value of the clock period of the sender. We have 32 clocks per bit. | |
* If you have only a receiver at hand -> Data sheet says: transmitter clock has to be 2.5 to 8 times slower than sender clock | |
* A complete sender word consists of 32 x 12 + 4 (4 for last sync bit) = 388 clock cycles. | |
* A frame consists of 4 repeats of (address/data + sync) aka word | |
*/ | |
//#define PT2262_CLOCK_PERIOD_MICROS 110 // 3.7 times slower than measured 33.91 kHz / 29.5 us receiver clock | |
#define PT2262_CLOCK_PERIOD_MICROS 81 // derived from sender word length of 31.5 ms | |
/* | |
* Settings for my ELRO / Flamingo set | |
*/ | |
#define ADDRESS_SENDER_5_BIT 0b01110 // LSB's ON = 0, OFF = 1 | |
#define ADDRESS_RECEIVER_5_BIT_A 0b10110 | |
#define ADDRESS_RECEIVER_5_BIT_B 0b11101 | |
#define ADDRESS_RECEIVER_5_BIT_C 0b11011 | |
#define ADDRESS_RECEIVER_5_BIT_D 0b10111 | |
#define ADDRESS_RECEIVER_10_BIT_D 0x2EE // or 0b1011101110 | |
#define DATA_SWITCH_ON 0b10 | |
#define DATA_SWITCH_OFF 0b01 | |
/* | |
* Send code for receiver D | |
*/ | |
void handleButtonPress(bool aButton0ToggleState) { | |
Serial.print(F("Send a ")); | |
Serial.println(aButton0ToggleState); | |
if (aButton0ToggleState) { | |
sendFrameForPT2262(ADDRESS_SENDER_5_BIT, ADDRESS_RECEIVER_5_BIT_D, DATA_SWITCH_ON); | |
// sendFrameForPT2262(ADDRESS_RECEIVER_10_BIT_D, 2); | |
} else { | |
sendFrameForPT2262(ADDRESS_SENDER_5_BIT, ADDRESS_RECEIVER_5_BIT_D, DATA_SWITCH_OFF); | |
// sendFrameForPT2262(ADDRESS_RECEIVER_10_BIT_D, 1); | |
} | |
} | |
void setup() { | |
// initialize the digital pin as an output. | |
pinMode(LED_BUILTIN, OUTPUT); | |
pinMode(OUT_433_SIGNAL_PIN, OUTPUT); | |
Serial.begin(115200); | |
// Just to know which program is running on my Arduino | |
Serial.println(F("START " __FILE__ "\r\nVersion " VERSION_EXAMPLE " from " __DATE__)); | |
} | |
void loop() { | |
// we have a callback function :-) | |
} | |
/* | |
* PT2262/2272 Stuff | |
*/ | |
#define PT2262_DURATION4 (PT2262_CLOCK_PERIOD_MICROS * 4) | |
#define PT2262_DURATION12 (PT2262_CLOCK_PERIOD_MICROS * 12) | |
#define PT2262_DURATION128 (PT2262_CLOCK_PERIOD_MICROS * 128) | |
/* | |
* Sender IC HX2262 | |
* Receiver IC PT2262 | |
*/ | |
#define PT2262_0 0 // DIP switch in position ON (connect HX2262 pin to ground) | |
#define PT2262_1 1 | |
#define PT2262_FLOAT 3 // Code input pin floating - DIP switch in position off | |
#define PT2262_SYNC 4 | |
#define PT2262_FLOAT_MASK 0x02 | |
void sendBitForPT2262(uint8_t aCode) { | |
switch (aCode) { | |
case PT2262_0: // Bit"0" 4 high + 12 low + 4 high + 12 low | |
case 2: | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 1); | |
delayMicroseconds(PT2262_DURATION4); | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 0); | |
delayMicroseconds(PT2262_DURATION12); | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 1); | |
delayMicroseconds(PT2262_DURATION4); | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 0); | |
delayMicroseconds(PT2262_DURATION12); | |
break; | |
case PT2262_1: // Bit"1" 12 high + 4 low + 12 high + 4 low | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 1); | |
delayMicroseconds(PT2262_DURATION12); | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 0); | |
delayMicroseconds(PT2262_DURATION4); | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 1); | |
delayMicroseconds(PT2262_DURATION12); | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 0); | |
delayMicroseconds(PT2262_DURATION4); | |
break; | |
case PT2262_FLOAT: // Bit"f" Floating 4 high + 12 low + 12 high + 4 low | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 1); | |
delayMicroseconds(PT2262_DURATION4); | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 0); | |
delayMicroseconds(PT2262_DURATION12); | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 1); | |
delayMicroseconds(PT2262_DURATION12); | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 0); | |
delayMicroseconds(PT2262_DURATION4); | |
break; | |
case PT2262_SYNC: // Sync 4 high + 128 low | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 1); | |
delayMicroseconds(PT2262_DURATION4); | |
digitalWriteFast(OUT_433_SIGNAL_PIN, 0); | |
delayMicroseconds(PT2262_DURATION128); | |
break; | |
default: | |
break; | |
} | |
} | |
/* | |
* A frame consists of 4 repeats of (address/data + sync) aka word | |
* @param a1MeansFloating true send floating code instead of code for a 1. This is default for most of the switches | |
* Floating is required for DIP switches which let the pin float at position 1 | |
* @param aAddressData 10 bit address/data LSB is sent first | |
*/ | |
void sendFrameForPT2262(uint16_t aAddressData, bool a1MeansFloating) { | |
Serial.print(F("Address/Data=0x")); | |
Serial.print(aAddressData,HEX); | |
Serial.print(F(", 0b")); | |
Serial.println(aAddressData,BIN); | |
// 4 words | |
for (uint8_t i = 0; i < 4; ++i) { | |
// 12 bit address/data | |
uint16_t tAddressData = aAddressData; | |
for (uint8_t j = 0; j < 12; ++j) { | |
uint8_t tValue = tAddressData & 0x01; | |
tAddressData = tAddressData >> 1; | |
if (a1MeansFloating) { | |
sendBitForPT2262(tValue | PT2262_FLOAT_MASK); | |
} else { | |
sendBitForPT2262(tValue); | |
} | |
} | |
// sync | |
sendBitForPT2262(PT2262_SYNC); | |
} | |
} | |
void sendFrameForPT2262(uint16_t a10BitAddress, uint8_t a2BitData) { | |
sendFrameForPT2262(a10BitAddress | (a2BitData << 10), true); | |
} | |
void sendFrameForPT2262(uint16_t a5BitSenderAddress, uint16_t a5BitReceiverAddressExtension, uint8_t a2BitData) { | |
sendFrameForPT2262((a5BitSenderAddress | (a5BitReceiverAddressExtension << 5)) | (a2BitData << 10), true); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define BIT_READ(value, bit) ((value) & (1UL << (bit))) | |
#define BIT_SET(value, bit) ((value) |= (1UL << (bit))) | |
#define BIT_CLEAR(value, bit) ((value) &= ~(1UL << (bit))) | |
#define BIT_WRITE(value, bit, bitvalue) (bitvalue ? BIT_SET(value, bit) : BIT_CLEAR(value, bit)) | |
#if !defined(digitalPinToPortReg) | |
#if (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || \ | |
defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)) | |
// Arduino Mega Pins | |
#define __digitalPinToPortReg(P) \ | |
(((P) >= 22 && (P) <= 29) ? &PORTA : \ | |
((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PORTB : \ | |
(((P) >= 30 && (P) <= 37) ? &PORTC : \ | |
((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PORTD : \ | |
((((P) >= 0 && (P) <= 3) || (P) == 5) ? &PORTE : \ | |
(((P) >= 54 && (P) <= 61) ? &PORTF : \ | |
((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PORTG : \ | |
((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PORTH : \ | |
(((P) == 14 || (P) == 15) ? &PORTJ : \ | |
(((P) >= 62 && (P) <= 69) ? &PORTK : &PORTL)))))))))) | |
#define __digitalPinToDDRReg(P) \ | |
(((P) >= 22 && (P) <= 29) ? &DDRA : \ | |
((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &DDRB : \ | |
(((P) >= 30 && (P) <= 37) ? &DDRC : \ | |
((((P) >= 18 && (P) <= 21) || (P) == 38) ? &DDRD : \ | |
((((P) >= 0 && (P) <= 3) || (P) == 5) ? &DDRE : \ | |
(((P) >= 54 && (P) <= 61) ? &DDRF : \ | |
((((P) >= 39 && (P) <= 41) || (P) == 4) ? &DDRG : \ | |
((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &DDRH : \ | |
(((P) == 14 || (P) == 15) ? &DDRJ : \ | |
(((P) >= 62 && (P) <= 69) ? &DDRK : &DDRL)))))))))) | |
#define __digitalPinToPINReg(P) \ | |
(((P) >= 22 && (P) <= 29) ? &PINA : \ | |
((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PINB : \ | |
(((P) >= 30 && (P) <= 37) ? &PINC : \ | |
((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PIND : \ | |
((((P) >= 0 && (P) <= 3) || (P) == 5) ? &PINE : \ | |
(((P) >= 54 && (P) <= 61) ? &PINF : \ | |
((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PING : \ | |
((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PINH : \ | |
(((P) == 14 || (P) == 15) ? &PINJ : \ | |
(((P) >= 62 && (P) <= 69) ? &PINK : &PINL)))))))))) | |
#define __digitalPinToBit(P) \ | |
(((P) >= 7 && (P) <= 9) ? (P) - 3 : \ | |
(((P) >= 10 && (P) <= 13) ? (P) - 6 : \ | |
(((P) >= 22 && (P) <= 29) ? (P) - 22 : \ | |
(((P) >= 30 && (P) <= 37) ? 37 - (P) : \ | |
(((P) >= 39 && (P) <= 41) ? 41 - (P) : \ | |
(((P) >= 42 && (P) <= 49) ? 49 - (P) : \ | |
(((P) >= 50 && (P) <= 53) ? 53 - (P) : \ | |
(((P) >= 54 && (P) <= 61) ? (P) - 54 : \ | |
(((P) >= 62 && (P) <= 69) ? (P) - 62 : \ | |
(((P) == 0 || (P) == 15 || (P) == 17 || (P) == 21) ? 0 : \ | |
(((P) == 1 || (P) == 14 || (P) == 16 || (P) == 20) ? 1 : \ | |
(((P) == 19) ? 2 : \ | |
(((P) == 5 || (P) == 6 || (P) == 18) ? 3 : \ | |
(((P) == 2) ? 4 : \ | |
(((P) == 3 || (P) == 4) ? 5 : 7))))))))))))))) | |
// 15 PWM | |
#define __digitalPinToTimer(P) \ | |
(((P) == 13 || (P) == 4) ? &TCCR0A : \ | |
(((P) == 11 || (P) == 12) ? &TCCR1A : \ | |
(((P) == 10 || (P) == 9) ? &TCCR2A : \ | |
(((P) == 5 || (P) == 2 || (P) == 3) ? &TCCR3A : \ | |
(((P) == 6 || (P) == 7 || (P) == 8) ? &TCCR4A : \ | |
(((P) == 46 || (P) == 45 || (P) == 44) ? &TCCR5A : 0)))))) | |
#define __digitalPinToTimerBit(P) \ | |
(((P) == 13) ? COM0A1 : (((P) == 4) ? COM0B1 : \ | |
(((P) == 11) ? COM1A1 : (((P) == 12) ? COM1B1 : \ | |
(((P) == 10) ? COM2A1 : (((P) == 9) ? COM2B1 : \ | |
(((P) == 5) ? COM3A1 : (((P) == 2) ? COM3B1 : (((P) == 3) ? COM3C1 : \ | |
(((P) == 6) ? COM4A1 : (((P) == 7) ? COM4B1 : (((P) == 8) ? COM4C1 : \ | |
(((P) == 46) ? COM5A1 : (((P) == 45) ? COM5B1 : COM5C1)))))))))))))) | |
#elif (defined(__AVR_ATmega644__) || \ | |
defined(__AVR_ATmega644P__)) | |
// Arduino 644 Pins | |
#define __digitalPinToPortReg(P) \ | |
(((P) >= 0 && (P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : &PORTA))) | |
#define __digitalPinToDDRReg(P) \ | |
(((P) >= 0 && (P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : (((P) >= 8 && (P) <= 15) ? &DDRC : &DDRA))) | |
#define __digitalPinToPINReg(P) \ | |
(((P) >= 0 && (P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 8 && (P) <= 15) ? &PINC : &PINA))) | |
#define __digitalPinToBit(P) \ | |
(((P) >= 0 && (P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (P) - 24))) | |
// 6 PWM | |
#define __digitalPinToTimer(P) \ | |
(((P) == 3 || (P) == 4) ? &TCCR0A : \ | |
(((P) == 12 || (P) == 13) ? &TCCR1A : \ | |
(((P) == 14 || (P) == 15) ? &TCCR2A : 0))) | |
#define __digitalPinToTimerBit(P) \ | |
(((P) == 3) ? COM0A1 : (((P) == 4) ? COM0B1 : \ | |
(((P) == 13) ? COM1A1 : (((P) == 12) ? COM1B1 : \ | |
(((P) == 15) ? COM2A1 : COM2B1))))) | |
#else | |
// Standard Arduino Pins | |
#define __digitalPinToPortReg(P) \ | |
(((P) >= 0 && (P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : &PORTC)) | |
#define __digitalPinToDDRReg(P) \ | |
(((P) >= 0 && (P) <= 7) ? &DDRD : (((P) >= 8 && (P) <= 13) ? &DDRB : &DDRC)) | |
#define __digitalPinToPINReg(P) \ | |
(((P) >= 0 && (P) <= 7) ? &PIND : (((P) >= 8 && (P) <= 13) ? &PINB : &PINC)) | |
#define __digitalPinToBit(P) \ | |
(((P) >= 0 && (P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14)) | |
#if defined(__AVR_ATmega8__) | |
// 3 PWM | |
#define __digitalPinToTimer(P) \ | |
(((P) == 9 || (P) == 10) ? &TCCR1A : (((P) == 11) ? &TCCR2 : 0)) | |
#define __digitalPinToTimerBit(P) \ | |
(((P) == 9) ? COM1A1 : (((P) == 10) ? COM1B1 : COM21)) | |
#else //168,328 | |
// 6 PWM | |
#define __digitalPinToTimer(P) \ | |
(((P) == 6 || (P) == 5) ? &TCCR0A : \ | |
(((P) == 9 || (P) == 10) ? &TCCR1A : \ | |
(((P) == 11 || (P) == 3) ? &TCCR2A : 0))) | |
#define __digitalPinToTimerBit(P) \ | |
(((P) == 6) ? COM0A1 : (((P) == 5) ? COM0B1 : \ | |
(((P) == 9) ? COM1A1 : (((P) == 10) ? COM1B1 : \ | |
(((P) == 11) ? COM2A1 : COM2B1))))) | |
#endif //defined(__AVR_ATmega8__) | |
#endif | |
#endif //#if !defined(digitalPinToPortReg) | |
#if !defined(digitalWriteFast) | |
#define digitalWriteFast(P, V) \ | |
if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \ | |
BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (V)); \ | |
} else { \ | |
digitalWrite((P), (V)); \ | |
} | |
#endif | |
#if !defined(pinModeFast) | |
#define pinModeFast(P, V) \ | |
if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \ | |
if (digitalPinToTimer(P)) \ | |
BIT_CLEAR(*__digitalPinToTimer(P), __digitalPinToTimerBit(P)); \ | |
BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (V)); \ | |
} else { \ | |
pinMode((P), (V)); \ | |
} | |
#endif | |
#if !defined(digitalReadFast) | |
#define digitalReadFast(P) ( (int) __digitalReadFast((P)) ) | |
#define __digitalReadFast(P) \ | |
(__builtin_constant_p(P)) \ | |
? BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P)) \ | |
: digitalRead((P)) | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment