/* Garage Door Remote Controller pfodDevice for Arduino Parses commands of the form { cmd ... } see www.pfod.com.au for more details. (c)2012 Forward Computing and Control Pty. Ltd. This code may be freely used for both private and commerical use. Provide this copyright is maintained. */ // define LED to check main loop delay: int led = 13; // set pin for controlling reed relay const int relayPin = 7; unsigned long startTimeInMills = 0; // the time when we started the relay pulse bool pulseTimerRunning = false; // set to true when we have a timer running unsigned long pulseLength = 750; // 0.75sec keep all timing in unsigned long void setup() { parserSetup(); // initialize pfod Cmd parser setupRelay(); // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } Serial.println("Garage Door Remote Control (9600baud)"); pinMode(led, OUTPUT); // to check main loop timing } void loop() // run over and over { // Led must flash at >500Hz i.e. <1mS off and <1mS on if (digitalRead(led)) { digitalWrite(led, LOW); // turn the LED off by making the voltage LOW } else { digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) } byte cmd = 0; byte in = 0; if (Serial.available()) { in = Serial.read(); cmd = parse(in); if (cmd != 0) { Serial.print("Cmd:"); Serial.write(cmd); Serial.println(); if (cmd == ((byte)'o')) { startRelayPulse(); Serial.println("{}"); } else if (cmd == (byte)'.') { // send main menu Serial.println("{^Press to open/close garage door|||||o~Open/Close}"); } else { // this should never happen Serial.println("Unknown cmd"); Serial.println("{}"); } // so clear it cmd = 0; // have processed this cmd now // so clear it and wait for next one } // else keep looping } controlRelay(); // always call this each loop // to ensure we turn the relay off } void setupRelay() { // set the digital pin as output: // make pin low digitalWrite(relayPin, LOW); // then make it an output pinMode(relayPin, OUTPUT); } // this is called on receiving // a command to open/close // sets up time and turns relay on void startRelayPulse() { startTimeInMills = millis(); pulseTimerRunning = true; // make pin high digitalWrite(relayPin, HIGH); Serial.println("Start pulse"); } // this is called each loop // turns relay off once time // exceeds stopTime void controlRelay() { // else if (pulseTimerRunning && ((millis() - startTimeInMills) > pulseLength)) { pulseTimerRunning = false; // timer finished // make pin low digitalWrite(relayPin, LOW); Serial.println("End pulse"); } } byte cmdByte; byte parserByteCounter; byte parserState; static const byte pfodMaxMsgLen = 0xff; // == 255, if no closing } by now ignore msg static const byte pfodStartMsg = (byte)'{'; static const byte pfodEndMsg = (byte)'}'; static const byte pfodWaitingForStart = 0xff; static const byte pfodInMsg = 0; void parserSetup() { parserByteCounter = 0; cmdByte = 0; // not started yet parserState = pfodWaitingForStart; // switch to pfodInMsg when see { } //------------------------------------- //PROCESS_RECEIVED_CHAR // { char } // save first char after { // store in cmdByte // // before { parserState == pfodWaitingForStart // when { seen parserState == pfodInMsg // after { first char ( != } ) is stored in cmdByte // cmdByte returned when terminating } seen but // not if no } seen for 254 bytes after starting { then // ignore msg and start looking for { again // //------------------------------------- // return 0 if no cmd found yet // else return cmd when see } // or ignore if >254 bytes after { // // in is byte read from Serial port byte parse(byte in) { parserByteCounter++; if (parserState == pfodWaitingForStart) { if (in == pfodStartMsg) { // found { parserSetup(); // clean out last cmd parserState = pfodInMsg; } // else ignore this char as waiting for start { // always reset counter if waiting for { parserByteCounter = 1; return 0; } // else have seen { if ((parserByteCounter == pfodMaxMsgLen) && (in != pfodEndMsg)) { // ignore this msg and reset // should not happen as pfodApp should limit // msgs sent to pfodDevice to <=255 bytes parserSetup(); return 0; } // else is this the end of the msg if (in == pfodEndMsg) { byte pfodMsgCmd = cmdByte; // this will return 0 when parsing {} msg // set up to wait for next { parserSetup(); // return command byte found return pfodMsgCmd; // else normal byte } else if (cmdByte == 0) { // save first cmd byte (only the first) cmdByte = in; } return 0; }