// 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 ();_
_ } _
_ }_
_ }_
_}*_