General

IR Remote and IR Receiver for KODI (Arduino sketch)

userHead LNC-SPN 2019-03-07 22:44:21 8917 Views0 Replies

Hi Lattepanders! If you want to control Kodi with an IR remote this is for you. 
Works on all versions of LattePanda.

SOFTWARE

KODI - Open Source Home Theater Software:
https://kodi.tv/download

To run Kodi when Windows starts: 
Put a Kodi.exe shortcut in the startup folder (Win + R | shell:startup)

To run Kodi when Windows starts and bypass the explorer shell:
Run the Group Policy Editor (gpedit.msc), then navigate to:
User Configuration -> Administrative Templates -> System and then select “Custom User Interface” 

Enable it and enter the entire path of Kodi.exe
(ie: C:\Program Files (x86)\Kodi\Kodi.exe)

*To get back into Windows from Kodi. Exit Kodi and then start the task manager (Ctrl:Alt:Del) and run task ‘explorer.exe’

Arduino IDE sketch & Libraries (IRremote & Keyboard):
Download from Google Drive: https://drive.google.com/file/d/1WGziGu ... lkzps/view
 

Extract the two libraries folders (IRreceiver, Keyboard) into "C:\Program Files (x86)\Arduino\libraries"Extract the IR_Receiver_for_KODI folder into "Documents\Arduino"Open "IR_Receiver_for_KODI.ino" with the Arduino IDEUpload the skecth (make sure the Arduino Leonardo board and their COM port is selected in Tools)

Sketch Code:

*Note: The remote IR codes are from the "Gravity: IR Kit for Arduino" remote https://www.dfrobot.com/product-366.html
If you are using another remote just monitor the serial output and press the remote buttons. Then change the HEXA codes in the ( REMOTE IR CODES ) section.

/*
 * Using a IR Remote and IR Receiver to control KODI
 * by Luis N.C
 * ver 1.0
 */
 
/*-----( INCLUDING THE LIBRARIES )-----*/
#include <IRremote.h>
#include <Keyboard.h>

/*-----( REMOTE IR CODES )-----*/
#define power        0xFD00FF   // Power
#define power_1      0xB2EEDF3D // Power
#define func_stop    0xFD40BF   // Func/Stop
#define func_stop_1  0x2C87261  // Func/Stop
#define pause_play   0xFDA05F   // >||
#define pause_play_1 0xA6B913BD // >|| 
#define foward       0xFD609F   // >>|
#define foward_1     0xD0529225 // >>| 
#define backward     0xFD20DF   // |<<
#define backward_1   0x1644C1C1 // |<<
#define vol_up       0xFD807F   // VOL+
#define vol_up_1     0xC9C3741  // VOL+
#define vol_down     0xFD906F   // VOL-
#define vol_down_1   0x925D5B5D // VOL-
#define up_arrow     0xFD50AF   // ^
#define up_arrow_1   0xCB3D6F7D // ^
#define down_arrow   0xFD10EF   // v
#define down_arrow_1 0x1E90961  // v
#define st_rept      0xFD708F   // ST/REPT
#define st_rept_1    0x6BFD8B01 // ST/REPT
#define eq           0xFDB04F   // EQ
#define eq_1         0x42640C99 // EQ
#define button_0     0xFD30CF   // 0
#define button_0_1   0xB1EFBA9D // 0
#define button_1     0xFD08F7   // 1
#define button_1_1   0xDEE522C1 // 1
#define button_2     0xFD8877   // 2
#define button_2_1   0x6F5974BD // 2
#define button_3     0xFD48B7   // 3
#define button_3_1   0x986FB325 // 3
#define button_4     0xFD28D7   // 4
#define button_4_1   0xCBD2CCFD // 4
#define button_5     0xFDA857   // 5
#define button_5_1   0x25802501 // 5
#define button_6     0xFD6897   // 6
#define button_6_1   0x85E09D61 // 6
#define button_7     0xFD18E7   // 7
#define button_7_1   0xC76EF4E5 // 7
#define button_8     0xFD9867   // 8
#define button_8_1   0x57E346E1 // 8
#define button_9     0xFD58A7   // 9
#define button_9_1   0x90C35B01 // 9
#define hold_press   0xFFFFFFFF // Button press holded 

/*-----( GLOBAL VARIABLES )-----*/
int receiver = 11; // Signal Pin of IR receiver to Arduino Digital Pin 11
long unsigned int lastCode; // Save the last remote code for REPEAT

/*-----( DECLARE OBJECTS )-----*/
IRrecv irrecv(receiver);     // create instance of 'irrecv'
decode_results results;      // create instance of 'decode_results'

/*----( SETUP: RUNS ONCE )----*/
void setup()
{
  Keyboard.begin();
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver 
}
/*--( END SETUP )---*/

/*----( LOOP: RUNS CONSTANTLY )----*/
void loop()
{
  if (irrecv.decode(&results)) // Have we received an IR signal?
  {
    translateIR();    
    irrecv.resume(); // Receive the next value
  }  
}
/* --(END MAIN LOOP )-- */

/*-----( FUNCTIONS )-----*/
void translateIR() // Takes action based on IR code received

// Describing Remote IR codes, sending Keyboard presses to control KODI  

{
  if(results.value == hold_press)
  {
      Serial.println(" REPEAT");
      results.value = lastCode;      
  }
  
  switch(results.value)
  {

    case power:  // KODI Shutdown menu-Show preset(Music Visualisation)
      lastCode = results.value, HEX;
      Serial.print("POWER");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press('s');
      Keyboard.release('s');
      break;

    case power_1:  // KODI Shutdown menu-Show preset(Music Visualisation)
      lastCode = results.value, HEX;
      Serial.print("POWER");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press('s');
      Keyboard.release('s');
      break;
      
    case func_stop:  // Stop
      lastCode = results.value, HEX;
      Serial.print("FUNC/STOP");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press('x');
      Keyboard.release('x');
      break;

    case func_stop_1:  // Stop
      lastCode = results.value, HEX;
      Serial.print("FUNC/STOP");      
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press('x');
      Keyboard.release('x');
      break;
      
    case pause_play:  // Pause/Play-Current playlist window (video & music listings)-Highlight (File manager)
      lastCode = results.value, HEX;
      Serial.print(">||");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press((char) 32);
      Keyboard.release((char) 32);
      break;

     case pause_play_1:  // Pause/Play-Current playlist window (video & music listings)-Highlight (File manager)
      lastCode = results.value, HEX;
      Serial.print(">||");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press((char) 32);
      Keyboard.release((char) 32);
      break;

    case foward:     // Fast forward
      lastCode = results.value, HEX;
      Serial.print(">>|");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press('f');
      Keyboard.release('f');
      break;

     case foward_1:     // Fast forward
      lastCode = results.value, HEX;
      Serial.print(">>|");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press('f');
      Keyboard.release('f');
      break;
      
    case backward:   // Rewind - Rename (File manager)
      lastCode = results.value, HEX;
      Serial.print("|<<");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press('r');
      Keyboard.release('r');
      break;
      
    case backward_1:   // Rewind - Rename (File manager)
      lastCode = results.value, HEX;
      Serial.print("|<<");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press('r');
      Keyboard.release('r');
      break;

    case vol_up:    // Volume up
      lastCode = results.value, HEX;
      Serial.print("VOL+");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press((char) 223);
      Keyboard.release((char) 223);
      break;
      
    case vol_up_1:    // Volume up
      lastCode = results.value, HEX;
      Serial.print("VOL+");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press((char) 223);
      Keyboard.release((char) 223);
      break;

    case vol_down:  // Volume down
      lastCode = results.value, HEX;
      Serial.print("VOL-");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press((char) 222);
      Keyboard.release((char) 222);
      break;

    case vol_down_1:  // Volume down
      lastCode = results.value, HEX;
      Serial.print("VOL-");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press((char) 222);
      Keyboard.release((char) 222);
      break;

    case up_arrow:  // Page up - Skip to next queued video or next chapter if no videos are queued
      lastCode = results.value, HEX;
      Serial.print("^");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_PAGE_UP);
      Keyboard.release(KEY_PAGE_UP);
      break;
      
    case up_arrow_1:  // Page up - Skip to next queued video or next chapter if no videos are queued
      lastCode = results.value, HEX;
      Serial.print("^");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_PAGE_UP);
      Keyboard.release(KEY_PAGE_UP);
      break;
      
    case down_arrow: // Page down - Skip to previous queued video or previous chapter if no videos are queued
      lastCode = results.value, HEX;
      Serial.print("v");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_PAGE_DOWN);
      Keyboard.release(KEY_PAGE_DOWN);
      break;
      
    case down_arrow_1: // Page down - Skip to previous queued video or previous chapter if no videos are queued
      lastCode = results.value, HEX;
      Serial.print("v");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_PAGE_DOWN);
      Keyboard.release(KEY_PAGE_DOWN);
      break;
      
    case st_rept:    // Contextual menu - Playlist
      lastCode = results.value, HEX;
      Serial.print("ST/REPT");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press('c');
      Keyboard.release('c');
      break;
            
    case st_rept_1:    // Contextual menu - Playlist
      lastCode = results.value, HEX;
      Serial.print("ST/REPT");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press('c');
      Keyboard.release('c');
      break;
      
    case eq:         // MUTE
      lastCode = results.value, HEX;
      Serial.print("EQ");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_F8);
      Keyboard.release(KEY_F8);
      break;
     
    case eq_1:         // MUTE
      lastCode = results.value, HEX;
      Serial.print("EQ");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_F8);
      Keyboard.release(KEY_F8);
      break;
      
    case button_0:  // Back
      lastCode = results.value, HEX;
      Serial.print("0");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_BACKSPACE);
      Keyboard.release(KEY_BACKSPACE);
      break;
      
    case button_0_1:  // Back
      lastCode = results.value, HEX;
      Serial.print("0");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_BACKSPACE);
      Keyboard.release(KEY_BACKSPACE);
      break;

    case button_1:  // None
      lastCode = results.value, HEX;
      Serial.print("1");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      //Keyboard.press('1');
      //Keyboard.release('1');
      break;

    case button_1_1:  // None
      lastCode = results.value, HEX;
      Serial.print("1");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      //Keyboard.press('1');
      //Keyboard.release('1');
      break;
      
    case button_2:  // Up - Seek step forward 10min OR Next chapter (videos)-Channel up (live TV)
      lastCode = results.value, HEX;
      Serial.print("2");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_UP_ARROW);
      Keyboard.release(KEY_UP_ARROW);
      break;
      
    case button_2_1:  // Up - Seek step forward 10min OR Next chapter (videos)-Channel up (live TV)
      lastCode = results.value, HEX;
      Serial.print("2");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_UP_ARROW);
      Keyboard.release(KEY_UP_ARROW);
      break;
      
    case button_3:  // None
      lastCode = results.value, HEX;
      Serial.print("3");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      //Keyboard.press('3');
      //Keyboard.release('3');
      break;

    case button_3_1:  // None
      lastCode = results.value, HEX;
      Serial.print("3");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      //Keyboard.press('3');
      //Keyboard.release('3');
      break;

    case button_4:  // Left - Seek step backward - Prev channel group (live TV)
      lastCode = results.value, HEX;
      Serial.print("4");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_LEFT_ARROW);
      Keyboard.release(KEY_LEFT_ARROW);
      break;

     case button_4_1:  // Left - Seek step backward - Prev channel group (live TV)
      lastCode = results.value, HEX;
      Serial.print("4");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_LEFT_ARROW);
      Keyboard.release(KEY_LEFT_ARROW);
      break;

    case button_5:  // Select(Enter) - Player controls (OSD)
      lastCode = results.value, HEX;
      Serial.print("5");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_RETURN);
      Keyboard.release(KEY_RETURN);
      break;
      
    case button_5_1:  // Select(Enter) - Player controls (OSD)
      lastCode = results.value, HEX;
      Serial.print("5");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_RETURN);
      Keyboard.release(KEY_RETURN);
      break;
      
    case button_6:  // Right - Seek step forward - Next channel group (live TV)
      lastCode = results.value, HEX;
      Serial.print("6");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_RIGHT_ARROW);
      Keyboard.release(KEY_RIGHT_ARROW);
      break;

    case button_6_1:  // Right - Seek step forward - Next channel group (live TV)
      lastCode = results.value, HEX;
      Serial.print("6");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_RIGHT_ARROW);
      Keyboard.release(KEY_RIGHT_ARROW);
      break;
      
    case button_7:  // None
      lastCode = results.value, HEX;
      Serial.print("7");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      //Keyboard.press('7');
      //Keyboard.release('7');
      break;
      
    case button_7_1:  // None
      lastCode = results.value, HEX;
      Serial.print("7");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      //Keyboard.press('7');
      //Keyboard.release('7');
      break;

    case button_8:  // Down - Step back 10min OR Prev chapter (videos) - Channel down (live TV)
      lastCode = results.value, HEX;
      Serial.print("8");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_DOWN_ARROW);
      Keyboard.release(KEY_DOWN_ARROW);
      break;

    case button_8_1:  // Down - Step back 10min OR Prev chapter (videos) - Channel down (live TV)
      lastCode = results.value, HEX;
      Serial.print("8");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      Keyboard.press(KEY_DOWN_ARROW);
      Keyboard.release(KEY_DOWN_ARROW);
      break;
      
    case button_9:  // None
      lastCode = results.value, HEX;
      Serial.print("9");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      //Keyboard.press('9');
      //Keyboard.release('9');
      break;
            
    case button_9_1:  // None
      lastCode = results.value, HEX;
      Serial.print("9");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);
      //Keyboard.press('9');
      //Keyboard.release('9');
      break;
      
  default: 
      Serial.print("UNREGISTERED CODE");
      Serial.print("\t"); 
      Serial.print("Code:0x");
      Serial.println(results.value, HEX);

  }// END CASE SWITCH

  delay(250); // Do not get immediate repeat

} 
/*-----( END FUNCTIONS )-----*/

 

HARDWARE

IR remote & IR receiver for Arduino:

Gravity: IR Kit for Arduino: https://www.dfrobot.com/product-366.html
Image

IR receiver connection:
*Note: I am not responsible for damages caused by an incorrect connection.

The receiver have 3 pins/cables: Black is GND - Red is 5v - Green is Signal

- For the first version of the LattePanda SBC just connect to the 3 Pin header "D11" IR_Receiver_LattePanda.jpg IR_Receiver_LattePanda.jpg (150.32 KiB) Viewed 8006 times - For the LattePanda Alpha you need to modify the cable in order to change it for male jumper terminations. IR_Receiver_LattePanda_Alpha.jpg

 IR Remote Keymap:

Remote buttons - Kodi keys/actions
 

POWER = KODI Shutdown menu - Show preset(Music Visualisation)
FUNC/STOP = Stop
>|| = Pause/Play - Current playlist window (video & music listings)-Highlight (File manager)
>>| = Fast forward
|<< = Rewind - Rename (File manager)
VOL+ = Volume up
VOL- = Volume down
EQ = MUTE
UP_ARROW = Page up - Skip to next queued video or next chapter if no videos are queued
DOWN ARROW = Page down - Skip to previous queued video or previous chapter if no videos are queued
ST_REPT = Contextual menu - Playlist
0 = Back
1 = None
2 = Up - Seek step forward 10min OR Next chapter (videos)-Channel up (live TV)
3 = None
4 = Left - Seek step backward - Prev channel group (live TV)
5 = Select(Enter) - Player controls (OSD)
6 = Right - Seek step forward - Next channel group (live TV)
7 = None
8 = Down - Step back 10min OR Prev chapter (videos) - Channel down (live TV)
9 = None

IR_Remote_Keys.jpg