//Copyright (c) 2010, Jake Bordens //All rights reserved. //Redistribution and use in source and binary forms, with or without //modification, are permitted provided that the following conditions are //met: // //- Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. //- Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. //- Neither the name of the author nor the names of any contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE //LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //POSSIBILITY OF SUCH DAMAGE. #include "Wire.h" #include // Refrences //RTC Code: http://combustory.com/wiki/index.php/RTC1307_-_Real_Time_Clock //Ardumoto: http://mechomaniac.com/ArduinoMotorControlWithTheArdumotoShield //Breathing LED: http://www.adafruit.com/blog/2006/08/11/reverse-engineering-the-mac-breathing-led/ //MsTimer2: http://www.arduino.cc/playground/Main/MsTimer2 #define DS1307_I2C_ADDRESS 0x68 // This is the I2C address // Direction Constants #define CW 0 #define CCW 1 #define BOTH 2 // Watch winder parameters #define WinderATPD 650.0 #define WinderBTPD 800.0 #define WinderADir BOTH #define WinderBDir CW // Global Variables byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; int WinderA_Seconds, WinderB_Seconds; // Motor Control & LED Constants #define PwmPinMotorA 10 #define PwmPinMotorB 11 #define DirectionPinMotorA 12 #define DirectionPinMotorB 13 #define LedAPin 5 #define LedBPin 6 byte values[]={255,238,222,207,192,177,163,150,137,125,113,102,92,82,73,64,56,48,41,34,28,23,18,14,10,7,5,3,1,0,0,1,3,6,10,16,23,31,41,52,64,77,92,108,125,143,163,184,207,230}; // Convert normal decimal numbers to binary coded decimal byte decToBcd(byte val) { return ( (val/10*16) + (val%10) ); } // Convert binary coded decimal to normal decimal numbers byte bcdToDec(byte val) { return ( (val/16*10) + (val%16) ); } // Gets the date and time from the ds1307 and prints result void getDateDs1307() { // Reset the register pointer Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.send(0x00); Wire.endTransmission(); Wire.requestFrom(DS1307_I2C_ADDRESS, 7); // A few of these need masks because certain bits are control bits second = bcdToDec(Wire.receive() & 0x7f); minute = bcdToDec(Wire.receive()); hour = bcdToDec(Wire.receive() & 0x3f); // Need to change this if 12 hour am/pm dayOfWeek = bcdToDec(Wire.receive()); dayOfMonth = bcdToDec(Wire.receive()); month = bcdToDec(Wire.receive()); year = bcdToDec(Wire.receive()); } void printDateTime() { Serial.print(hour, DEC); Serial.print(":"); Serial.print(minute, DEC); Serial.print(":"); Serial.print(second, DEC); Serial.print(" "); Serial.print(month, DEC); Serial.print("/"); Serial.print(dayOfMonth, DEC); Serial.print("/"); Serial.print(year, DEC); } void setup() { //Start up wire and serial Wire.begin(); Serial.begin(57600); //Setup outputs pinMode(PwmPinMotorA, OUTPUT); pinMode(PwmPinMotorB, OUTPUT); pinMode(DirectionPinMotorA, OUTPUT); pinMode(DirectionPinMotorB, OUTPUT); pinMode(LedAPin, OUTPUT); pinMode(LedBPin, OUTPUT); //Motor A stop time WinderA_Seconds = WinderATPD * 0.4; //Motor B stop time WinderB_Seconds = WinderBTPD * 0.4; //Setup the Timer MsTimer2::set(125, timer); // 500ms period MsTimer2::start(); //Log startup getDateDs1307(); Serial.print("System initialized at "); printDateTime(); Serial.print("\n"); } void loop() { getDateDs1307(); long SecondsInHour = (minute * 60) + second; //MOTOR A Start Condition if (digitalRead(PwmPinMotorA) == 0 && SecondsInHour < WinderA_Seconds) { //Start MOTORA byte Adir; if (WinderADir == BOTH) { Adir = hour % 2; } else { Adir = WinderADir; } digitalWrite(DirectionPinMotorA, Adir); digitalWrite(PwmPinMotorA, HIGH); //Log to Serial Serial.print("Motor A Started. Direction "); Serial.print(Adir, DEC); Serial.print(" at time "); printDateTime(); Serial.print("\n"); } //MOTOR B Start Condition if (digitalRead(PwmPinMotorB) == 0 && SecondsInHour < WinderB_Seconds) { //Start MOTORB byte Bdir; if (WinderBDir == BOTH) { Bdir = hour % 2; } else { Bdir = WinderBDir; } digitalWrite(DirectionPinMotorB, Bdir); digitalWrite(PwmPinMotorB, HIGH); //Log to serial Serial.print("Motor B Started. Direction "); Serial.print(Bdir, DEC); Serial.print(" at time "); printDateTime(); Serial.print("\n"); } //MOTOR A Stop Condition if (digitalRead(PwmPinMotorA) == 1 && SecondsInHour > WinderA_Seconds) { //Stop MOTORA digitalWrite(PwmPinMotorA, LOW); //Log to Serial Serial.print("Motor A Stopped at "); printDateTime(); Serial.print("\n"); } //MOTOR B Stop Condition if (digitalRead(PwmPinMotorB) == 1 && SecondsInHour > WinderB_Seconds) { //Stop MOTORB digitalWrite(PwmPinMotorB, LOW); //Log To Serial Serial.print("Motor B Stopped at "); printDateTime(); Serial.print("\n"); } } void timer() { //Update the LED state based on the Motor state. //Get the current frame of the "Breathing LED" animation static byte frame=0; int value = ((values[frame] * 1) / 2) + 10; //If we're moving, turn on the LED at 147. Otherwise, animate. if (digitalRead(PwmPinMotorA)) { analogWrite(LedAPin, 147); } else { analogWrite(LedAPin, value); } //If we're moving, turn on the LED at 147. Otherwise, animate. if (digitalRead(PwmPinMotorB)) { analogWrite(LedBPin, 147); } else { analogWrite(LedBPin, value); } //Advance the frame for next time frame++; if (frame >= 50) frame = 0; }