Hello Everyone!
I have been working on this for a while now, going through various forums, threads and methods but to no avail, my ac refuses to detect the signal from my IR Transmitter. I'm providing all the details I can in hopes someone can decipher what I am missing.
Board: Arduino Uno
Voltage Supply: 5V from Arduino Uno onto a breadboard
IR Receiver [Pin 2]: KY-022 Module KY-022 Infrared Receiver Module - ArduinoModulesInfo
IR Transmitter [Pin 3]: Standard IR LED, 2N2222 Transistor, 100 ohm Resistor https://europe1.discourse-cdn.com/arduino/original/4X/1/9/4/1940fcb591fe5901aa19f3ac81ef0ceaae27294a.png
AC Model: Hitachi Split AC (RAS.B318PCAIBA) Attached a picture for reference
AC Remote: Attached a picture for reference
I was able to capture the raw signal using the Arduino-IRremote-master ReceiveAndSend example.
/*
* ReceiveAndSend.cpp
*
* Record and play back last received IR signal at button press.
* The logic is:
* If the button is pressed, send the IR code.
* If an IR code is received, record it.
* If the protocol is unknown or not enabled, store it as raw data for later sending.
*
* An example for simultaneous receiving and sending is in the UnitTest example.
*
* An IR detector/demodulator must be connected to the input IR_RECEIVE_PIN.
*
* A button must be connected between the input SEND_BUTTON_PIN and ground.
* A visible LED can be connected to STATUS_PIN to provide status.
*
* See also https://dronebotworkshop.com/ir-remotes/#ReceiveAndSend_Code
*
* Initially coded 2009 Ken Shirriff http://www.righto.com
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2009-2025 Ken Shirriff, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#include <Arduino.h>
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
/*
* Specify which protocol(s) should be used for decoding.
* If no protocol is defined, all protocols (except Bang&Olufsen) are active.
* This must be done before the #include <IRremote.hpp>
*/
//#define DECODE_DENON // Includes Sharp
//#define DECODE_JVC
//#define DECODE_KASEIKYO
//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
//#define DECODE_LG
//#define DECODE_NEC // Includes Apple and Onkyo
//#define DECODE_SAMSUNG
//#define DECODE_SONY
//#define DECODE_RC5
//#define DECODE_RC6
//#define DECODE_BOSEWAVE
//#define DECODE_LEGO_PF
//#define DECODE_MAGIQUEST
//#define DECODE_WHYNTER
//#define DECODE_FAST
//
#if !defined(RAW_BUFFER_LENGTH)
// For air condition remotes it may require up to 750. Default is 200.
# if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF))
#define RAW_BUFFER_LENGTH 700 // we require 2 buffer of this size for this example
# endif
#endif
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135.
// 20 is taken as default if not otherwise specified / defined.
//#define MARK_EXCESS_MICROS 40 // Adapt it to your IR receiver module. 40 is recommended for the cheap VS1838 modules at high intensity.
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
#include <IRremote.hpp>
int SEND_BUTTON_PIN = APPLICATION_PIN;
int DELAY_BETWEEN_REPEAT = 50;
// Storage for the recorded code
struct storedIRDataStruct {
IRData receivedIRData;
// extensions for sendRaw
uint8_t rawCode[RAW_BUFFER_LENGTH]; // The durations if raw
uint8_t rawCodeLength; // The length of the code
} sStoredIRData;
bool sSendButtonWasActive;
void storeCode();
void sendCode(storedIRDataStruct *aIRDataToSend);
void setup() {
pinMode(SEND_BUTTON_PIN, INPUT_PULLUP);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
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!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
// Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
Serial.print(F("Ready to send IR signal (with repeats) at pin " STR(IR_SEND_PIN) " as long as button at pin "));
Serial.print(SEND_BUTTON_PIN);
Serial.println(F(" is pressed."));
}
void loop() {
// If button pressed, send the code.
bool tSendButtonIsActive = (digitalRead(SEND_BUTTON_PIN) == LOW); // Button pin is active LOW
/*
* Check for current button state
*/
if (tSendButtonIsActive) {
if (!sSendButtonWasActive) {
Serial.println(F("Stop receiving"));
IrReceiver.stop();
}
/*
* Button pressed -> send stored data
*/
Serial.print(F("Button pressed, now sending "));
if (sSendButtonWasActive == tSendButtonIsActive) {
Serial.print(F("repeat "));
sStoredIRData.receivedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
} else {
sStoredIRData.receivedIRData.flags = IRDATA_FLAGS_EMPTY;
}
Serial.flush(); // To avoid disturbing the software PWM generation by serial output interrupts
sendCode(&sStoredIRData);
delay(DELAY_BETWEEN_REPEAT); // Wait a bit between retransmissions
} else if (sSendButtonWasActive) {
/*
* Button is just released -> activate receiving
*/
// Restart receiver
Serial.println(F("Button released -> start receiving"));
IrReceiver.start();
delay(100); // Button debouncing
} else if (IrReceiver.decode()) {
/*
* Button is not pressed and data available -> store received data and resume
*/
storeCode();
IrReceiver.resume(); // resume receiver
}
sSendButtonWasActive = tSendButtonIsActive;
}
// Stores the code for later playback in sStoredIRData
// Most of this code is just logging
void storeCode() {
if (IrReceiver.decodedIRData.rawDataPtr->rawlen < 4) {
Serial.print(F("Ignore data with rawlen="));
Serial.println(IrReceiver.decodedIRData.rawDataPtr->rawlen);
return;
}
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
Serial.println(F("Ignore repeat"));
return;
}
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_AUTO_REPEAT) {
Serial.println(F("Ignore autorepeat"));
return;
}
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_PARITY_FAILED) {
Serial.println(F("Ignore parity error"));
return;
}
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) {
Serial.println(F("Overflow occurred, raw data did not fit into " STR(RAW_BUFFER_LENGTH) " byte raw buffer"));
return;
}
/*
* Copy decoded data
*/
sStoredIRData.receivedIRData = IrReceiver.decodedIRData;
auto tProtocol = sStoredIRData.receivedIRData.protocol;
if (tProtocol == UNKNOWN || tProtocol == PULSE_WIDTH || tProtocol == PULSE_DISTANCE) {
// TODO: support PULSE_WIDTH and PULSE_DISTANCE with IrSender.write
sStoredIRData.rawCodeLength = IrReceiver.decodedIRData.rawDataPtr->rawlen - 1;
/*
* Store the current raw data in a dedicated array for later usage
*/
IrReceiver.compensateAndStoreIRResultInArray(sStoredIRData.rawCode);
/*
* Print info
*/
Serial.print(F("Received unknown code and store "));
Serial.print(IrReceiver.decodedIRData.rawDataPtr->rawlen - 1);
Serial.println(F(" timing entries as raw in buffer of size " STR(RAW_BUFFER_LENGTH)));
IrReceiver.printIRResultRawFormatted(&Serial, true); // Output the results in RAW format
} else {
IrReceiver.printIRResultShort(&Serial);
IrReceiver.printIRSendUsage(&Serial);
sStoredIRData.receivedIRData.flags = 0; // clear flags -esp. repeat- for later sending
Serial.println();
}
}
void sendCode(storedIRDataStruct *aIRDataToSend) {
auto tProtocol = aIRDataToSend->receivedIRData.protocol;
if (tProtocol == UNKNOWN || tProtocol == PULSE_WIDTH || tProtocol == PULSE_DISTANCE /* i.e. raw */) {
// Assume 38 KHz
IrSender.sendRaw(aIRDataToSend->rawCode, aIRDataToSend->rawCodeLength, 38);
Serial.print(F("raw "));
Serial.print(aIRDataToSend->rawCodeLength);
Serial.println(F(" marks or spaces"));
} else {
/*
* Use the write function, which does the switch for different protocols
*/
IrSender.write(&aIRDataToSend->receivedIRData);
printIRResultShort(&Serial, &aIRDataToSend->receivedIRData);
}
}
This is the output I get.
OFF
Received unknown code and store 451 timing entries as raw in buffer of size 700
rawData[452]:
-49350
+3350,-1700
+ 400,-1250 + 400,- 450 + 400,- 450 + 400,- 400
+ 400,- 450 + 400,- 450 + 350,- 450 + 400,- 450
+ 400,- 450 + 400,- 450 + 400,- 400 + 400,- 450
+ 400,-1300 + 400,- 400 + 400,- 450 + 400,- 450
+ 400,- 450 + 400,- 400 + 400,- 450 + 400,- 450
+ 350,-1300 + 400,-1300 + 350,- 450 + 450,- 400
+ 400,- 450 + 400,- 450 + 400,- 400 + 450,- 400
+ 400,- 450 + 400,- 450 + 350,-1300 + 400,- 450
+ 400,-1250 + 400,-1300 + 400,-1250 + 400,-1300
+ 400,-1250 + 400,-1300 + 400,- 400 + 400,-1300
+ 400,-1250 + 400,- 450 + 400,- 450 + 400,- 400
+ 400,- 450 + 400,- 450 + 400,- 400 + 450,- 400
+ 450,- 400 + 400,-1250 + 450,-1250 + 400,-1250
+ 450,-1250 + 400,-1250 + 400,-1300 + 400,-1250
+ 400,-1300 + 400,- 400 + 450,- 400 + 400,- 450
+ 400,-1250 + 400,- 450 + 400,- 450 + 400,- 450
+ 350,- 450 + 400,-1300 + 350,- 450 + 450,- 400
+ 400,-1300 + 400,- 400 + 400,- 450 + 400,- 450
+ 400,-1250 + 400,-1300 + 400,- 400 + 450,- 400
+ 400,- 450 + 400,- 450 + 400,- 400 + 400,- 450
+ 400,- 450 + 350,- 500 + 400,-1250 + 400,- 450
+ 400,- 400 + 450,- 400 + 400,- 450 + 400,- 450
+ 400,- 400 + 450,- 400 + 400,- 450 + 400,-1250
+ 400,-1300 + 400,-1300 + 400,- 400 + 400,- 450
+ 400,- 400 + 450,- 400 + 400,- 450 + 400,- 450
+ 400,- 400 + 400,- 450 + 400,- 450 + 400,- 450
+ 400,-1250 + 400,- 450 + 400,- 400 + 450,- 400
+ 400,- 450 + 400,- 450 + 400,- 400 + 450,- 400
+ 400,- 450 + 400,-1250 + 450,-1250 + 400,- 450
+ 400,- 400 + 400,- 450 + 400,- 450 + 400,- 450
+ 400,- 400 + 400,-1300 + 400,-1250 + 400,- 450
+ 400,- 450 + 400,- 400 + 450,- 450 + 350,- 450
+ 400,- 450 + 400,- 450 + 350,- 450 + 400,- 450
+ 400,- 450 + 400,- 400 + 400,- 450 + 400,- 450
+ 400,- 400 + 450,- 450 + 350,- 450 + 400,- 450
+ 400,- 450 + 350,- 500 + 350,- 450 + 400,- 450
+ 400,- 450 + 350,- 500 + 350,- 450 + 400,- 450
+ 400,- 450 + 350,- 450 + 400,- 450 + 400,- 450
+ 400,- 450 + 350,- 450 + 400,- 450 + 400,- 450
+ 350,- 500 + 350,- 450 + 400,- 450 + 400,- 450
+ 350,- 500 + 350,- 450 + 400,- 450 + 400,- 450
+ 350,- 450 + 400,- 450 + 400,- 450 + 350,- 500
+ 350,- 450 + 400,- 450 + 400,- 450 + 350,- 500
+ 350,- 450 + 400,- 450 + 400,- 450 + 400,- 450
+ 350,- 450 + 400,- 450 + 400,- 450 + 350,- 450
+ 400,- 450 + 400,- 450 + 350,- 500 + 350,- 450
+ 400,- 450 + 400,- 450 + 350,- 500 + 350,- 450
+ 400,- 450 + 400,- 450 + 350,- 500 + 350,- 450
+ 400,-1300 + 350,- 450 + 400,- 450 + 400,- 450
+ 350,- 500 + 350,- 450 + 400,- 450 + 400,- 450
+ 350,- 500 + 350,- 450 + 400,- 450 + 400,-1300
+ 350,- 450 + 400,- 450 + 350,- 500 + 350,- 450
+ 400,- 450 + 400,- 450 + 350,- 500 + 350,- 450
+ 400,- 450 + 400,- 450 + 350,- 500 + 350,-1300
+ 350,-1300 + 400,-1300 + 350,-1300 + 400,- 450
+ 400,- 450 + 350,- 500 + 350,- 450 + 400,- 450
+ 400
Duration=227150us
ON
Ignore data with rawlen=2
Received unknown code and store 451 timing entries as raw in buffer of size 700
rawData[452]:
-49400
+3300,-1700
+ 400,-1300 + 400,- 400 + 400,- 450 + 400,- 450
+ 400,- 400 + 450,- 400 + 400,- 450 + 400,- 450
+ 350,- 450 + 450,- 400 + 400,- 450 + 400,- 450
+ 400,-1250 + 400,- 450 + 350,- 500 + 350,- 450
+ 400,- 450 + 400,- 450 + 400,- 400 + 450,- 400
+ 400,-1300 + 400,-1250 + 400,- 450 + 400,- 450
+ 350,- 450 + 400,- 450 + 400,- 450 + 400,- 400
+ 400,- 450 + 400,- 450 + 400,-1250 + 450,- 400
+ 400,-1300 + 400,-1250 + 400,-1250 + 400,-1300
+ 400,-1250 + 400,-1300 + 400,- 450 + 400,-1250
+ 400,-1300 + 400,- 400 + 400,- 450 + 400,- 450
+ 350,- 450 + 400,- 450 + 400,- 450 + 400,- 450
+ 350,- 450 + 450,-1250 + 400,-1250 + 450,-1250
+ 400,-1250 + 400,-1300 + 350,-1300 + 400,-1300
+ 400,-1250 + 400,- 450 + 400,- 450 + 400,- 400
+ 400,-1300 + 350,- 500 + 400,- 400 + 400,- 450
+ 400,- 450 + 400,-1250 + 400,- 450 + 400,- 450
+ 350,-1300 + 400,- 450 + 400,- 400 + 450,- 400
+ 400,-1300 + 350,-1300 + 400,- 450 + 400,- 450
+ 400,- 400 + 450,- 400 + 400,- 450 + 400,- 400
+ 450,- 400 + 400,- 450 + 400,-1300 + 400,- 400
+ 400,- 450 + 400,- 450 + 400,- 400 + 450,- 400
+ 400,- 450 + 400,- 450 + 400,- 400 + 400,-1300
+ 400,-1250 + 400,-1300 + 400,- 400 + 450,- 400
+ 400,- 450 + 400,- 450 + 350,- 450 + 450,- 400
+ 400,- 450 + 400,- 450 + 400,- 400 + 400,- 450
+ 400,-1300 + 400,- 400 + 400,- 450 + 450,- 400
+ 400,- 400 + 450,- 400 + 400,- 450 + 400,- 450
+ 400,- 400 + 400,-1300 + 350,-1300 + 400,- 450
+ 400,- 450 + 400,- 450 + 400,- 400 + 400,- 450
+ 400,- 450 + 400,-1300 + 350,-1300 + 400,- 400
+ 400,- 500 + 350,- 500 + 350,- 450 + 400,- 450
+ 350,- 500 + 350,- 450 + 400,- 450 + 400,- 450
+ 350,- 450 + 400,- 450 + 400,- 450 + 350,- 500
+ 350,- 450 + 400,- 450 + 400,- 450 + 350,- 500
+ 350,- 450 + 400,- 450 + 400,- 450 + 350,-1300
+ 400,- 450 + 400,- 450 + 350,- 450 + 400,- 450
+ 400,- 450 + 350,- 500 + 350,- 450 + 400,- 450
+ 400,- 450 + 350,- 500 + 350,- 450 + 400,- 450
+ 350,- 500 + 350,- 450 + 400,- 450 + 400,- 450
+ 350,- 500 + 350,- 450 + 400,- 450 + 400,- 450
+ 350,- 500 + 350,- 450 + 400,- 450 + 400,- 450
+ 350,- 450 + 400,- 450 + 400,- 450 + 350,- 500
+ 350,- 450 + 400,- 450 + 400,- 450 + 350,- 500
+ 350,- 450 + 400,- 450 + 400,- 450 + 400,- 450
+ 350,- 450 + 400,- 450 + 350,- 500 + 350,- 450
+ 400,- 450 + 400,- 450 + 350,- 500 + 350,- 450
+ 400,- 450 + 400,- 450 + 350,- 500 + 350,- 450
+ 400,-1300 + 350,- 450 + 400,- 450 + 400,- 450
+ 350,- 500 + 350,- 450 + 400,- 450 + 400,- 450
+ 350,- 500 + 350,- 450 + 400,- 450 + 400,-1300
+ 350,- 450 + 400,- 450 + 350,- 500 + 350,- 450
+ 400,- 450 + 400,- 450 + 350,- 500 + 350,- 450
+ 400,- 450 + 400,- 450 + 350,- 500 + 350,- 450
+ 400,-1300 + 350,-1300 + 400,-1300 + 350,- 450
+ 400,- 450 + 400,- 450 + 350,- 500 + 350,- 450
+ 400
Duration=227100us
I also used the ReceiveAndSendDistanceWidth example
/*
* ReceiveAndSendDistanceWidth.cpp
*
* Record and play back last received distance width IR signal at button press.
* Using DistanceWidthProtocol covers a lot of known and unknown IR protocols,
* and requires less memory than raw protocol.
*
* The logic is:
* If the button is pressed, send the IR code.
* If an IR code is received, record it.
*
* An example for simultaneous receiving and sending is in the UnitTest example.
*
* An IR detector/demodulator must be connected to the input IR_RECEIVE_PIN.
*
* A button must be connected between the input SEND_BUTTON_PIN and ground.
* A visible LED can be connected to STATUS_PIN to provide status.
*
* See also https://dronebotworkshop.com/ir-remotes/#ReceiveAndSendDistanceWidth_Code
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2023 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#include <Arduino.h>
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if !defined(IR_SEND_PIN)
#define IR_SEND_PIN 3
#endif
/*
* Specify DistanceWidthProtocol for decoding. This must be done before the #include <IRremote.hpp>
*/
#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
//
#if !defined(RAW_BUFFER_LENGTH)
// For air condition remotes it may require up to 750. Default is 200.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 360
# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
#define RAW_BUFFER_LENGTH 750
# endif
#endif
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
#include <IRremote.hpp>
#define SEND_BUTTON_PIN APPLICATION_PIN
#define DELAY_BETWEEN_REPEATS_MILLIS 70
// Storage for the recorded code, pre-filled with NEC data
IRRawDataType sDecodedRawDataArray[DECODED_RAW_DATA_ARRAY_SIZE] = { 0x7B34ED12 }; // Initialize with NEC address 0x12 and command 0x34
DistanceWidthTimingInfoStruct sDistanceWidthTimingInfo = { 9000, 4500, 560, 1690, 560, 560 }; // Initialize with NEC timing
uint8_t sNumberOfBits = 32;
bool sSendButtonWasActive;
void setup() {
pinMode(SEND_BUTTON_PIN, INPUT_PULLUP);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
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!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
// Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
Serial.println(F("Ready to receive pulse distance/width coded IR signals at pin " STR(IR_RECEIVE_PIN)));
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
Serial.print(F("Ready to send IR signals at pin " STR(IR_SEND_PIN) " on press of button at pin "));
Serial.println(SEND_BUTTON_PIN);
}
void loop() {
// If button pressed, send the code.
bool tSendButtonIsActive = (digitalRead(SEND_BUTTON_PIN) == LOW); // Button pin is active LOW
/*
* Check for current button state
*/
if (tSendButtonIsActive) {
if (!sSendButtonWasActive) {
Serial.println(F("Stop receiving"));
IrReceiver.stop();
}
/*
* Button pressed -> send stored data
*/
Serial.print(F("Button pressed, now sending "));
Serial.print(sNumberOfBits);
Serial.print(F(" bits 0x"));
Serial.print(sDecodedRawDataArray[0], HEX);
Serial.print(F(" with sendPulseDistanceWidthFromArray timing="));
IrReceiver.printDistanceWidthTimingInfo(&Serial, &sDistanceWidthTimingInfo);
Serial.println();
Serial.flush(); // To avoid disturbing the software PWM generation by serial output interrupts
IrSender.sendPulseDistanceWidthFromArray(38, &sDistanceWidthTimingInfo, &sDecodedRawDataArray[0], sNumberOfBits,
#if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
PROTOCOL_IS_MSB_FIRST
#else
PROTOCOL_IS_LSB_FIRST
#endif
, 100, 0);
delay(DELAY_BETWEEN_REPEATS_MILLIS); // Wait a bit between retransmissions
} else if (sSendButtonWasActive) {
/*
* Button is just released -> activate receiving
*/
// Restart receiver
Serial.println(F("Button released -> start receiving"));
IrReceiver.start();
} else if (IrReceiver.decode()) {
/*
* Button is not pressed and data available -> store received data and resume
* DistanceWidthTimingInfo and sNumberOfBits should be constant for all keys of the same IR remote / protocol
*/
IrReceiver.printIRResultShort(&Serial);
if (IrReceiver.decodedIRData.protocol != UNKNOWN) {
IrReceiver.printIRSendUsage(&Serial);
if (memcmp(&sDistanceWidthTimingInfo, &IrReceiver.decodedIRData.DistanceWidthTimingInfo,
sizeof(sDistanceWidthTimingInfo)) != 0) {
Serial.print(F("Store new timing info data="));
IrReceiver.printDistanceWidthTimingInfo(&Serial, &IrReceiver.decodedIRData.DistanceWidthTimingInfo);
Serial.println();
sDistanceWidthTimingInfo = IrReceiver.decodedIRData.DistanceWidthTimingInfo; // copy content here
} else {
Serial.print(F("Timing did not change, so we can reuse already stored timing info."));
}
if (sNumberOfBits != IrReceiver.decodedIRData.numberOfBits) {
Serial.print(F("Store new numberOfBits="));
sNumberOfBits = IrReceiver.decodedIRData.numberOfBits;
Serial.println(IrReceiver.decodedIRData.numberOfBits);
}
if (sDecodedRawDataArray[0] != IrReceiver.decodedIRData.decodedRawDataArray[0]) {
*sDecodedRawDataArray = *IrReceiver.decodedIRData.decodedRawDataArray; // copy content here
Serial.print(F("Store new sDecodedRawDataArray[0]=0x"));
Serial.println(IrReceiver.decodedIRData.decodedRawDataArray[0], HEX);
}
}
IrReceiver.resume(); // resume receiver
}
sSendButtonWasActive = tSendButtonIsActive;
delay(100);
}
and got this:
OFF
Protocol=UNKNOWN 1 bits (incl. gap and start) received
Protocol=PulseDistance Raw-Data=0x7800801 224 bits LSB first Gap=49300us Duration=227100us
Send on a 8 bit platform with:
uint32_t tRawData[]={0x40301001, 0x11FE01BF, 0x38040312, 0x6060100, 0x0, 0x0, 0x7800801};
IrSender.sendPulseDistanceWidthFromArray(38, 3400, 1650, 400, 1250, 400, 400, &tRawData[0], 224, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
Store new timing info data=3400, 1650, 400, 1250, 400, 400
ON
Protocol=PulseDistance Raw-Data=0x7000801 224 bits LSB first Gap=49300us Duration=227150us
Send on a 8 bit platform with:
uint32_t tRawData[]={0x40301001, 0x11FE01BF, 0x38040312, 0x6060100, 0x8000, 0x0, 0x7000801};
IrSender.sendPulseDistanceWidthFromArray(38, 3350, 1700, 400, 1250, 400, 400, &tRawData[0], 224, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
Store new timing info data=3350, 1700, 400, 1250, 400, 400
Using this code:
/*
Author: AnalysIR
Revision: 1.0 - Initial release
Revision: 1.1 - update generic digitalPinToInterrupt to support most arduino platform
This code is provided to overcome an issue with Arduino IR libraries
It allows you to capture raw timings for signals longer than 255 marks & spaces.
Typical use case is for long Air conditioner signals.
You can use the output to plug back into IRremote, to resend the signal.
This Software was written by AnalysIR.
Usage: Free to use, subject to conditions posted on blog below.
Please credit AnalysIR and provide a link to our website/blog, where possible.
Copyright AnalysIR 2014-2019
Please refer to the blog posting for conditions associated with use.
http://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino/
Connections:
IR Receiver Arduino
V+ -> +5v
GND -> GND
Signal Out -> Digital Pin 2
(If using a 3V3 Arduino, you should connect V+ to +3V3)
Tested on UNO only
*/
#define LEDPIN 13
//you may increase this value on Arduinos with greater than 2k SRAM
#define maxLen 800
#define rxPinIR 2 //pin D2 or D3 on standard arduinos. (other pins may be available on More mordern modules like MEga2560, DUE, ESP8266, ESP32)
volatile unsigned int irBuffer[maxLen]; //stores timings - volatile because changed by ISR
volatile unsigned int x = 0; //Pointer thru irBuffer - volatile because changed by ISR
void setup() {
Serial.begin(115200); //change BAUD rate as required
attachInterrupt(digitalPinToInterrupt(rxPinIR), rxIR_Interrupt_Handler, CHANGE);//set up ISR for receiving IR signal
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println(F("Press the button on the remote now - once only"));
delay(5000); // pause 5 secs
if (x) { //if a signal is captured
digitalWrite(LEDPIN, HIGH);//visual indicator that signal received
Serial.println();
Serial.print(F("Raw: (")); //dump raw header format - for library
Serial.print((x - 1));
Serial.print(F(") "));
detachInterrupt(digitalPinToInterrupt(rxPinIR));//stop interrupts & capture until finshed here
for (int i = 1; i < x; i++) { //now dump the times
if (!(i & 0x1)) Serial.print(F("-"));
Serial.print(irBuffer[i] - irBuffer[i - 1]);
Serial.print(F(", "));
}
x = 0;
Serial.println();
Serial.println();
digitalWrite(LEDPIN, LOW);//end of visual indicator, for this time
attachInterrupt(digitalPinToInterrupt(rxPinIR), rxIR_Interrupt_Handler, CHANGE);//re-enable ISR for receiving IR signal
}
}
void rxIR_Interrupt_Handler() {
if (x > maxLen) return; //ignore if irBuffer is already full
irBuffer[x++] = micros(); //just continually record the time-stamp of signal transitions
}
I get this:
OFF
Raw: (453) 30076, -49768, 3448, -1624, 476, -1212, 480, -364, 476, -372, 476, -368, 476, -368, 476, -368, 476, -368, 476, -372, 476, -368, 476, -368, 476, -368, 476, -368, 476, -1224, 476, -360, 476, -368, 476, -368, 476, -368, 476, -368, 480, -368, 476, -368, 476, -1212, 476, -1212, 480, -364, 480, -368, 476, -368, 476, -368, 476, -368, 476, -368, 480, -368, 476, -368, 480, -1208, 480, -364, 480, -1212, 476, -1212, 476, -1212, 480, -1212, 476, -1216, 476, -1212, 476, -368, 476, -1212, 476, -1212, 480, -364, 480, -368, 476, -368, 480, -364, 476, -368, 480, -364, 480, -368, 476, -368, 476, -1212, 480, -1208, 484, -1208, 476, -1212, 476, -1216, 476, -1212, 476, -1212, 476, -1212, 480, -368, 476, -368, 476, -368, 480, -1208, 480, -368, 476, -368, 476, -368, 476, -368, 476, -1216, 476, -368, 476, -368, 476, -1216, 476, -368, 476, -368, 476, -368, 476, -1212, 476, -1212, 480, -368, 476, -368, 476, -368, 476, -368, 476, -368, 476, -368, 476, -368, 480, -368, 476, -1212, 476, -368, 476, -368, 476, -372, 476, -368, 476, -368, 476, -1212, 476, -372, 476, -368, 476, -1212, 476, -1212, 476, -1216, 476, -368, 472, -372, 476, -368, 476, -372, 476, -364, 480, -368, 476, -368, 476, -368, 476, -368, 476, -372, 472, -368, 476, -1212, 476, -372, 476, -368, 476, -372, 472, -368, 476, -368, 476, -368, 476, -372, 472, -1216, 476, -1212, 476, -368, 476, -372, 472, -368, 476, -372, 472, -372, 476, -368, 476, -1212, 476, -1212, 476, -372, 472, -372, 472, -372, 472, -372, 476, -368, 476, -368, 476, -372, 476, -364, 476, -372, 472, -372, 472, -372, 476, -368, 476, -368, 476, -368, 476, -372, 472, -372, 472, -372, 472, -372, 472, -372, 500, -344, 476, -368, 476, -372, 472, -368, 476, -372, 472, -372, 472, -372, 472, -372, 476, -368, 476, -368, 472, -372, 476, -372, 472, -372, 472, -372, 472, -372, 476, -368, 472, -376, 472, -372, 472, -372, 472, -372, 472, -372, 472, -372, 476, -368, 472, -372, 476, -368, 476, -372, 472, -372, 472, -372, 472, -372, 472, -372, 472, -372, 472, -372, 500, -348, 472, -372, 472, -372, 472, -372, 472, -372, 472, -372, 476, -372, 472, -368, 476, -368, 476, -372, 476, -368, 476, -368, 476, -368, 476, -368, 476, -372, 472, -372, 472, -372, 476, -372, 472, -1212, 476, -372, 472, -372, 472, -392, 472, -356, 472, -372, 472, -372, 472, -372, 476, -368, 476, -368, 476, -372, 472, -1216, 500, -344, 472, -376, 472, -372, 472, -372, 472, -372, 476, -368, 476, -368, 476, -372, 472, -372, 472, -372, 476, -372, 472, -1216, 472, -1216, 472, -372, 472, -1220, 472, -372, 472, -372, 472, -396, 448, -396, 448, -388, 468,
ON
Raw: (453) 30020, -49824, 3412, -1676, 440, -1232, 440, -404, 440, -404, 440, -404, 440, -404, 440, -408, 440, -404, 440, -404, 440, -404, 444, -404, 440, -404, 440, -404, 440, -1252, 440, -404, 440, -404, 440, -404, 440, -408, 440, -404, 436, -408, 440, -404, 440, -1252, 444, -1244, 444, -400, 440, -404, 444, -404, 440, -404, 440, -404, 440, -412, 440, -400, 436, -408, 440, -1252, 440, -404, 436, -1252, 444, -1248, 440, -1248, 444, -1244, 444, -1244, 444, -1248, 444, -400, 440, -1252, 440, -1252, 464, -376, 440, -408, 440, -404, 440, -404, 440, -404, 440, -404, 444, -404, 440, -404, 440, -1252, 440, -1248, 444, -1248, 440, -1252, 440, -1248, 440, -1248, 440, -1248, 444, -1248, 440, -404, 440, -404, 440, -404, 440, -1252, 444, -400, 440, -404, 440, -404, 472, -372, 440, -1256, 440, -400, 440, -408, 440, -1248, 444, -400, 440, -404, 440, -404, 440, -1252, 444, -1248, 440, -404, 436, -408, 440, -404, 440, -404, 440, -408, 440, -404, 440, -404, 440, -404, 440, -1252, 440, -404, 440, -404, 440, -404, 440, -408, 440, -404, 440, -404, 440, -1252, 440, -1248, 444, -400, 440, -1252, 440, -1248, 444, -400, 440, -404, 440, -404, 440, -408, 440, -404, 440, -404, 440, -404, 440, -408, 440, -404, 436, -408, 440, -1252, 440, -404, 436, -408, 440, -404, 440, -416, 440, -396, 440, -404, 436, -408, 440, -404, 440, -1252, 440, -1252, 440, -400, 440, -408, 436, -408, 436, -408, 440, -404, 440, -404, 440, -1276, 420, -1268, 420, -400, 444, -400, 444, -404, 444, -400, 444, -400, 444, -400, 444, -372, 472, -404, 444, -400, 444, -420, 424, -428, 416, -424, 420, -432, 412, -432, 416, -428, 392, -452, 392, -452, 392, -456, 392, -452, 392, -452, 392, -1300, 388, -456, 392, -452, 392, -456, 392, -452, 392, -452, 392, -452, 392, -452, 396, -448, 396, -452, 392, -452, 392, -432, 440, -400, 440, -404, 416, -428, 444, -404, 440, -404, 440, -404, 440, -404, 416, -428, 440, -404, 416, -432, 412, -432, 416, -428, 416, -428, 416, -428, 416, -432, 412, -432, 412, -432, 416, -428, 416, -428, 416, -428, 416, -432, 412, -432, 412, -432, 412, -432, 412, -432, 416, -432, 412, -432, 412, -432, 412, -432, 412, -432, 412, -432, 416, -432, 412, -432, 412, -432, 412, -432, 412, -432, 412, -436, 408, -1280, 412, -432, 412, -432, 412, -436, 408, -436, 408, -436, 408, -436, 412, -432, 412, -436, 408, -436, 408, -436, 408, -1304, 388, -436, 408, -436, 408, -460, 384, -460, 384, -460, 388, -456, 388, -472, 384, -448, 384, -464, 384, -456, 384, -464, 384, -460, 384, -1308, 380, -464, 384, -460, 384, -1308, 380, -464, 380, -464, 380, -468, 376, -468, 376,
I try sending the raw data pulses using the associated sending codes but my AC does not detect them. If anyone could please guide me towards the right direction because I'm at a loss. I already went through this forum post: Sending IR code to air conditioner (clone IR remote) - Projects / General Guidance - Arduino Forum
and various others with no success. Any help is much appreciated.