├── LICENSE ├── README.md ├── documentation ├── TinyRemoteRF_pic1.jpg ├── TinyRemoteRF_pic2.jpg ├── TinyRemoteRF_pic3.jpg ├── TinyRemoteRF_pic4.jpg └── TinyRemoteRF_wiring.png ├── hardware ├── TinyRemoteRF_BOM.tsv ├── TinyRemoteRF_gerber.zip └── TinyRemoteRF_schematic.pdf └── software ├── receiver └── RF_Receiver.ino ├── remote_4_buttons ├── RF_Remote_4B.ino └── makefile └── remote_5_buttons ├── RF_Remote_5B.ino └── makefile /LICENSE: -------------------------------------------------------------------------------- 1 | This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. 2 | To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ or send 3 | a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TinyRemoteRF - 433MHz RF Remote Control based on ATtiny13A 2 | TinyRemoteRF is an RF remote control based on an ATtiny13A microcontroller and a SYN115 ASK transmitter IC powered by a CR2032 coin cell battery. 3 | 4 | - Design Files (EasyEDA): https://easyeda.com/wagiminator/attiny13-tinyremote-rf 5 | 6 | ![pic1.jpg](https://raw.githubusercontent.com/wagiminator/ATtiny13-TinyRemoteRF/main/documentation/TinyRemoteRF_pic1.jpg) 7 | 8 | # Hardware 9 | The wiring is shown below: 10 | 11 | ![wiring.png](https://raw.githubusercontent.com/wagiminator/ATtiny13-TinyRemoteRF/main/documentation/TinyRemoteRF_wiring.png) 12 | 13 | If you want to use only four buttons, you can leave KEY5 unsoldered and upload the 4-button version of the firmware. If you want to use all five buttons, you have to disable RESET on PB5 by burning the respective fuses after uploading the 5-button version of the firmware: 14 | 15 | ``` 16 | avrdude -c usbasp -p t13 -U lfuse:w:0x2a:m -U hfuse:w:0xfe:m 17 | ``` 18 | 19 | Warning: You will need a high voltage fuse resetter to undo this change! 20 | 21 | For a simple breadboard test you can directly connect the DATA pin of an RF module to PB0. 22 | 23 | # Software 24 | ## Protocol 25 | The protocol is based on the ones used for infrared remote controls, but also takes into account the special needs of a stable radio connection. It is a simple but robust and DC-free protocol which is easy to decode and does not require precise timing. It operates with ASK/OOK (Amplitude Shift Keying / On-Off Keyed). 26 | 27 | Pulse lengths are derived from an adjustable error width (RF_ERR). A "0" bit is a 2 * RF_ERR long burst and an equally long space, a "1" bit is a 4 * RF_ERR long burst and an equally long space. A start bit is a 6 * RF_ERR long burst and an equally long space. 28 | 29 | ``` 30 | +-------+ +---+ +-----+ +---+ +- ON 31 | | | | | | | | | | start: 6 * ERR 32 | | 6 | 6 | 2 | 2 | 4 | 4 | 2 | 2 | ... bit0: 2 * ERR 33 | | | | | | | | | | bit1: 4 * ERR 34 | --+ +-------+ +---+ +-----+ +---+ OFF 35 | 36 | |<--- start --->|<-"0"->|<---"1"--->|<-"0"->| 37 | ``` 38 | 39 | An RF telegram starts with the preamble in which a defined number of "0" bits are transmitted to wake up the receiver and allow it to set its automatic gain (AGC). The following start bits signify the start of the transmission. Afterwards three data bytes are transmitted, most significant bit first. The three data bytes are in order: 40 | - the 8-bit address of the device, 41 | - the 8-bit key-dependent command and 42 | - the 8-bit logical inverse of the command. 43 | 44 | After the last bit a space of at least 8 * RF_ERR signifies the end of the transmission. The transmission can be repeated several times. 45 | 46 | ## Implementation 47 | At the beginning of the code, the framework conditions are set, some of which can also be adapted by the user. 48 | 49 | ```c 50 | // RF Codes 51 | #define ADDR 0x55 // address of the device 52 | #define CMD1 0x01 // command KEY1 53 | #define CMD2 0x02 // command KEY2 54 | #define CMD3 0x03 // command KEY3 55 | #define CMD4 0x04 // command KEY4 56 | #define CMD5 0x05 // command KEY5 57 | 58 | // define RF error width in microseconds; must be the same in the receiver code; 59 | // higher values reduce the error rate, but lengthen the transmission time 60 | #define RF_ERR 150 61 | 62 | // define number of preamble bits 63 | #define RF_PRE 32 64 | 65 | // define number of start bits; must be the same in the receiver code 66 | #define RF_START 4 67 | 68 | // define number of transmission repeats 69 | #define RF_REP 3 70 | 71 | // macros ASK/OOK 72 | #define RF_on() PORTB |= (1<|<-"0"->|<---"1"--->|<-"0"->| 17 | // 18 | // An RF telegram starts with the preamble byte to wake up the receiver 19 | // and allow it to set its automatic gain. The following start bits 20 | // signifies the start of the transmission. Afterwards three data bytes 21 | // are transmitted, most significant bit first. The three data bytes 22 | // are in order: 23 | // - the 8-bit address of the device, 24 | // - the 8-bit key-dependent command and 25 | // - the 8-bit logical inverse of the command. 26 | // After the last bit a space of at least 8 * RF_ERR signifies the end 27 | // of the transmission. 28 | 29 | #define DATA_PIN 10 // pin connected to receiver module 30 | #define RF_ERR 150 // must be the same value as in the transmitter code 31 | #define RF_START 4 // must be the same value as in the transmitter code 32 | 33 | uint16_t duration; 34 | 35 | void setup() { 36 | pinMode(DATA_PIN, INPUT); 37 | pinMode(LED_BUILTIN, OUTPUT); 38 | Serial.begin(9600); 39 | } 40 | 41 | void loop() { 42 | // turn off LED 43 | digitalWrite(LED_BUILTIN, LOW); 44 | 45 | // wait for start bits 46 | uint8_t counter = RF_START; 47 | do { 48 | duration = pulseIn(DATA_PIN, HIGH, 14 * RF_ERR); 49 | if ((duration < (5 * RF_ERR)) || (duration > (7 * RF_ERR))) counter = 5; 50 | } while(--counter); 51 | delayMicroseconds(2 * RF_ERR); 52 | 53 | // turn on LED 54 | digitalWrite(LED_BUILTIN, HIGH); 55 | 56 | // read bytes 57 | uint32_t data = 1; 58 | for(uint8_t i=24; i; i--) { 59 | duration = pulseIn(DATA_PIN, HIGH, 10 * RF_ERR); 60 | if ((duration < RF_ERR) || (duration > (5 * RF_ERR))) break; 61 | data <<= 1; 62 | if (duration > (3 * RF_ERR)) data |= 1; 63 | } 64 | 65 | // check reading 66 | if (data & 0x01000000) { 67 | Serial.println("Telegram received:"); 68 | Serial.print("Address: "); Serial.println((data >> 16) & 0xFF, HEX); 69 | Serial.print("Command: "); Serial.println((data >> 8) & 0xFF, HEX); 70 | Serial.print("Inverse: "); Serial.println( data & 0xFF, HEX); 71 | if(((data >> 8) & 0xFF) == (~data & 0xFF)) Serial.println("Valid Code Reading"); 72 | else Serial.println("Invalid Code Reading"); 73 | } 74 | else Serial.println("Incomplete Reading !"); 75 | } 76 | -------------------------------------------------------------------------------- /software/remote_4_buttons/RF_Remote_4B.ino: -------------------------------------------------------------------------------- 1 | // tinyRemoteRF for ATtiny13A - 4 Buttons 2 | // 3 | // RF remote control using an ATtiny 13A. This demo code implements a 4 | // simple but robust and DC-free protocol which is easy to decode and 5 | // does not require precise timing. It operates with ASK/OOK (Amplitude 6 | // Shift Keying / On-Off Keyed). 7 | // 8 | // Pulse lengths are derived from an adjustable error width (RF_ERR). 9 | // A "0" bit is a 2 * RF_ERR long burst and an equally long space, a 10 | // "1" bit is a 4 * RF_ERR long burst and an equally long space. A 11 | // start bit is a 6 * RF_ERR long burst and an equally long space. 12 | // 13 | // +-------+ +---+ +-----+ +---+ +- ON 14 | // | | | | | | | | | start: 6 * ERR 15 | // | 6 | 6 | 2 | 2 | 4 | 4 | 2 | 2 | ... bit0: 2 * ERR 16 | // | | | | | | | | | bit1: 4 * ERR 17 | // -+ +-------+ +---+ +-----+ +---+ OFF 18 | // 19 | // |<--- start --->|<-"0"->|<---"1"--->|<-"0"->| 20 | // 21 | // An RF telegram starts with the preamble in which a defined number 22 | // of "0" bits are transmitted to wake up the receiver and allow it to 23 | // set its automatic gain. The following start bits signify the 24 | // start of the transmission. Afterwards three data bytes are transmitted, 25 | // most significant bit first. The three data bytes are in order: 26 | // - the 8-bit address of the device, 27 | // - the 8-bit key-dependent command and 28 | // - the 8-bit logical inverse of the command. 29 | // After the last bit a space of at least 8 * RF_ERR signifies the end 30 | // of the transmission. The transmission can be repeated several times. 31 | // 32 | // The code utilizes the sleep mode power down function. The device will 33 | // work several months on a CR2032 battery. 34 | // 35 | // +-\/-+ 36 | // KEY5 --- A0 (D5) PB5 1| |8 Vcc 37 | // KEY3 --- A3 (D3) PB3 2| |7 PB2 (D2) A1 --- KEY2 38 | // KEY4 --- A2 (D4) PB4 3| |6 PB1 (D1) ------ KEY1 39 | // GND 4| |5 PB0 (D0) ------ DATA 40 | // +----+ 41 | // 42 | // Controller: ATtiny13 43 | // Core: MicroCore (https://github.com/MCUdude/MicroCore) 44 | // Clockspeed: 1.2 MHz internal 45 | // BOD: BOD disabled (energy saving) 46 | // Timing: Micros disabled 47 | // 48 | // Note: The internal oscillator may need to be calibrated for the device 49 | // to function properly. 50 | // 51 | // 2020 by Stefan Wagner 52 | // Project Files (EasyEDA): https://easyeda.com/wagiminator 53 | // Project Files (Github): https://github.com/wagiminator 54 | // License: http://creativecommons.org/licenses/by-sa/3.0/ 55 | 56 | 57 | // oscillator calibration value (uncomment and set if necessary) 58 | //#define OSCCAL_VAL 0x4B 59 | 60 | // libraries 61 | #include 62 | #include 63 | #include 64 | #include 65 | 66 | // pin definitions 67 | #define DATA PB0 68 | #define KEY1 PB1 69 | #define KEY2 PB2 70 | #define KEY3 PB3 71 | #define KEY4 PB4 72 | #define KEY5 PB5 73 | 74 | // RF Codes 75 | #define ADDR 0x55 // address of the device 76 | #define CMD1 0x01 // command KEY1 77 | #define CMD2 0x02 // command KEY2 78 | #define CMD3 0x03 // command KEY3 79 | #define CMD4 0x04 // command KEY4 80 | #define CMD5 0x05 // command KEY5 81 | 82 | // button mask 83 | #define BT_MASK (1< $(TARGET).asm 74 | 75 | size: 76 | @echo "FLASH: $(shell avr-size -d $(TARGET).bin | awk '/[0-9]/ {print $$1 + $$2}') bytes" 77 | @echo "SRAM: $(shell avr-size -d $(TARGET).bin | awk '/[0-9]/ {print $$2 + $$3}') bytes" 78 | 79 | removetemp: 80 | @echo "Removing temporary files ..." 81 | @$(CLEAN) 82 | 83 | removebin: 84 | @echo "Removing $(TARGET).bin ..." 85 | @rm -f $(TARGET).bin 86 | -------------------------------------------------------------------------------- /software/remote_5_buttons/RF_Remote_5B.ino: -------------------------------------------------------------------------------- 1 | // tinyRemoteRF for ATtiny13A - 5 Buttons 2 | // 3 | // RF remote control using an ATtiny 13A. This demo code implements a 4 | // simple but robust and DC-free protocol which is easy to decode and 5 | // does not require precise timing. It operates with ASK/OOK (Amplitude 6 | // Shift Keying / On-Off Keyed). 7 | // 8 | // Pulse lengths are derived from an adjustable error width (RF_ERR). 9 | // A "0" bit is a 2 * RF_ERR long burst and an equally long space, a 10 | // "1" bit is a 4 * RF_ERR long burst and an equally long space. A 11 | // start bit is a 6 * RF_ERR long burst and an equally long space. 12 | // 13 | // +-------+ +---+ +-----+ +---+ +- ON 14 | // | | | | | | | | | start: 6 * ERR 15 | // | 6 | 6 | 2 | 2 | 4 | 4 | 2 | 2 | ... bit0: 2 * ERR 16 | // | | | | | | | | | bit1: 4 * ERR 17 | // -+ +-------+ +---+ +-----+ +---+ OFF 18 | // 19 | // |<--- start --->|<-"0"->|<---"1"--->|<-"0"->| 20 | // 21 | // An RF telegram starts with the preamble in which a defined number 22 | // of "0" bits are transmitted to wake up the receiver and allow it to 23 | // set its automatic gain. The following start bits signify the 24 | // start of the transmission. Afterwards three data bytes are transmitted, 25 | // most significant bit first. The three data bytes are in order: 26 | // - the 8-bit address of the device, 27 | // - the 8-bit key-dependent command and 28 | // - the 8-bit logical inverse of the command. 29 | // After the last bit a space of at least 8 * RF_ERR signifies the end 30 | // of the transmission. The transmission can be repeated several times. 31 | // 32 | // The code utilizes the sleep mode power down function. The device will 33 | // work several months on a CR2032 battery. 34 | // 35 | // +-\/-+ 36 | // KEY5 --- A0 (D5) PB5 1| |8 Vcc 37 | // KEY3 --- A3 (D3) PB3 2| |7 PB2 (D2) A1 --- KEY2 38 | // KEY4 --- A2 (D4) PB4 3| |6 PB1 (D1) ------ KEY1 39 | // GND 4| |5 PB0 (D0) ------ DATA 40 | // +----+ 41 | // 42 | // Controller: ATtiny13 43 | // Core: MicroCore (https://github.com/MCUdude/MicroCore) 44 | // Clockspeed: 1.2 MHz internal 45 | // BOD: BOD disabled (energy saving) 46 | // Timing: Micros disabled 47 | // 48 | // Reset pin must be disabled by writing respective fuse after uploading the code: 49 | // avrdude -p attiny13 -c usbasp -U lfuse:w:0x2a:m -U hfuse:w:0xfe:m 50 | // Warning: You will need a high voltage fuse resetter to undo this change! 51 | // 52 | // Note: The internal oscillator may need to be calibrated for the device 53 | // to function properly. 54 | // 55 | // 2020 by Stefan Wagner 56 | // Project Files (EasyEDA): https://easyeda.com/wagiminator 57 | // Project Files (Github): https://github.com/wagiminator 58 | // License: http://creativecommons.org/licenses/by-sa/3.0/ 59 | 60 | 61 | // oscillator calibration value (uncomment and set if necessary) 62 | //#define OSCCAL_VAL 0x4B 63 | 64 | // libraries 65 | #include 66 | #include 67 | #include 68 | #include 69 | 70 | // pin definitions 71 | #define DATA PB0 72 | #define KEY1 PB1 73 | #define KEY2 PB2 74 | #define KEY3 PB3 75 | #define KEY4 PB4 76 | #define KEY5 PB5 77 | 78 | // RF Codes 79 | #define ADDR 0x55 // address of the device 80 | #define CMD1 0x01 // command KEY1 81 | #define CMD2 0x02 // command KEY2 82 | #define CMD3 0x03 // command KEY3 83 | #define CMD4 0x04 // command KEY4 84 | #define CMD5 0x05 // command KEY5 85 | 86 | // button mask 87 | #define BT_MASK (1< $(TARGET).asm 75 | 76 | size: 77 | @echo "FLASH: $(shell avr-size -d $(TARGET).bin | awk '/[0-9]/ {print $$1 + $$2}') bytes" 78 | @echo "SRAM: $(shell avr-size -d $(TARGET).bin | awk '/[0-9]/ {print $$2 + $$3}') bytes" 79 | 80 | removetemp: 81 | @echo "Removing temporary files ..." 82 | @$(CLEAN) 83 | 84 | removebin: 85 | @echo "Removing $(TARGET).bin ..." 86 | @rm -f $(TARGET).bin 87 | --------------------------------------------------------------------------------