Arduino-IRremote/examples/IRDispatcherDemo/IRDispatcherDemo.ino

307 lines
10 KiB
C++

/*
* IRDispatcherDemo.cpp
*
* Receives NEC IR commands and maps them to different actions by means of a mapping array.
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* IRMP 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>
/*
* Choose the library to be used for IR receiving
*/
#define USE_TINY_IR_RECEIVER // Recommended, but only for NEC protocol!!! If disabled and IRMP_INPUT_PIN is defined, the IRMP library is used for decoding
//#define TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT // costs 112 bytes program memory + 4 bytes RAM
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
// Some kind of auto detect library if USE_TINY_IR_RECEIVER is deactivated
#if !defined(USE_TINY_IR_RECEIVER)
# if defined(IR_RECEIVE_PIN)
#define USE_TINY_IR_RECEIVER
# elif !defined(USE_IRMP_LIBRARY) && defined(IRMP_INPUT_PIN)
#define USE_IRMP_LIBRARY
# else
#error No IR library selected
# endif
#endif
//#define NO_LED_FEEDBACK_CODE // You can set it here, before the include of IRCommandDispatcher below
#if defined(USE_TINY_IR_RECEIVER)
//#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt.
/*
* Set sensible receive pin for different CPU's
*/
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IR_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
# else
#define IR_INPUT_PIN 0 // PCINT0
# endif
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IR_INPUT_PIN 10
# elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
#define IR_INPUT_PIN 21 // INT0
# elif defined(ESP8266)
#define IR_INPUT_PIN 14 // D5
# elif defined(ESP32)
#define IR_INPUT_PIN 15
# elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO)
#define IR_INPUT_PIN 3 // GPIO15 Use pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
# elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IR_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
# else
#define IR_INPUT_PIN 2 // INT0
# endif
#elif defined(USE_IRMP_LIBRARY)
/*
* IRMP version
*/
#define IR_INPUT_PIN 2
#define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality. It is required if IRMP library is used.
#if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define FEEDBACK_LED_PIN ALTERNATIVE_IR_FEEDBACK_LED_PIN
#endif
//#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT // Enable interrupt functionality (not for all protocols) - requires around 376 additional bytes of program memory
#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some program memory. Must before #include <irmp*>
#define IRMP_SUPPORT_NEC_PROTOCOL 1 // this enables only one protocol
//#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1
# if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define IRMP_FEEDBACK_LED_PIN ALTERNATIVE_IR_FEEDBACK_LED_PIN
# endif
/*
* After setting the definitions we can include the code and compile it.
*/
#include <irmp.hpp>
void handleReceivedIRData();
void irmp_tone(uint8_t _pin, unsigned int frequency, unsigned long duration);
#endif // #if defined(USE_IRMP_LIBRARY)
bool doBlink = false;
uint16_t sBlinkDelay = 200;
void doPrintMenu();
void doLedOn();
void doLedOff();
void doIncreaseBlinkFrequency();
void doDecreaseBlinkFrequency();
void doStop();
void doResetBlinkFrequency();
void doLedBlinkStart();
void doLedBlink20times();
void doTone1800();
void doTone2200();
/*
* Set definitions and include IRCommandDispatcher library after the declaration of all commands to map
*/
#define INFO // to see some informative output
#include "IRCommandDispatcher.h" // Only for required declarations, the library itself is included below after the definitions of the commands
#include "IRCommandMapping.h" // must be included before IRCommandDispatcher.hpp to define IR_ADDRESS and IRMapping and string "unknown".
#include "IRCommandDispatcher.hpp"
/*
* Helper macro for getting a macro definition as string
*/
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || 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
#if defined(ESP8266)
Serial.println(); // to separate it from the internal boot output
#endif
// Just to know which program is running on my Arduino
#if defined(USE_TINY_IR_RECEIVER)
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing TinyIRReceiver"));
#elif defined(USE_IRREMOTE_LIBRARY)
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing IRremote library version " VERSION_IRREMOTE));
#elif defined(USE_IRMP_LIBRARY)
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing IRMP library version " VERSION_IRMP));
#endif
#if !defined(ESP8266) && !defined(NRF5)
// play feedback tone before setup, since it kills the IR timer settings
tone(TONE_PIN, 1000, 50);
delay(50);
#endif
IRDispatcher.init(); // This just calls irmp_init()
#if defined(USE_TINY_IR_RECEIVER)
Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_INPUT_PIN)));
#else
irmp_register_complete_callback_function(&handleReceivedIRData); // fixed function in IRCommandDispatcher.hpp
Serial.print(F("Ready to receive IR signals of protocols: "));
irmp_print_active_protocols(&Serial);
Serial.println(F("at pin " STR(IRMP_INPUT_PIN)));
# if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at ALTERNATIVE_IR_FEEDBACK_LED_PIN
Serial.println(F("IR feedback pin is " STR(ALTERNATIVE_IR_FEEDBACK_LED_PIN)));
# endif
#endif
Serial.print(F("Listening to commands of IR remote of type "));
Serial.println(IR_REMOTE_NAME);
doPrintMenu();
}
void loop() {
IRDispatcher.checkAndRunSuspendedBlockingCommands();
if (doBlink) {
digitalWrite(LED_BUILTIN, HIGH);
DELAY_AND_RETURN_IF_STOP(sBlinkDelay);
digitalWrite(LED_BUILTIN, LOW);
DELAY_AND_RETURN_IF_STOP(sBlinkDelay);
}
if (millis() - IRDispatcher.IRReceivedData.MillisOfLastCode > 120000)
{
//Short beep as remainder, if we did not receive any command in the last 2 minutes
IRDispatcher.IRReceivedData.MillisOfLastCode += 120000;
doTone1800();
}
// delay(10);
}
void doPrintMenu(){
Serial.println();
Serial.println(F("Press 1 for tone 1800 Hz"));
Serial.println(F("Press 2 for tone 2200 Hz"));
Serial.println(F("Press 3 for this Menu"));
Serial.println(F("Press 0 for LED blink 20 times"));
Serial.println(F("Press UP for LED on"));
Serial.println(F("Press DOWN for LED off"));
Serial.println(F("Press OK for LED blink start"));
Serial.println(F("Press RIGHT for LED increase blink frequency"));
Serial.println(F("Press LEFT for LED decrease blink frequency"));
Serial.println(F("Press STAR for reset blink frequency"));
Serial.println(F("Press HASH for stop"));
Serial.println();
}
/*
* Here the actions that are matched to IR keys
*/
void doLedOn() {
digitalWrite(LED_BUILTIN, HIGH);
doBlink = false;
}
void doLedOff() {
digitalWrite(LED_BUILTIN, LOW);
doBlink = false;
}
void doIncreaseBlinkFrequency() {
doBlink = true;
if (sBlinkDelay > 5) {
sBlinkDelay -= sBlinkDelay / 4;
}
}
void doDecreaseBlinkFrequency() {
doBlink = true;
sBlinkDelay += sBlinkDelay / 4;
}
void doStop() {
doBlink = false;
}
void doResetBlinkFrequency() {
sBlinkDelay = 200;
digitalWrite(LED_BUILTIN, LOW);
}
void doLedBlinkStart() {
doBlink = true;
}
/*
* This is a blocking function and checks periodically for stop
*/
void doLedBlink20times() {
for (int i = 0; i < 20; ++i) {
digitalWrite(LED_BUILTIN, HIGH);
DELAY_AND_RETURN_IF_STOP(200);
digitalWrite(LED_BUILTIN, LOW);
DELAY_AND_RETURN_IF_STOP(200);
}
}
void doTone1800() {
#if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
irmp_tone(TONE_PIN, 1800, 200);
#else
# if !defined(ESP8266) && !defined(NRF5) // tone() stops timer 1 for ESP8266
tone(TONE_PIN, 1800, 200);
# endif
#endif
}
void doTone2200() {
#if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
// use IRMP compatible function for tone()
irmp_tone(TONE_PIN, 2200, 50);
#else
# if !defined(ESP8266) && !defined(NRF5) // tone() stops timer 1 for ESP8266
tone(TONE_PIN, 2200, 50);
# endif
#endif
}
#if defined(USE_IRMP_LIBRARY)
/*
* Convenience IRMP compatible wrapper function for Arduino tone() if IRMP_ENABLE_PIN_CHANGE_INTERRUPT is NOT activated
* It currently disables the receiving of repeats
*/
void irmp_tone(uint8_t _pin, unsigned int frequency, unsigned long duration) {
# if defined(__AVR__) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
storeIRTimer();
tone(_pin, frequency, 0);
if (duration == 0) {
duration = 100;
}
delay(duration);
noTone(_pin);
restoreIRTimer();
#elif defined(ESP8266)
// tone() stops timer 1
(void) _pin;
(void) frequency;
(void) duration;
#else
tone(_pin, frequency, duration);
#endif
}
#endif // #if defined(USE_IRMP_LIBRARY)