Controlling Remote Controlled Sockets (SC2262 emulation by Arduino)

Hi,

As my first project, I wanted to use my PC to control the switching of a few cheap remote controlled sockets in my house. I "googled" for an existing solution, failed miserably, so have made my own. The only components required:

These remote controlled switches use an SC2262 chip to encode a data packet that (in my case) is modulated to 433MHz. Initially I tried building a circuit similar to the 433MHz handset of the remote controlled socket, but I could not get it to work: the answer is embarrassingly easy: emulate the output of the 2262 encoder chip using the Arduino and send to a 433 MHz AM transmission unit. A quick search on eBay revealed an AM transmitter that promised: "The module is very simple to operate and offers low current consumption (typ. 15mA). Data can be supplied directly from a microprocessor or encoding device, thus keeping the component count down and ensuring a low hardware cost."

Using a "DSO Nano V2" oscilloscope" (and a magnifying glass to examine the handset), I discovered the encoding and frequencies generated. The Arduino's "delayMicroseconds ()" function allowed me to reproduced the data packet to be transmitted and I sent it to the AM Transmitter. I won't say it worked immediately, but it does work now. The range is more than 20metres - without an ariel.

I use "System Scheduler" from SplinterWare to schedule on/off commands to the remote controlled sockets via a very simple DOS batch script.

Next project - download schedule to Arduino, so that the remote controlled sockets are controlled when the PC is off (but the Arduino is independently powered) OR woodstove monitor to remind me to put more fuel in when it starts to run out.

// SC2262 Emulator / Controller for radio-controlled sockets
//
// This project aims at computer controlling the power to devices around my home.
//
// Kit list:
// 1x Arduino Duemilanove ATMege328
// 1x AM Radio Transmitter Module: Quasar UK, "QAM-TX1" 433MHz, http://www.quasaruk.co.uk/acatalog/AM_Transmitter_-_TX1.html
// 1x "smj electrical" "remote control socket" [Maplin Order Code: N79FN]
// Connect Arduino Digital pin13 to Transmitter "Data"
// Connect Arduino Power "5v" to Transmitter "VCC"
// Connect Arduino Power "Gnd" to Transmitter "GND"
//
// Windows "bat" file relays arguments to my Arduino: argument: "smj[A|B|C|D][1|2|3][on|off]" eg. "smjA1on"
//@echo off
//mode com3 baud=9600 data=8 parity=n stop=1 xon=on odsr=off octs=off rts=off dtr=off
//echo %* > com3
// -- Use "Splinterware" "System Scheduler" to automate operation of the Arduino via the above ".bat" file.

// V3 Date: 2011 05 01

// Copyright (C) 2011 Ian Craig, Tithby Hill Limited. tithbyhillifcraig.com.
//
// This program 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.
//
// A copy of the GNU General Public License is available at: Licenses - GNU Project - Free Software Foundation.

#define TRANSMITTER 13 // The Arduino output pin 13 is used to drive 433 MHz AM transmitter
#define SC2262Clock 100 // SC2262 internal clock is run at 10KHz for "smj" transmitter device (3.3MOhm timing resistor), therefore 100 microSecond wavelength

// sc2262pins is an array that indicates the voltage applied to the simulated SC2262 chip pins
char sc2262pins[] = "FFFFFFFFFFFF"; // H=High, L=Low or F=Floating for 12 pins

// These globals are defaults, for different devices they are changed by "SetSC2262Clock()".
// 16 cycles per bit, 2 bits per SC2262 tri-state address/data pin, 12 address/data pins on SC2262
int DurationShort;
int DurationLong;
int DurationSyncShort;
int DurationSyncLong;

// -----------------------------------------------------------------------------
// Basic SC2262 output emulation

// Input wavelength of SC2262 internal clock in micro-seconds to get revised timings for basic components of packet that simulates SC2262 output
void setSC2262Clock (int sc2262Clock)
{ // One bit of two-bit tri-state pin state takes 16 cycles
DurationShort = sc2262Clock * 4; // 4 clock cycles for short part of bit
DurationLong = sc2262Clock * (16-4); // 12 clock cycles for long part of bit
DurationSyncShort = sc2262Clock * 4; // Sync bit has a 4 cycle/short "high", followed by 124 bit "low"
DurationSyncLong = sc2262Clock * (128-4); // Sync bit has a 4 cycle/short "high", followed by 124 bit "low"
}

void longShort ()
{ digitalWrite (TRANSMITTER, HIGH);
delayMicroseconds (DurationLong);
digitalWrite (TRANSMITTER, LOW);
delayMicroseconds (DurationShort);
}

void shortLong ()
{ digitalWrite (TRANSMITTER, HIGH);
delayMicroseconds (DurationShort);
digitalWrite (TRANSMITTER, LOW);
delayMicroseconds (DurationLong);
}

// Sync has a long pause after packet sent
void sync ()
{ digitalWrite (TRANSMITTER, HIGH);
delayMicroseconds (DurationSyncShort);
digitalWrite (TRANSMITTER, LOW);
delayMicroseconds (DurationSyncLong);
}

// Tri-state logic on/off/float of signals emulated here
void pinLow ()
{ shortLong ();
shortLong ();
}

void pinHigh ()
{ longShort ();
longShort ();
}

void pinFloat ()
{ shortLong ();
longShort ();
}

// Packet terminated with on of these
void syncBit ()
{ sync ();
}

// -----------------------------------------------------------------------------
// Send SC2262 packet

// Send repeat of packets - to be sure (min 2 times - 6 is good)
void sendSC2262Packet ()
{ // Send packet, repeated in blocks - overkill is OK, underkill is a disaster
for (int i=0; i < 10; i++)
{ sendOneSC2262Packet();
sendOneSC2262Packet();
sendOneSC2262Packet();
sendOneSC2262Packet();
sendOneSC2262Packet();
sendOneSC2262Packet();

delay (100);
}
}

// This will send one packet to receivers - not enough!
void sendOneSC2262Packet ()
{ noInterrupts();
for (int i=0; i<12; i++)
{ switch (sc2262pins*)*

  • { case 'H':*

  • pinHigh();*

  • break;*

  • case 'L':*

  • pinLow();*

  • break;*

  • case 'F':*

  • pinFloat();*

  • break;*

  • }*

  • } *

  • syncBit ();*

  • interrupts();*
    }
    // -----------------------------------------------------------------------------
    // Serial port / PC communication
    void serialRx_waitForSMJ () // Looking for "smj"
    { boolean gotS = false;

  • boolean gotM = false;*

  • while (true)*

  • { if (Serial.available() > 0)*

  • { switch (Serial.read())*

  • { case 's':*

  • case 'S':*

  • gotS = true;*

  • gotM = false;*

  • continue;*

  • case 'm':*

  • case 'M':*

  • if (gotS == true && gotM == false)*

  • { gotM = true; }*

  • else*

  • { gotS = false;*

  • gotM = false;*

  • }*

  • continue;*

  • case 'j':*

  • case 'J':*

  • if (gotS == true && gotM == true)*

  • { *

  • return;*

  • }*

  • else*

  • { gotS = false;*

  • gotM = false;*

  • }*

  • continue;*

  • default:*

  • gotS = false;*

  • gotM = false;*

  • }*

  • }*

  • else*

  • { delay (100);*

  • }*

  • }*
    }
    boolean serialRx_getABCD() // Looking for "A,B,C or D"
    { if (Serial.available() > 0)

  • { switch (Serial.read())*

  • { case 'A':*

  • case 'a':*

  • sc2262pins[0] = 'L';*

  • return true;*

  • case 'B':*

  • case 'b':*

  • sc2262pins[1] = 'L';*

  • return true;*

  • case 'C':*

  • case 'c':*

  • sc2262pins[2] = 'L';*

  • return true;*

  • case 'D':*

  • case 'd':*

  • sc2262pins[3] = 'L';*

  • return true;*

  • }*

  • }*

  • // Give up*

  • return false;*
    }
    boolean serialRx_get123 () // Looking for "1,2 or 3"
    { if (Serial.available() > 0)

  • { switch (Serial.read())*

  • { case '1':*

  • sc2262pins[4] = 'L';*

  • return true;*

  • case '2':*

  • sc2262pins[5] = 'L';*

  • return true;*

  • case '3':*

  • sc2262pins[6] = 'L';*

  • return true;*

  • }*

  • }*

  • // Give up*

  • return false;*
    }
    boolean serialRx_getOnOrOff () // Looking for "on or off"
    { if (Serial.available() > 1)

  • { if (Serial.read() == 'o')*

  • { switch (Serial.read())*

  • { case 'n':*

  • sc2262pins[11] = 'H';*

  • return true;*

  • case 'f': *

  • sc2262pins[11] = 'L';*

  • if (Serial.available()) Serial.read(); // Don't really care about 2nd 'f' in "off"*

  • return true;*

  • }*

  • }*

  • }*

  • // Give up*

  • return false;*
    }
    // -----------------------------------------------------------------------------
    // Main bit
    void setup ()
    { // Wait for bootloader to get out of the way

  • delay (2000);*

  • // initialize the serial communication:*

  • Serial.begin (9600);*

  • // Tell Arduino which pin used for output to 433MHz transmitter*

  • pinMode (TRANSMITTER, OUTPUT);*

  • // Initialise output to low*

  • digitalWrite (TRANSMITTER, LOW);*

  • // Set frequency of encoded packet [for "smj" socket device 3M3 ohms/(1MHz, 32 cycles per word)]*

  • setSC2262Clock (SC2262Clock);*
    }
    void loop ()
    { // Looking for: "smj[A|B|C|D][1|2|3][on|off]" from computer

  • // Step 1: Wait for "smj" to be sent to Arduino. Ignore everything else.*

  • serialRx_waitForSMJ ();*

  • // Reset pattern to simulate the pins of an SC2262 packet*
    _ for (int i=0; i<12; i++) sc2262pins = 'F';_
    * // If the rest of the string isn't here (after the delay) then give up*
    * delay (500);*
    * if (serialRx_getABCD ()) // Looking for "A,B,C or D"
    { if (serialRx_get123 ()) // Looking for "1,2 or 3"
    { if (serialRx_getOnOrOff ()) // Looking for "on" or "off"
    _
    { // Serial.print ("SC2262 pins: ");_
    _
    // Serial.println (sc2262pins);_
    _
    sendSC2262Packet ();_
    _
    } _
    _
    }_
    _
    }_
    _
    }*_

I've just realised that the radio transmitter has an 11mA (max 22mA) specification. Since my Duemilanove can supply 40mA per digital IO pin, I can use the digital IO to power the transmitter with a simple connection. This means that I can turn the transmitter on just before sending the signal (20mS min) and off afterwards. The transmitter won't be broadcasting the carrier wave all the time, and the power consumption is reduced.

i did the same thing but i used the deomotic home softgware for my htc desire.
and modified it to work with any rf controlled wall socket
its network controlled over the internet and both from my phone and from a random pc.
its programmed to turn on the garden lights at 9:30 and turn them off at 23:30

i use the arduino to read the rf codes from any rf 433 hz remote and transmit them back when needed.

Tricky to port this app to a Netduino Plus - it does not support microsecond timings. It seems that the C# garbage collector can blunder about messing up my timings. Bit of a shame, the built-in network interface, memory card and extra RAM promised an app that would allow me to turn my PC off and a web/cron interface.

CaptainIffy - Thanks for this post. It is very informative. Have you done any work on the receive side of things? My planned project is the opposite of your work - I want to handle the receive side of things. Specifically, I want to use an Arduino to receive 433MHz transmissions from a remote keyfob that uses a SC2262 chip. The specific keyfob that I am going to use costs under $8US and is commonly sold on eBay and included with cheap Chinese alarm systems, also sold on eBay. I have attached a photo of the target keyfob.

CaptainIffy, thanks! this is very close to what i am working on.

I do not have a "DSO Nano V2" oscilloscope, but i do have a 4333 MHz receiver for the arduino uno, and i was hoping to use that to decode the signal the remote transmits.

I understand it should be possible, but i was trying to determine what rate i should read from the transmitter. I see that you found that using from the 3.3MOhm resistor value.

// SC2262 internal clock is run at 10KHz for "smj" transmitter device (3.3MOhm timing resistor), therefore 100 microSecond wavelength

My SC2262 has a 1MOhm resistor value, i was unsure how you calculated the wavelength from that. Could you please explain that?

In order to start to ply with this project I've tried to upload the code as is, with the TX unit connected, but i'm getting a verify error on the code, I've looked through it but can't understand why it's having an issue with the array on line 121, error:

sketch_nov22a.ino: In function 'void sendOneSC2262Packet()':
sketch_nov22a:121: error: switch quantity not an integer
sketch_nov22a.ino: In function 'void loop()':
sketch_nov22a:270: error: incompatible types in assignment of 'char' to 'char [13]'.

Is anyone able to point me in the right direction?

Many thanks,
Stuart.

aero9 - The frequency/wavelength relationship with the resistor value is in the sc2262 chip specification.

Nice job. I bought all the same parts a couple of years ago intending to do this but I never got around to implementing it until today.

There's a couple of bugs in the code - a few array indices are missing (that's causing the error Stuart_B reported above), and I replaced the command parser with one that works off a single character. After that it worked fine. It works much better than the actual remote!