Project tutorial
Repurpose Old Remote Controls

Repurpose Old Remote Controls © GPL3+

Don't throw away those old TV, DVD, etc., remotes because they can control your house's electrical devices!

  • 11,704 views
  • 4 comments
  • 44 respects

Components and supplies

Ard nano
Arduino Nano R3
×1
Kingbright wp7113srd d image
5 mm LED: Red
One red one for the status LED, after that, the colour is not really important - just need to be able to identify which one is active.
×3
Kingbright wp7113sgd
5 mm LED: Green
Colour is not really important - just need to be able to identify which one is active
×1
Led technology l03r5000q1 image
5 mm LED: Yellow
Colour is not really important - just need to be able to identify which one is active
×1
Blue LED
Colour is not really important - just need to be able to identify which one is active
×2
Adafruit industries ada239 image 75px
Solderless Breadboard Full Size
×1
11026 02
Jumper wires (generic)
×1
4314603
Toggle Switch, (Off)-On
Any SPST toggle switch will work
×1
10804 01
SparkFun Breadboard Power Supply Stick 5V/3.3V
Optional if you can supply 5 volts from another source or if you are using it from your computer's USB connection,
×1
IR receiver (generic)
I used a KY-022 37.9KHz Infrared IR Sensor Receiver that I obtained from Amazon
×1

About this project

This project allows you to reuse surplus remote controls from old VCRs, TV, DVD players, etc.

You can use the remotes to turn on devices like lamps, heaters, etc. with relays, power transistors or anything else a 5-volt signal can control. As shown here, it just toggles up to 6 LEDs. The idea is to provide the sketch and breadboard layout so that the signals sent to the LEDs can be sent in parallel to whatever the user imagines!

As designed, it reads 6 IR codes from any remote control and "memorizes" them. I like to use dights 1, 2, 3, 4, 5, 6 -- but any six keys will work. Note that any other key with an IR code other than the 6 known codes acts as a reset and sets all outputs to off. I achieve this by writing the codes as long integers to the EEPROM memory on the Ardunio board. Each one takes 4 bytes, but since the UNO and NANO each have 1024 bytes of EEPROM memory, there's plenty of room. This memory holds through resets and power-offs, as one would expect. The whole thing would fit on a single breadboard, except for the toggle switch. Pins could be soldered to this switch to include it on the breadboard. I was lazy and used tape to hold it on my desk during development.

I've tried it with five different old surplus ones, and they all perform the same. The "gotcha" I struggled with was stray light or weaker signals from some remotes. To solve this, I carefully bent the receiver "LED" downwards to about 45 degrees, and I put a little homemade cardboard and tape box over it, with one end open. It seems to catch the codes consistently and from 5-8 feet away or more. I haven't had a miss in over five days of testing and tweaking the program.

To program it, use the "learn" position. You go from "run" mode to "learn" mode by flipping a toggle switch. This toggle turns on a red mode indicator LED, indicating it's ready to listen. It flashes LED 1, and you press a key on your remote. The flashing LED 1 is programmed to react to that code. As soon as it recognizes the code, it rapidly flashes the mode indicator LED for a second or two (so fast it looks like it's vibrating!) and moves on to the next LED. This continues until all six are programmed. Then the mode indicator LED flashes slowly at one-second intervals indicating the system should be toggled to the run mode.

I found when programming it that the most common mistake was to forget to move your finger to the next digit on the remote. Thus it is easy to program two outputs with the same code. Every time it starts up, it looks for such duplicates. If it finds them, it flashes the "offending" LEDs a few times to suggest re-programming might be necessary. However, a person may want several keys doing the same thing, so it doesn't force re-programming.

Mode status, errors, etc. are indicated by the flash rate of the RED status LED. All the information indicated by the flashing LEDs, etc., is sent to the serial monitor. I set it up to use LED sequences of flashes so it could a user could set it up without a computer. The messages sent to the serial monitor are easier to follow than memorizing what flashing LEDs at various speeds mean. Since this would typically only be programmed a few times, it probably is more natural to hook it up to your PC and watch the text on the serial monitor.

There are a lot of checks and balances in the sketch code. They are well documented (I hope!), so I won't give the details here. Users familiar with C, C++ and the Arduino IDE should easily be able to follow the code and make modifications if desired.

Addendum: I have tested this with 5 relays in parallel with LEDs 1 through 5 and it works as expected. They all toggle a 120 VAC table lamp, so the circuit works as expected. I ran out of relays, so one has to assume the 6th signal will work as well. Note this is just a proof of concept. I had to invert the signals of the first four outputs with a CD4011 quad NAND gate because they close on 0 volts as opposed to 5 volts. The single relay works on a + 5-volt signal, so no signal inversion was needed. Please be careful switching mains voltages. They are high voltage and have the potential to give a bad shock or even kill!

Remember, this is just an example. Use your imagination as to what devices to connect to the 6 outputs. Enjoy!

Code

IR Remote repurposing sketchArduino
/*

  Toggle 6 LEDs using an IR remote to illustrate
  how to re-purpose surpulus remotes so they can be
  used to control almost any device.
  
  This sketch learns the manufacturer's codes for 
  the 1,2,3,4,5,6 and 0 buttons on any IR remote 
  when the toggle switch is in the "Learn" or program
  position. These values are saved in the Arduino Nano's 
  EEPROM. When the toggle switch is put in the "Run" mode,
  these values are used to determine which key is pressed.

  6 associated LEDs are then be toggled on and off by
  the remote. This is to demonstrate how to learn and 
  ise the codes regardless of the type of IR remote. In 
  addition to LEDs, the outputs can be expanded to turn 
  on or off devices with relays, high-power transistors,etc.
  
  Paul M Dunphy VE1DX

  March 2020
  
*/
 
// Include IR Remote Library developed by Ken Shirriff
#include <IRremote.h>
// Give the ability to read/write to the 1024 bytes of EEPROM
#include <EEPROM.h>

long unsigned int intIRCode;
long unsigned int savedIRCodes[6];
long unsigned int dupeCheck[6];
 
// Define pin for the IR sensor
const int Recv_Pin = 2;
 
// Define pin constants to toggle the LEDs
const int PinOne     = 12; 
const int PinTwo     = 11;
const int PinThree   = 10; 
const int PinFour    = 9;
const int PinFive    = 8; 
const int PinSix     = 7;

// Define pin constants to read and indicate the
// status of Run/Learn toggle switch.
const int switchPin  = 4;    
const int statusPin  = 5; 

const unsigned long int repeatKeyPress = 0xFFFFFFFF;

boolean learnMode; // Used to keep track of which
                   // mode we are in as per the toggle switch.
boolean first_iteration;                   

// Define integers to remember toggle states of each LED
int togglestate1;
int togglestate2;
int togglestate3;
int togglestate4;
int togglestate5;
int togglestate6;

int current_remote_code;

int  remote_code_1;
int  remote_code_2;
int  remote_code_3;
int  remote_code_4;
int  remote_code_5;
int  remote_code_6;

 
// Define IR Receiver and Results Objects
IRrecv irrecv(Recv_Pin);
decode_results results;




void EEPROMWritelong(int address, long value)

// Write a 4 byte (32bit) long integer to the EEPROM
// Since they are 4 bytes long, they are stored at 
// address to address + 3
    {
      // Decompose a long integer into 4 bytes by using bitshift.
      // One = Most significant -> Four = Least significant byte
      byte four = (value & 0xFF);
      byte three = ((value >> 8) & 0xFF);
      byte two = ((value >> 16) & 0xFF);
      byte one = ((value >> 24) & 0xFF);
      EEPROM.write(address, four);
      EEPROM.write(address + 1, three);
      EEPROM.write(address + 2, two);
      EEPROM.write(address + 3, one);
    }




long EEPROMReadlong(long address)

// Read a 4 byte (32bit) long integer from the EEPROM.
// Since they are 4 bytes long, they were stored at 
// address to address + 3
    {
      long four  = EEPROM.read(address);
      long three = EEPROM.read(address + 1);
      long two   = EEPROM.read(address + 2);
      long one   = EEPROM.read(address + 3);

      //Assemble the bytes into a long integer and return
      return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + 
             ((two << 16) & 0xFFFFFF) + ((one << 24) & repeatKeyPress);
    }






int Flip_LED(int led, int toggle_state)

  {
    if(toggle_state==0)
      {
        digitalWrite(led, HIGH);
        toggle_state=1;
       }
     else 
       {
         digitalWrite(led, LOW);
         toggle_state=0;
       }
     return toggle_state;  
  }





void Reset()
  {
    // Turn all LEDs off and set the toggle
    // flags to off (0)
    digitalWrite(PinOne,   LOW);
    digitalWrite(PinTwo,   LOW);
    digitalWrite(PinThree, LOW);
    digitalWrite(PinFour,  LOW);
    digitalWrite(PinFive,  LOW);
    digitalWrite(PinSix,   LOW);
    togglestate1 = 0;
    togglestate2 = 0;
    togglestate3 = 0;
    togglestate4 = 0;
    togglestate5 = 0;
    togglestate6 = 0;
  }




void guessType()
  {
    Serial.print("Remote appears to be a ");
     switch (results.decode_type){
     case NEC: 
       Serial.println("NEC "); 
       break;
     case SONY: 
       Serial.println("SONY "); 
       break;
     case RC5: 
       Serial.println("RC5 "); 
       break;
     case RC6: 
       Serial.println("RC6 "); 
       break;
     case DISH: 
       Serial.println("DISH "); 
        break;
     case SHARP: 
       Serial.println("SHARP "); 
       break;
     case JVC: 
       Serial.println("JVC "); 
       break;
     case SANYO: 
       Serial.println("SANYO "); 
       break;
     case MITSUBISHI: 
       Serial.println("MITSUBISHI "); 
       break;
     case SAMSUNG: 
       Serial.println("SAMSUNG "); 
       break;
     case LG: 
       Serial.println("LG "); 
       break;
       case WHYNTER: 
         Serial.println("WHYNTER "); 
         break;
       case AIWA_RC_T501: 
         Serial.println("AIWA_RC_T501 "); 
         break;
       case PANASONIC: 
         Serial.println("PANASONIC "); 
         break;
       case DENON: 
         Serial.println("DENON "); 
         break;
       default:
       case UNKNOWN: 
         Serial.println("UNKNOWN "); 
         break;
      }
    }
    



int learnCodeRead(int pinCode)

  {  
     if (irrecv.decode(&results))
      {
        pinCode = results.value;
      }
    return pinCode;
  }
  
  

void Confirm()
  {
    int i;

    for(i=0; i<=20; i++)
      {
        digitalWrite(statusPin,   HIGH);
        delay(50);
        digitalWrite(statusPin,   LOW);
        delay(50);
      }  
     digitalWrite(statusPin,   HIGH); // Leave "Learn" LED high
  }


  


void learn_Mode()
  {
    boolean goodCode; 
    int i, j;
    int location;
    int pins[6] = {12,11,10,9,8,7};
 
    // Start listening for each in sequence
       if (first_iteration) 
        {
          Serial.println();
          Serial.println("Entering learn mode");
          Serial.println();
        }
    intIRCode = 0;
    location = 0;
    goodCode = true;
    j = 0;
    while ((goodCode=true) and (j<=5))
      {
        for(i=0; i<=25; i++)
        {
          digitalWrite(pins[j],   HIGH);
          delay(200);
          intIRCode = learnCodeRead(intIRCode);
          digitalWrite(pins[j],   LOW);
          delay(200);
          intIRCode = learnCodeRead(intIRCode);
          goodCode = ((intIRCode !=repeatKeyPress) and (intIRCode !=0));
          if (goodCode) 
            { 
              i=30; // Trick to bail out of loop because 'break' 
                    // doesn't work on loops
            }
          irrecv.resume();     // Start listening again  
        }
        goodCode = (intIRCode !=repeatKeyPress and intIRCode !=0);
        if (goodCode)
          {   
            if (j==0) 
              {
                guessType();
              }
            Serial.print("Writing to EEPROM Location ");Serial.print(location); 
            Serial.print("  IR code = ");Serial.println(intIRCode,HEX);
            EEPROMWritelong(location, intIRCode);        
            location = location + 4;
            j++;
            Confirm();
            intIRCode = 0;
            irrecv.resume();     // Start listening again
           }
          
      }
        Serial.println();
        Serial.println("Put Arduino back in run mode.");
        while (digitalRead(switchPin) == HIGH)
          {
            digitalWrite(statusPin,   HIGH);
            delay(1000);
            digitalWrite(statusPin,   LOW);
            delay(1000);
          } 
        Serial.println();
        Serial.println("Returning to run mode.");
        
        // Probably don't need to be so drastic here, but
        // This is a "reset" to be sure we get out of learn
        // mode and restart properly. It's *likely* OK to
        // remove the following 4 lines.
        delay(50);
        Serial.flush(); 
        delay(50);
        asm volatile ("  jmp 0");
  }




  

void run_Mode()
  {
    if (first_iteration) 
      {
        Serial.println("Entering run mode");
      }
    if (irrecv.decode(&results))
      {
        if (results.value!=repeatKeyPress) {
        current_remote_code = results.value; 
        Serial.print("Key press detected, IR code = "); 
        Serial.println(current_remote_code,HEX);
        if (current_remote_code == remote_code_1)
          {
            togglestate1 = Flip_LED(PinOne,togglestate1);
           }
        else if (current_remote_code == remote_code_2) {
            togglestate2 = Flip_LED(PinTwo,togglestate2);
                             }
        else if (current_remote_code == remote_code_3) {
            togglestate3 = Flip_LED(PinThree,togglestate3);
                             }
        else if (current_remote_code == remote_code_4) {
           togglestate4 = Flip_LED(PinFour,togglestate4);
                             }
        else if (current_remote_code == remote_code_5) {
           togglestate5 = Flip_LED(PinFive,togglestate5);
                             }   
        else if (current_remote_code == remote_code_6) {
           togglestate6 = Flip_LED(PinSix,togglestate6);
                             }
        else  {
            Reset();
              } 
      }                                            
         delay(500);         // Used to get around the rapid string of data
                             // if a button is held down. Slows down response time
                             // by introducing a lag in the loop.                             
        irrecv.resume();     // Start listening again  
      }
  } 


 

 
void setup()
  {
    first_iteration = true;
    int i,j,k;
    int location; 
    int dupeFlash[6] = {12,11,10,9,8,7}; // Pin numbers to flash
                                         // if duplicates found
    
    Serial.begin(9600);
    irrecv.enableIRIn(); // Enable the IR Receiver

 /* The following section of code should never need to be reset the EEPROM.
  * However, some new, off "the shelf" NANOs show up with their EEPROMs set 
  * to FFFFFFFFs. This happens to be the code sent by many IR Remotes when 
  * a key is held down. This sketch checks for that code in several places
  * and it won't work properly if a "key" is assigned a hex FFFFFFFF. To 
  * prevent this gotcha, we check for FFFFFFFFs and if we find one, we set 
  * the 6 key locations to Sony RM-YD104 codes.  If this happens, unless you
  * are using that particular remote, you'll need to run the sketch in "learn"
  * mode to initialise it.
  */

// ============= Begin New Arduino ==================

   boolean defaultToSony = false;
   long unsigned int IRCode = 0;
   location = 0;
   for(i=0; i<=5; i++)
      {     
        IRCode = EEPROMReadlong(location);
        if (IRCode==repeatKeyPress)
          {
            defaultToSony = true;
          }          
        location = location + 4;
      } 
    if (defaultToSony) 
      {
        Serial.println("HEX FFFFFFFF found in EEPROM memory. Setting codes");
        Serial.println("for a Sony RM-YD104 remote. Running 'learn' mode now");
        Serial.println("is recommended unless that's the remote you have.");
        EEPROMWritelong(0, 0x10);
        delay(50);
        EEPROMWritelong(4, 0x810);
        delay(50);
        EEPROMWritelong(8, 0x410);
        delay(50);
        EEPROMWritelong(12, 0xC10);
        delay(50);  
        EEPROMWritelong(16, 0x210);
        delay(50); 
        EEPROMWritelong(20, 0xA10);
        delay(50);                             
      } 


// ============= End New Arduino ==================
  
    // Set LED pins as outputs
    pinMode(PinOne,   OUTPUT);
    pinMode(PinTwo,   OUTPUT);
    pinMode(PinThree, OUTPUT);
    pinMode(PinFour,  OUTPUT);
    pinMode(PinFive,  OUTPUT);
    pinMode(PinSix,   OUTPUT);
  
    Reset(); // Start out with them all off
  
    pinMode(statusPin, OUTPUT); 
    pinMode(switchPin, INPUT);

    //Get codes from last used remote
    Serial.println();
    Serial.println("Reading stored IR remote codes . . . ");    
    location = 0;
    for(j=0; j<=5; j++)
      {   
        savedIRCodes[j] = EEPROMReadlong(location);
        Serial.print("Reading from EEPROM Location ");Serial.print(location); 
        Serial.print("  IR code = ");Serial.println(savedIRCodes[j],HEX);
        location = location + 4;
        dupeCheck[j]=savedIRCodes[j]; // Save a copy for duplicate checking
      } 

    // Look for consecutive duplicate codes assigned to the 
    // outputs. We don't look for overall duplicates because
    // they are unlikely to happen. Experience has shown that 
    // during programming, the most likely mistake is to press
    // the same key twice on bacl-to-back LEDs.  If duplicates
    // are found, indicate this by flashing the suspect LEDs.
    // There are only 6 LEDs, so it only takes 21 comparisons
    // to find any duplicates (6 + 5 + 4 + 3 + 2 + 1 = 21). This 
    // section could be enhanced to look for any duplicates by
    // sorting the array first, etc.
    for (i = 0; i <5 - 1; i++) 
      {
        for (j = i + 1; j <6; j++)
          {
            if (dupeCheck[i] == dupeCheck[j]) 
              {
              Serial.println("Duplicate codes found. Suggest re-running learn mode");
              for(k=0; k<=5; k++)
                {
                  digitalWrite(dupeFlash[i],HIGH);
                  digitalWrite(dupeFlash[j],HIGH);
                  delay(1000);
                  digitalWrite(dupeFlash[i],LOW);
                  digitalWrite(dupeFlash[j],LOW);
                  delay(1000);
                } 
              }
          }
       }
      
      remote_code_1 = savedIRCodes[0];
      remote_code_2 = savedIRCodes[1];
      remote_code_3 = savedIRCodes[2];
      remote_code_4 = savedIRCodes[3];
      remote_code_5 = savedIRCodes[4];
      remote_code_6 = savedIRCodes[5];
      delay(1000);
      Serial.println("Stored codes read.");
      Serial.println();
    }

    
 

 
void loop()
  {  
    // Check if the toggle is on or off. If it is on (in learn mode)
    // the switchPin is HIGH:
    learnMode = (digitalRead(switchPin) == HIGH);
    if (learnMode) 
      {    
        first_iteration = true;
        Reset();
        digitalWrite(statusPin, HIGH); // Turn learn mode LED on:
        learn_Mode();
        Reset();
        first_iteration = false; 
      } 
    else 
      {  
        digitalWrite(statusPin, LOW);  // Turn learn mode LED off:
        run_Mode();  
        first_iteration = false;     
      }
     
  }

Schematics

Breadboard layout with a Nano
Remote with nano mfy9rrcdyv

Comments

Similar projects you might like

Nero: A Smart Glove That Controls Remote Devices

Project tutorial by Team Nero

  • 3,930 views
  • 5 comments
  • 79 respects

Servo Control with TV Remote Control

Project showcase by eldo85

  • 14,067 views
  • 7 comments
  • 38 respects

Nano IR Remote for DC Motors

Project showcase by Boaz Lawnce

  • 2,961 views
  • 2 comments
  • 7 respects

Convert Your Old Phone to a Remote Switch

Project tutorial by Vishwas Navada

  • 11,886 views
  • 5 comments
  • 42 respects

Remote Lamp

Project tutorial by Kutluhan Aktar

  • 3,223 views
  • 0 comments
  • 7 respects

Control TV Using A Touch Remote

Project tutorial by the lonely programmer

  • 1,253 views
  • 2 comments
  • 9 respects
Add projectSign up / Login