1/* 2 * ReceiveOneAndSendMultiple.cpp 3 * 4 * Serves as a IR remote macro expander 5 * Receives Samsung32 protocol and on receiving a specified input frame, 6 * it sends multiple Samsung32 frames with appropriate delays in between. 7 * This serves as a Netflix-key emulation for my old Samsung H5273 TV. 8 * 9 * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. 10 * 11 ************************************************************************************ 12 * MIT License 13 * 14 * Copyright (c) 2020-2021 Armin Joachimsmeyer 15 * 16 * Permission is hereby granted, free of charge, to any person obtaining a copy 17 * of this software and associated documentation files (the "Software"), to deal 18 * in the Software without restriction, including without limitation the rights 19 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 * copies of the Software, and to permit persons to whom the Software is furnished 21 * to do so, subject to the following conditions: 22 * 23 * The above copyright notice and this permission notice shall be included in all 24 * copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 27 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 28 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 29 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 30 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 31 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 * 33 ************************************************************************************ 34 */ 35 36// Digispark ATMEL ATTINY85 37// Piezo speaker must have a 270 Ohm resistor in series for USB programming and running at the Samsung TV. 38// IR LED has a 270 Ohm resistor in series. 39// +-\/-+ 40// !RESET (5) PB5 1| |8 Vcc 41// USB+ 3.6V Z-Diode, 1.5kOhm to VCC Piezo (3) PB3 2| |7 PB2 (2) TX Debug output 42// USB- 3.6V Z-Diode IR Output (4) PB4 3| |6 PB1 (1) Feedback LED 43// GND 4| |5 PB0 (0) IR Input 44// +----+ 45#include <Arduino.h> 46 47// select only Samsung protocol for sending and receiving 48#define DECODE_SAMSUNG 49#define ADDRESS_OF_SAMSUNG_REMOTE 0x0707 // The value you see as address in printIRResultShort() 50/* 51 * Define macros for input and output pin etc. 52 */ 53#include "PinDefinitionsAndMore.h" 54 55#include <IRremote.hpp> 56 57void sendSamsungSmartHubMacro(bool aDoSelect); 58void IRSendWithDelay(uint8_t aCommand, uint16_t aDelayMillis); 59 60void setup() { 61 pinMode(LED_BUILTIN, OUTPUT); 62 63 Serial.begin(115200); 64#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) || defined(ARDUINO_attiny3217) 65 delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! 66#endif 67 // Just to know which program is running on my Arduino 68 Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE)); 69 70 // tone before IR setup, since it kills the IR timer settings 71 tone(TONE_PIN, 2200); 72 digitalWrite(LED_BUILTIN, HIGH); 73 delay(400); 74 digitalWrite(LED_BUILTIN, LOW); 75 noTone(TONE_PIN); 76 77 /* 78 * Start the receiver, enable feedback LED and take LED feedback pin from the internal boards definition 79 */ 80 IrReceiver.begin(IR_RECEIVE_PIN); 81 IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin 82 83 Serial.print(F("Ready to receive IR signals of protocols: ")); 84 printActiveIRProtocols(&Serial); 85 Serial.print(F("at pin ")); 86#if defined(ARDUINO_ARCH_STM32) || defined(ESP8266) 87 Serial.println(IR_RECEIVE_PIN_STRING); 88#else 89 Serial.println(IR_RECEIVE_PIN); 90#endif 91 Serial.print(F("Ready to send IR signals at pin ")); 92#if defined(ARDUINO_ARCH_STM32) || defined(ESP8266) 93 Serial.println(IR_SEND_PIN_STRING); 94#else 95 Serial.println(IR_SEND_PIN); 96#endif 97 98} 99 100void loop() { 101 /* 102 * Check if new data available and get them 103 */ 104 if (IrReceiver.decode()) { 105 // Print a short summary of received data 106 IrReceiver.printIRResultShort(&Serial); 107 Serial.println(); 108 109 /* 110 * Here data is available -> evaluate IR command 111 */ 112 switch (IrReceiver.decodedIRData.command) { 113 case 0x47: // The play key on the bottom of my Samsung remote 114 Serial.println(F("Play key detected, open Netflix")); 115 sendSamsungSmartHubMacro(true); 116 break; 117 118 case 0x4A: // The pause key on the bottom of my Samsung remote 119 Serial.println(F("Pause key detected, open SmartHub")); 120 sendSamsungSmartHubMacro(false); 121 break; 122 123 default: 124 break; 125 } 126 127 /* 128 * !!!Important!!! Enable receiving of the next value, 129 * since receiving has stopped after the end of the current received data packet. 130 */ 131 IrReceiver.resume(); // Enable receiving of the next value 132 } 133} 134 135void IRSendWithDelay(uint8_t aCommand, uint16_t aDelayMillis) { 136 IrSender.sendSamsung(ADDRESS_OF_SAMSUNG_REMOTE, aCommand, 1); // send with one repeat 137 Serial.print(F("Send Samsung command 0x")); 138 Serial.println(aCommand); 139 delay(aDelayMillis); 140} 141 142bool sMacroWasCalledBefore = false; 143#define INITIAL_WAIT_TIME_APPS_READY_MILLIS 70000 // Time to let the TV load all software before Netflix can be started without an error 144#define INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS 20000 // Time to let the TV load all software before SmartHub manu can be displayed 145 146/* 147 * This macro calls the last SmartHub application you selected manually 148 * 149 * @param aDoSelect - if true select the current app (needs longer initial wait time) else show smarthub menu 150 * 151 */ 152void sendSamsungSmartHubMacro(bool aDoSelect) { 153 uint32_t tWaitTimeAfterBoot; 154 if (aDoSelect) { 155 tWaitTimeAfterBoot = INITIAL_WAIT_TIME_APPS_READY_MILLIS; 156 } else { 157 tWaitTimeAfterBoot = INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS; 158 } 159 160# if !defined(ESP32) 161 IrReceiver.stop(); // ESP32 uses another timer for tone() 162# endif 163 if (millis() < tWaitTimeAfterBoot) { 164 // division by 1000 and printing requires much (8%) program space 165 Serial.print(F("It is ")); 166 Serial.print(millis() / 1000); 167 Serial.print(F(" seconds after boot, Samsung H5273 TV requires ")); 168 Serial.print(tWaitTimeAfterBoot / 1000); 169 Serial.println(F(" seconds after boot to be ready for the command")); 170 171 tone(TONE_PIN, 2200); 172 delay(100); 173 noTone(TONE_PIN); 174 delay(100); 175 tone(TONE_PIN, 2200); 176 delay(100); 177 noTone(TONE_PIN); 178 179 if (millis() < tWaitTimeAfterBoot) { 180 Serial.print(F("Now do a blocking wait for ")); 181 Serial.print(tWaitTimeAfterBoot - millis()); 182 Serial.println(F(" milliseconds")); 183 delay(tWaitTimeAfterBoot - millis()); 184 } 185 } 186 187 // Do beep feedback for special key to be received 188 tone(TONE_PIN, 2200); 189 delay(200); 190 noTone(TONE_PIN); 191# if !defined(ESP32) 192 IrReceiver.start(200000); // to compensate for 200 ms stop of receiver. This enables a correct gap measurement. 193# endif 194 195 Serial.println(F("Wait for \"not supported\" to disappear")); 196 delay(2000); 197 198 Serial.println(F("Start sending of Samsung IR macro")); 199 200 IRSendWithDelay(0x1A, 2000); // Menu and wait for the Menu to pop up 201 202 Serial.println(F("Wait for the menu to pop up")); 203 if (!sMacroWasCalledBefore) { 204 delay(2000); // wait additional time for the Menu load 205 } 206 207 for (uint_fast8_t i = 0; i < 4; ++i) { 208 IRSendWithDelay(0x61, 250); // Down arrow. For my Samsung, the high byte of the command is the inverse of the low byte 209 } 210 211 IRSendWithDelay(0x62, 400); // Right arrow 212 for (uint_fast8_t i = 0; i < 2; ++i) { 213 IRSendWithDelay(0x61, 250); // Down arrow 214 } 215 216 delay(250); 217 IRSendWithDelay(0x68, 1); // Enter for SmartHub 218 219 if (aDoSelect) { 220 Serial.println(F("Wait for SmartHub to show up, before entering current application")); 221 delay(10000); // Wait not longer than 12 seconds, because smarthub menu then disappears 222 IRSendWithDelay(0x68, 1); // Enter for last application (e.g. Netflix or Amazon) 223 } 224 225 sMacroWasCalledBefore = true; 226 Serial.println(F("Done")); 227 228} 229