Enter Your Project for a chance to win a grand prize for the most innovative use of Arduino or a $200 shopping cart! The Birthday Special: Arduino Projects for Arduino Day! | Project14 Home | |
Monthly Themes | ||
Monthly Theme Poll |
This project was a suggestion from the publisher of TheShed magazine https://www.theshedmag.co.nz
He was using those mechanical timers to turn on lights while he was away, and got sick of them failing.
We had been keen to find a solution to switch mains that was safe for readers.
As we've seen here Mains and Safety aren't always sitting together in some posts, and element14 has supported our efforts to rectify this.
I'd looked at the wireless outlets that were available through a NZ and Australian retailer, and were affordable.
So the question of replacing his timers with some controller and wireless outlets was more of an exercise in how.
Concept
It was obvious that I'd use an Arduino as the controller, and wireless power outlets as the device to replace the mechanical timers.
The issue was how to program it, and get that information into the unit with the skill set I had. (it was 2012)
This Design process was a piece of software on my tablet, and I found it very useful to draw out the various options.
( I must start using it again )
As you see from above, the choices for the controller were standard with shield or add-on cards, or special version Arduinos.
I'd put this as Step 2 in my Electronic Diet - Engineering a Solution blog
I identified that an SD card could hold the data, and was able to be removed and programmed with the times, etc.
Keeping time was going to be handled by an RTC.
Initially we thought about hacking a remote control to provide the 433MHz RF, but while looking around I stumbled across RCSwitch
https://github.com/sui77/rc-switch
This allowed an Arduino and RF transmitter to communicate with these outlets, which also allowed more codes than the remote had.
Hence the following block diagram became the plan.
Having a plan always makes it easier to focus on the various parts required.
Hardware
I identified that we would use an Arduino, but needed RTC and SD card along with a connection to the RF Transmitter.
We had in mind that this would be useful to readers so a complicated build was out of the question.
Luckily I ran across some clever guys at Wyolum (sadly the website is not around any more) who created a nifty board that slotted into an Arduino to interface with a GPS receiver.
It included the microSD card, RTC and had a few I/O pins to interface to the outside world.
I did run a few jumpers to connect the Analogue inputs to the header where they normally would reside.
PC0 to P5 pin 1, PC 1 to P5 pin2, PC2 to P5 pin 3 and D to P5 pin 4 along with power to where Vin would be.
The transmitter and connectors were fitted onto a piece of a prototyping shield.
The button is used to start it running.
Programming is via an FTDI cable.
OUTLETS
I used the WattsClever and discovered that they could be programmed for codes greater then the remote provided.
The codes are attached below
It appears that bit 21 is changed between the On and OFF, so it's very easy when controlling these devices.
One of the units had a light, and it seems that all the units have two channels, with bit 24 controlling the 2nd channel.
SOFTWARE
I can honestly say I have never spent as much time on what appeared to be a very simple task.
I ran out of memory and each debug I added created more problems.
In the end I removed all the Serial.print statements and attacked the RCSwitch library to reduce it's size.
This library includes receiver and other functions, and for this project I only needed transmit.
I also had to modify the DS3231 library.
The Minder.txt file on the SD card consists of a series of instructions.
It is limited to 20 events, 8 channels and assumes that file is correctly formatted. (for you Americans, this is how we do dates dd/mm/yy)
Channels =8
Clock =2359
Date =300812
Time =2300,ON
Channel =1,2,3,4,5,6,7,8
Day =mon,tue,wed thur,fri,sat,sun
Time =2310,OFF
Channel =1,2
Day =mon,tue
Time =2330,OFF
Channel =8
Day =mon,tue,wed,thur,fri,sat,sun
Time =2330,OFF
Channel =1,2
Day =wed,thur,fri,sat,sun
This file also functions as the method of setting the RTC time and date.
These are the notes I wrote at the time :-
When the sketch starts, it attempts to read the file, Minder.txt..
It reads and stores the first 20 Events, and will ignore any further events.
If an Error is detected, it will flash LED1. (see Errors below).
If the RTC (Real Time Clock) is less than the date setting in the file, it will set the clock based on lines 2 and 3 of the file.
The sketch will then cycle through channels 1-8 every 10 secs, turning ON a channel and 5 secs later, turning it OFF.
This gives the Home owner a chance to check the outlets are being operated correctly.
This will continue until the ‘Go’ button is pressed, which sets the RTC to the date/time in file.
The ‘Go’ button signals that the sketch is ready to run, and after setting the Date/Time, it writes the date to the EEPROM.
The EEPROM data remains when the Arduino is restarted, which may be due to a power failure.
Once it has written to the EEPROM, the sketch checks the time every 10 seconds, and every minute, it will step through the Events to see if one matches the current time.
Once it finds a match, it will see if the Day of Week matches the DOW in the Event.
If a match(s) is found, the channel(s) for that Event are sent each time it checks the time (ie every 10 secs).
This ensures the wireless outlet has 5 or 6 chances to detect the code.
Each Event is either an ON or an OFF with certain channels (and DOW). It is possible to have an ON Event for channels 1,2 and an OFF Event for channels 3,4 with the same time.
The sketch will cycle through all events, so the order is not important.
There is some error checking which will result in a failure to run ie a Fatal Error as well as some indications to the user.
My notes at the time are :-
There are a number of Errors that mean the sketch cannot run. I have called these Fatal errors.
If one of these is generated, the sketch will display the appropriate Error Code and not process any Events.
Fatal Error Codes:
12 Unable to access/set RTC (long and 2 shorts)
13 Error accessing card/file (long and 3 shorts)
14 Error in file (long and 4 shorts)
There are a number of other Error codes that indicate a problem was encountered, but was able to be rectified.
In the case of ErrorCode 2, it may mean the time is not accurate, but it will continue running.
Non Fatal Error Codes:
0 Signals normal operation (single flash)
2 Signals a restart. (2 short)
5 Clock was reset to card value. (5 short)
Code
I've included the code which is close to the limitations, so care is needed about which Arduino you program it into.
If you modify it, be aware that you may have memory issues.
The zip file also contains the modified libraries, and the Utility sketch.
/* HOME MINDER This uses an DS3231 RTC, SD card and transmitter to control Wireless Power Outlets. Events are read from the file 'Minder.txt' into memory and then acted upon. A utility program allows the Outlets to be matched against the Channels 1-8. The RTC time/date can also be set. The code to transmit is based on the work of the guys at RCSwitch ( see http://code.google.com/p/rc-switch/ ) The sketch runs a POST which checks it can find and read 'Minder.txt' on the card. This is then broken down into its component parts and an error generated if the syntax is wrong. The RTC is checked and if invalid, the sketch uses the time/date in the file to set the RTC. A non fatal error code is generated if the time can be set. A successful POST will :- Turn the LED ON for 5 secs, and then flash regularily as a watchdog. Cycle through all the channels set in the file, until the 'Go' button is pressed Write the Date and Time from Minder.txt to the EEPROM, to use for subsequent restarts. It will also set the Date/Time from Minder.txt into the RTC when the Go buton is pressed. At sebsequent startup :- Performs POST Reads in Events to memory Checks EEPROM to match date/time. The Article was written using an I2GPS Board from www.wyolum.com (The Shed has stocks as well), which includes a MicroSD Card and DS3231 RTC along with an ATmega 328. The intention is to run the sketch in an ALaMode, which plugs onto a RaspberryPi, and provide greater interaction, and other functions. These were only just becoming available when this project was started. Enjoy Mark Beckett -------------------------------------------------------------------------- Pin assignments Pin 0 Rx Pin 1 Tx Pin 2 Pin 3 Pin 4 LED1 (I2GPS_v1 Board) Pin 5 Pin 6 Pin 7 LED2 (I2GPS_v1 Board) Pin 10 SD_CS , SS } Pin 11 SD_DATA_IN, MOSI } Card Pin 12 SD_DATA_OUT, MISO } Reader Pin 13 SC_CLK, SCK } Pin A0 (D14) Go Button Pin A1 (D15) Pin A2 (D16) Pin A3 (D17) Transmit data Pin A4 SDA I2C Data } RTC (i2GPS Board) Pin A5 SCA I2C Clock } RTC (I2GPS Board) created 1 Sept 2012 by Mark Beckett Version 0.1 Initial Code started 01 Apr 2012 1.0 Rewrite of code and libraries Dec 2012. Problems with memory resulted in libraries optimised to essentials only. This resulted in code changes and variable changes to compensate. Some features have been eliminated, and some assummed, in order to ensure stable operation. --------------------------------------------------- To Do : Utilise the RaspberryPi to do logging functions, which will eliminate the memory issues in Arduino. ****************************************** I make no apologies for the code used in the sketch below. The series is designed to help introduce novice programmers (including me), and as such code that can be followed is more important. Also I fix things for a living, rather than write software, so to all you programmers ....I'm sorry Mark Beckett ***************************************** */ #include #include <mod_rcswitch.h><mod_rcswitch.h> // Heavily modified #include File myFile; #include #include<mod_ds3231.h> <mod_ds3231.h> // Heavily modified I2GPS RTC DS3231 Clock; // Init the DS3231 RCSwitch mySwitch = RCSwitch(); //( see http://code.google.com/p/rc-switch/ ) // Card reading variables String fileString; String fileLineSub; char inChar; int Event[20][3]; //Event number to the maximum of 20, with three element for each Event byte EventNum=0; //counter for the Events 0-19 byte n =0; // size of the line byte linepos; // line position integer byte linenum =0; // line number integer // Inputs and Outputs const int ledPin1 = 4; // I2GPS_v1 Board LED 1 (additional LED) const int ledPin2 = 7; // I2GPS_v1 Board LED 2 (normally pin 13) const int GoButton = A0; // Go button on A0 //General purpose byte ErrorCode=0; // see DisplayError() byte FlashCount=0; // Used in loop to count errorcode flashes byte Eventcounter =0; // counter used for looping Events byte Channelcounter =0; // counter used for looping Events byte EventChannels=0; // byte to hold the binary of the channels for the Event boolean GoButtonState = false; // Used to detect if sketch has started // Channel OFF codes 1 to 8 for Watts Clever. Add 8 for ON code const unsigned long ChannelCodes[] = {13998166,13998164,13998162,13998176,13998178,13998180,13998182,13998192}; // RTC related variables unsigned long RTCDateCalc; //used to hold the manipulated reading from RTC unsigned long CardDateCalc; //used to hold the manipulated reading from SD card byte RTCsetHour; //RTC Hour byte RTCsetMin; //RTC Minute byte RTCsetYear; //RTC Year byte RTCsetMonth; //RTC Month byte RTCsetDay; //RTC Day byte DOW; //RTC Day of Week mon =1 String RTCsetDOW; //RTC Day of the week (1=mon, 7=sun), Minder.txt uses mon, tue to avoid confusion char* DaysOfWeek[]={"mon", "tue", "wed", "thur", "fri", "sat", "sun"}; bool Century; bool h12; bool PM; byte DoW; //Clock DOW (Day Of Week) // Timer variables int LastTime; // value to hold the last time we checked the read time int CurrentTime; // value to hold the current read time unsigned long LastTimerCheck = 0; // Time the Timer was read. unsigned long ChannelOn = 0; // Time the Channel was turned On. boolean CodeSent = false; //used in StartUpCheck() void setup() { Serial.begin(9600); showString(PSTR("Home Minder test Sketch\n")); pinMode(ledPin1, OUTPUT); pinMode(ledPin2, OUTPUT); pinMode(GoButton, INPUT); digitalWrite(GoButton, HIGH); // activate the Pullup resistor pinMode(10, OUTPUT); // used by SD card pinMode(A3, OUTPUT); // used by Transmitter myFile.close(); Wire.begin(); if (!SD.begin(10)) { showString(PSTR("initialization failed!\n")); ErrorCode = 13; // Error accesing card/file DisplayError(); } // Transmitter is connected to Arduino Pin A3 //mySwitch.enableTransmit(A3); // hardcoded in RCSwitch // Optional set protocol (default is 1, will work for most outlets) mySwitch.setProtocol(1); // Optional set number of transmission repetitions. // mySwitch.setRepeatTransmit(15); // We read the clock every 10 secs, therefore we repeat the send 6 times per minute, so not needed. myFile = SD.open("Minder.txt"); ReadFile(); myFile.close(); ClockRead(); if (RTCDateCalc < CardDateCalc) { ErrorCode = 5; // set ErrorCode to show Clock was reset ClockSet(); // set clock using setting in Minder.txt ClockRead(); // check to see it was able to be set if ((RTCDateCalc) != (CardDateCalc)) { ErrorCode = 12; DisplayError(); //Can't access/set RTC so Fatal Error. } } StartUpCheck(); //Check to see if the sketch has been running, or waiting for the 'Go' button } void loop(void) { if (GoButtonState == true) // has sketch been started yet, but should never get here unless started. { if (ErrorCode >= 10) // Errors above 10 are Fatal, but should never arrive here, so send it away. { DisplayError(); } if ( (millis() - LastTimerCheck) > 10000) // only need to check every 10.0 secs { LastTimerCheck = millis(); ClockRead(); //Go check the RTC time. EventCheck(); switch (ErrorCode) { case 0: digitalWrite(ledPin1, HIGH); delay (300); digitalWrite(ledPin1, LOW); break; case 2: do { digitalWrite(ledPin1, HIGH); //flash the short pulses to represent the units delay(1000); digitalWrite(ledPin1, LOW); delay(500); FlashCount ++; } while (FlashCount < 2); FlashCount =0; break; case 5: do { digitalWrite(ledPin1, HIGH); //flash the short pulses to represent the units delay(1000); digitalWrite(ledPin1, LOW); delay(500); FlashCount ++; } while (FlashCount < 5); FlashCount =0; break; } } } } void ReadFile() { if (!myFile) { ErrorCode = 13; return; } /* read lines from the file Channels =8 Clock =2359 Date =300812,mon */ ReadFileHeader: //This is a label to send the loop back to if (myFile.available()) { inChar = myFile.read(); if(inChar < 0) { if (EventNum < 1) { ErrorCode = 14; //Error in file no entries } return; // File is closed on return } if (inChar != 13) { fileString.concat(inChar); goto ReadFileHeader; } inChar = myFile.read(); //This should grab the LF char. n = fileString.length(); fileString = fileString.toLowerCase(); //ensure we know the characters linepos = fileString.indexOf('='); fileLineSub = fileString.substring(linepos +1, n); //fileLineSub contains from the '=' onwards. switch (linenum) { case 0: //setCNLnum = fileLineSub.toInt(); // Channels =8 (not used) break; case 1: RTCsetHour = (fileLineSub.substring(0,2)).toInt(); RTCsetMin = (fileLineSub.substring(2,4)).toInt(); break; case 2: RTCsetDay = (fileLineSub.substring(0,2)).toInt(); // extract DD and convert to an integer RTCsetMonth = (fileLineSub.substring(2,4)).toInt(); // extract MM and convert to an integer RTCsetYear = (fileLineSub.substring(4,6)).toInt(); // extract YY and convert to an integer RTCsetDOW = fileLineSub.substring((fileLineSub.indexOf(','))+1, n); // DOW =mon CardDateCalc = ((RTCsetYear) *10000UL) + ((RTCsetMonth) *100) + (RTCsetDay); break; } fileString=""; if (linenum <2) { linenum ++; goto ReadFileHeader; } /* first three lines read in, now to pick up the events max is 20 loaded as 0-19 Time =2300,ON Channel =1,2,3,4,5,6,7,8 Day =mon,tue,wed,thur,fri,sat,sun */ linenum=0; ReadFileEvents: //This is a label to send the loop back to inChar = myFile.read(); if(inChar <= 0 || ((EventNum) > 19)) //sketch limited to 20 events, so ignore the end ones. { return; // File is closed on return } if (inChar != 13) //build up the string until a CR { fileString.concat(inChar); goto ReadFileEvents; } inChar = myFile.read(); //This should grab the LF char. n = fileString.length(); fileString = fileString.toLowerCase(); //ensure we know the characters linepos = fileString.indexOf('='); fileLineSub = fileString.substring(linepos +1, n); //fileLineSub contains from the '=' onwards. switch (linenum) { case 0: // This adds either 4096 to the Event Time for OFF, and 8192 for an ON. if ((fileLineSub.indexOf('off'))> -1) { fileLineSub = fileLineSub.substring(0, fileLineSub.indexOf(',')); Event[EventNum][linenum] = 4096 + fileLineSub.toInt(); // line upto the ',' then turn in into a number and add 4096 for 'OFF' } if ((fileLineSub.indexOf('on'))> -1) { fileLineSub = fileLineSub.substring(0, fileLineSub.indexOf(',')); Event[EventNum][linenum] = 8192 + fileLineSub.toInt(); // line upto the ',' then turn in into a number and add 8192 for 'ON' } break; case 1: // This steps through the line and makes a binary number 0-254 based on each Channel // We modified 'fileLineSub' in the above case, so reload the substring. fileLineSub = fileString.substring(linepos +1, n); //linepart contains from the '=' onwards. if ((fileLineSub.indexOf("1"))> -1) { Event[EventNum][linenum]= 1+ (Event[EventNum][linenum]); } if ((fileLineSub.indexOf("2"))> -1) { Event[EventNum][linenum]= 2+ (Event[EventNum][linenum]); } if ((fileLineSub.indexOf("3"))> -1) { Event[EventNum][linenum]= 4+ (Event[EventNum][linenum]); } if ((fileLineSub.indexOf("4"))> -1) { Event[EventNum][linenum]= 8+ (Event[EventNum][linenum]); } if ((fileLineSub.indexOf("5"))> -1) { Event[EventNum][linenum]= 16+(Event[EventNum][linenum]); } if ((fileLineSub.indexOf("6"))> -1) { Event[EventNum][linenum]= 32+ (Event[EventNum][linenum]); } if ((fileLineSub.indexOf("7"))> -1) { Event[EventNum][linenum]= 64+ (Event[EventNum][linenum]); } if ((fileLineSub.indexOf("8"))> -1) { Event[EventNum][linenum]= 128+ (Event[EventNum][linenum]); } break; case 2: // This steps through the line and makes a binary number 0-127 based on each day if ((fileLineSub.indexOf("mon"))> -1) { Event[EventNum][linenum]= 1+ (Event[EventNum][linenum]); } if ((fileLineSub.indexOf("tue"))> -1) { Event[EventNum][linenum]= 2+ (Event[EventNum][linenum]); } if ((fileLineSub.indexOf("wed"))> -1) { Event[EventNum][linenum]= 4+ (Event[EventNum][linenum]); } if ((fileLineSub.indexOf("thur"))> -1) { Event[EventNum][linenum]= 8+ (Event[EventNum][linenum]); } if ((fileLineSub.indexOf("fri"))> -1) { Event[EventNum][linenum]= 16+(Event[EventNum][linenum]); } if ((fileLineSub.indexOf("sat"))> -1) { Event[EventNum][linenum]= 32+ (Event[EventNum][linenum]); } if ((fileLineSub.indexOf("sun"))> -1) { Event[EventNum][linenum]= 64+ (Event[EventNum][linenum]); } EventNum ++; break; } linenum ++; if (linenum ==3) { linenum =0; } fileString=""; fileLineSub=""; goto ReadFileEvents; } else { ErrorCode = 13; // Error accesing card/file myFile.close(); return; } } void StartUpCheck() { // This checks to see if the sketch is running for the first time if (RTCsetYear != (EEPROM.read(1)) || RTCsetMonth != (EEPROM.read(2)) || RTCsetDay != (EEPROM.read(3))) { if (ErrorCode ==5) { ErrorCode =0; // reset the code as not started yet. } digitalWrite(ledPin1, HIGH); // Turn On Led1 to show no errors LastTimerCheck = millis(); // Borrow the timer variable Channelcounter = 0; while (GoButtonState == false) { if (millis()-LastTimerCheck >=5000) // Led1 should be on for 5 secs { digitalWrite(ledPin1, LOW); LastTimerCheck =0; // Reset the borrowed timer variable } if (digitalRead(GoButton) == LOW) { delay(100); //check to see the button is pressed by waiting 100mS (We can accept a delay here) if (digitalRead(GoButton) == LOW) { GoButtonState = true; // Sketch has been started EEPROM.write(1, RTCsetYear); // Write it to EEPROM EEPROM.write(2, RTCsetMonth); EEPROM.write(3, RTCsetDay); digitalWrite(ledPin1, LOW); // Turn off the LED LastTimerCheck =0; // Reset the borrowed timer variable ClockSet(); // Set the clock based on 'Minder.txt' setting mySwitch.send(13998161, 24); // All OFF command digitalWrite(ledPin2, LOW); showString(PSTR("Go Button pressed\n")); return; // Exit here so we don't set ErrorCode at the end. } } //Cycle thru codes at set rate if (LastTimerCheck ==0) { if (ChannelOn ==0 || (millis()-ChannelOn) > 10000) // 10 seconds { digitalWrite(ledPin2, HIGH); ChannelOn= millis(); CodeSent = true; mySwitch.send(((ChannelCodes[Channelcounter])+8), 24); //send on code showString(PSTR("Channel ")); Serial.print(((Channelcounter)+1),DEC); showString(PSTR(" ON ")); } } if (CodeSent == true && (millis()-ChannelOn) > 6000) // 6 seconds { //send off code digitalWrite(ledPin2, LOW); CodeSent = false; showString(PSTR(" : OFF\n")); mySwitch.send(ChannelCodes[Channelcounter], 24); Channelcounter ++; if (Channelcounter == 8) //Channelcounter is zero based, 8 channels max { Channelcounter =0; } } } } else { if (digitalRead(GoButton) == LOW) { delay(100); //check to see the button is pressed by waiting 100mS (We can accept a delay here) if (digitalRead(GoButton) == LOW) { showString(PSTR("Go Button pressed\n")); GoButtonState = true; ErrorCode = 0; // Restart has been detected so set the ErrorCode } } else { //we have to assume we have started so change GoButtonState to true. GoButtonState = true; ErrorCode = 2; // Restart has been detected so set the ErrorCode showString(PSTR("Restart detected\n")); } } return; } void showString (PGM_P s) { char c; while ((c = pgm_read_byte(s++)) != 0) Serial.print(c); } void EventCheck() { //This process will check each event against the time for (Eventcounter=0; Eventcounter <= 19; Eventcounter++) //cycle thru 20 events { if (((Event[Eventcounter][1])-4096) == CurrentTime) { SendOffChannels(); } if (((Event[Eventcounter][1])-8192) == CurrentTime) { SendOnChannels(); } } return; } void SendOffChannels() { if (Event[Eventcounter][3] & (1<< (DoW-1)) >0) //Event[Eventcounter][2] will be binary 0-254 AND with DOW shifted { // cycle through the channels and send the code from ChannelCodes[] EventChannels = Event[Eventcounter][2]; for (Channelcounter=0; Channelcounter <= 7; Channelcounter++) //cycle thru 8 Channels { if (EventChannels & (1<< Channelcounter) ) //EventChannels will be binary 0-254 AND with Channelcounter shifted { digitalWrite(ledPin2, HIGH); mySwitch.send(ChannelCodes[Channelcounter], 24); delay(300); //300mS delay here is subtracted by the millis() timers digitalWrite(ledPin2, LOW); } } } return; } void SendOnChannels() { if (Event[Eventcounter][3] & (1<< (DoW-1)) >0) //Event[Eventcounter][2] will be binary 0-254 AND with DOW shifted { // cycle through the channels and send the code from ChannelCodes[] EventChannels = Event[Eventcounter][2]; for (Channelcounter=0; Channelcounter <= 7; Channelcounter++) //cycle thru 8 Channels { if (EventChannels & (1<< Channelcounter) ) //EventChannels will be binary 0-254 AND with Channelcounter shifted { digitalWrite(ledPin2, HIGH); mySwitch.send((ChannelCodes[Channelcounter]+8), 24); delay(300); //300mS delay here is subtracted by the millis() timers digitalWrite(ledPin2, LOW); } } } return; } void DisplayError() { /* Flashes the LED to show an error, so delays are acceptable. It should stay in this mode, until reset by power on/off. Tens are shown as a long, while units are a short Non Fatal Error Codes: 2 Signals a restart. 5 Clock was reset to card value. Fatal Error Codes: 12 Unable to access/set RTC (long and 2 shorts) 13 Error accesing card/file (long and 3 shorts) 14 Error in file (long and 4 shorts) */ // This flashes the LED to the number of the ErrorCode if (ErrorCode >= 10) { showString(PSTR("Fatal Error : Code ")); Serial.println(ErrorCode,DEC); do { digitalWrite(ledPin1, HIGH); //display the long pulse to represent the 10 delay(1000); digitalWrite(ledPin1, LOW); for (int x=10; x <= (ErrorCode); x++) { digitalWrite(ledPin1, HIGH); //flash the short pulses to represent the units delay(300); digitalWrite(ledPin1, LOW); delay(500); } delay(2000); } while (ErrorCode >10); //Errorcode 10 or above, which stops it leaving. } } void ClockSet() { Clock.setClockMode(false); // set to 24h Clock.setYear(RTCsetYear); Clock.setMonth(RTCsetMonth); Clock.setDate(RTCsetDay); for (int z=0; z < 6; z++) //cycle thru DaysOfWeek array to find a match { if (String(DaysOfWeek[z])== RTCsetDOW) { Clock.setDoW(z +1); //DaysOfWeek array is zero based so add 1, to get mon=1 } } Clock.setHour(RTCsetHour); //setRTCtime 2359 Clock.setMinute(RTCsetMin); Clock.setSecond(00); return; } void ClockRead() { DoW = Clock.getDoW(); RTCDateCalc = ((Clock.getYear()) *10000UL) + ((Clock.getMonth(Century))*100) + (Clock.getDate()); CurrentTime = ((Clock.getHour(h12, PM)) *100) + (Clock.getMinute()); return; }
Looking at some of the code I can already see small increments to help save memory.
ie the Channel Codes have a common 13998 at the front, so I only needed to save the last three digits as a byte, rather than an unsigned long, and simply add it before transmitting.
Video
This will be an interesting exercise.
The outlets can't be placed too close to each other as they interfere, so the placement for a video to cpature both might need some thinking.
*** video to come ****
I do have some photos showing a single light placed in the Hobby area which is near the front door.
Yes my plug looks rather battered ...
The result of just this light on from outside is :-
So careful placement of the light could give anyone the impression that someone was home.
Feel free to ask questions ... after you download the zip file ... and I'll do my best to answer them.
Mark
Top Comments