Pages: [1]   Go Down
Author Topic: Controlling Remote Controlled Sockets (SC2262 emulation by Arduino)  (Read 11163 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

- Arduino (mine is a Duemilanove) ATMega328
- AM Radio Transmitter Module: Quasar UK, "QAM-TX1" 433MHz",
  --  http://www.quasaruk.co.uk/acatalog/AM_Transmitter_-_TX1.html
- Three wires
- Pre-packed remote controlled sockets by "smj Electrical" [Maplin.co.uk Order Code: N79FN]

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.
« Last Edit: May 10, 2011, 06:07:43 am by CaptainIffy » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

// 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. tithby<dot>hill<at>ifcraig.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: http://www.gnu.org/licenses/.

#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 ();
         }  
      }
   }
}
« Last Edit: May 10, 2011, 06:08:01 am by CaptainIffy » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 28
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.


Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Jr. Member
**
Karma: 3
Posts: 52
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.


* Remote.jpg (44.67 KB, 600x672 - viewed 40 times.)
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!
« Last Edit: January 09, 2014, 02:50:37 pm by ali12345 » Logged

Pages: [1]   Go Up
Jump to: