/* 433Mhz learning remote control outlet with integrated timer Stefan Thesen, 2014 Copyright: public domain -> do what you want This code has been developed to make a learning remote control outlet with integrated timer out of the standard 10 pole DIP 433MHz remote control outlet which can be found in a lot of home improvement stores. D2 .. D12 are attached to the 10 pole DIP and have the functions listed below. For details visit http://blog.thesen.eu This code needs the rcswitch library. Load rcswitch code here http://code.google.com/p/rc-switch/ and copy to Arduino/libraries . Resstart IDE. CONNECTORS: All connectors need to be pulled to low for 'on'. D2 - attach to 433MHz RF in D3 - toggles learning mode (pull to low) D4 - resets - all learned codes lost (pull to low) D5 - sets relais on start to on or off (pull to low for on) D6 .. D12 - define timer for auto-off --> 128*2 Minute --> up to 4h 16 min D13 - attach to output relais */ #include #include ////////// // Globals ////////// RCSwitch mySwitch = RCSwitch(); unsigned long lStartTime_ms; // start time of last on command int iLearnMode; // plug in learning mode unsigned long lLastCommand; // last command received - used for learning int iConsRead; // consecutive, identical reads - used for learning long lTimeToRun_ms; // time for timer based switch-off // arrarys to store learned commands #define MAX_COMMANDS 10 int iNoValidCommand; struct RFCOMMAND { unsigned long lValidCommand; unsigned int iValidProtocol; unsigned int iValidBitLength; }; RFCOMMAND pRFCommand [MAX_COMMANDS]; //////////////////////////// // read RF codes from EEProm //////////////////////////// void WriteToEEProm() { int bytes, addr=0; eeprom_write_block((const void*)&iNoValidCommand, (void*)addr, sizeof(iNoValidCommand)); addr+=sizeof(iNoValidCommand); if (iNoValidCommand>0) { eeprom_write_block((const void*)pRFCommand, (void*)addr, sizeof(RFCOMMAND)*iNoValidCommand); } } /////////////////////////// // write RF codes to EEProm /////////////////////////// void ReadFromEEProm() { int bytes, addr=0; eeprom_read_block((void*)&iNoValidCommand, (void*)addr, sizeof(iNoValidCommand)); addr+=sizeof(iNoValidCommand); if ((iNoValidCommand>0) && (iNoValidCommand<=MAX_COMMANDS)) { eeprom_read_block((void*)pRFCommand, (void*)addr, sizeof(RFCOMMAND)*iNoValidCommand); } } //////////////////////////////// // read timer settings from pins //////////////////////////////// void ReadTimerSetting() { lTimeToRun_ms=0; for (int ii=0;ii<=6;ii++) { lTimeToRun_ms += (!digitalRead(6+ii)<<(ii+1)); // pin D6..D12 used for setting time - we can thus use 2 to 256 minutes for timer } Serial.print("Timer - Minutes to stay on: "); Serial.println(lTimeToRun_ms); lTimeToRun_ms *= 60000; // scale to ms } //////////////// // setup Routine //////////////// void setup() { // debug output Serial.begin(9600); Serial.println("433MHz Leraning Remote Plug started."); //////// // inits //////// lStartTime_ms=0; iLearnMode=0; lLastCommand=0; iConsRead=0; lTimeToRun_ms=0; for (int ii=0;iiMAX_COMMANDS)) { // read probably nonsense / not initialized data iNoValidCommand=0; } Serial.print("Read number of RF codes from EEProm:"); Serial.println(iNoValidCommand); // Receiver interrupt 0 on pin D2 mySwitch.enableReceive(0); // set D3-D12 as input for DIP switches for (int ipin=3;ipin<=12;ipin++) { pinMode(ipin,INPUT); // input digitalWrite(ipin,HIGH); // activate pull-up } // use D13 as output pinMode(13, OUTPUT); delay(500); // allow voltages to build up if (digitalRead(5)==LOW) // D5 determines start mode: on or off { digitalWrite(13, HIGH); lStartTime_ms = millis(); ReadTimerSetting(); Serial.println("Startmode: Switch on"); } else { digitalWrite(13, LOW); Serial.println("Startmode: Switch off"); } } /////////////// // loop Routine /////////////// void loop() { //////// // reset //////// if ((digitalRead(4)==LOW) && (iNoValidCommand!=0)) { iNoValidCommand=0; for (int ii=0;ii0) && (lTimeToRun_ms>0) && ( millis() > (lStartTime_ms+lTimeToRun_ms) ) ) { Serial.println("Time over - switch off"); digitalWrite(13, LOW); lStartTime_ms=0; } //////////////////// // handle RF receive //////////////////// if (mySwitch.available()) { int value = mySwitch.getReceivedValue(); if (value == 0) { Serial.print("Unknown encoding"); } else { Serial.print("Received "); Serial.print( mySwitch.getReceivedValue() ); Serial.print(" / "); Serial.print( mySwitch.getReceivedBitlength() ); Serial.print("bit "); Serial.print("Protocol: "); Serial.println( mySwitch.getReceivedProtocol() ); /////////// // learning /////////// if (iLearnMode==1) { // for learning request three consecutive identical readings if (lLastCommand == mySwitch.getReceivedValue()) { iConsRead++; if (iConsRead>=3) { int iCodeKnown=0; // code already known? - lazy check for value only // learn only even values (i.e. off values) long lCmd = mySwitch.getReceivedValue(); lCmd &= ~1; // kill lsb - we just learn off-commands (lowest bit off) for (int ii=0;ii