线性时钟源程序:
/*
Linear Clock driver
Written by Sandy Noble (sandy.noble@gmail.com)
This version 8th Jan 2011This uses the AFMotor library from Adafruit, because I used an Adafruit
Motorshield, and I think Adafruit are the bomb. Make sure you use a version
of the libraries from after 7th Jan 2011, because there's a little fix in
them that is important to this code.This should be fairly simple self-explanatory code.
*/
#include <AFMotor.h>
#include <WString.h>// These set up the motors. The values here depend on how they've been wired up.
AF_Stepper minuteHand(20, 1); // minutes
int const minutesIncrement = BACKWARD;
int const minutesDecrement = FORWARD;AF_Stepper hourHand(20, 2); // hours
int const hoursIncrement = FORWARD;
int const hoursDecrement = BACKWARD;int const stepType = DOUBLE;
int const motorRPM = 150;int second=0, minute=0, hour=0; // declare TIme variables
// Minutes setup
int startMinutePos = 0;
// current minute posiTIon. This gets updated all the TIme.
float currentMinutePos = startMinutePos;
// the current posiTIon of the indicators. This only gets updated when the hands move
int displayMinutePos = startMinutePos;// Hours setup
int startHourPos = 0;
float currentHourPos = startHourPos;
int displayHourPos = startHourPos;// These are the actual time, in seconds minutes and hours.
// doTick() writes these values, and renderTime() reads them.
int currentSeconds = 0;
int currentMinutes = 50;
int currentHours = 11;int const millisPerSecond = 200;
int const stepsPerClock = 592;
float const stepsPerMinute = stepsPerClock/60.0;
float const stepsPerHourMinute = stepsPerClock/720.0;
float const stepsPerHour = stepsPerClock/12.0;void setup()
{Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("LINEAR CLOCK!");hourHand.setSpeed(motorRPM); // 10 rpm
minuteHand.setSpeed(motorRPM); // 10 rpm}
void loop()
{static unsigned long lastTick = 0; // set up a local variable to hold the last time we moved forward one second
// (static variables are initialized once and keep their values between function calls)// move forward one second every 1000 milliseconds
unsigned long time = millis();
unsigned long sinceLastTick = time - lastTick;if (sinceLastTick >=millisPerSecond)
{
unsigned int secondsMissed = sinceLastTick / millisPerSecond;lastTick = millis();
for (int i = 0; i < secondsMissed; i++)
{
doTick();
}
}
renderTime();
}void doTick()
{
currentSeconds++;
if (currentSeconds > 59)
{
currentSeconds = 0;
currentMinutes++;
if (currentMinutes > 59)
{
currentMinutes = 0;
currentHours++;
if (currentHours > 11)
{
currentHours = 0;
}
}
}
Serial.print(millis());
Serial.print(" - tick!");
Serial.print(currentHours);
Serial.print(":");
Serial.print(currentMinutes);
Serial.print(":");
Serial.println(currentSeconds);
}void renderTime()
{
setTime(currentHours, currentMinutes);
}void setTime(int hour, int minute)
{
setHour(hour, minute);
setMinute(minute);
}void setHour(int hour, int minute)
{
// work out the new position and set it globally eg time 4:25.
// first hours
// eg 0.2055 * 4 * 60 = 49.333
float justHours = stepsPerHourMinute * hour * 60;
// eg 0.2055 * 25 = 5.13888
float justMinutes = stepsPerHourMinute * minute;// stick em together: position is 54.472 (4:25)
currentHourPos = justHours + justMinutes;// round to integer
// eg 54
int newPos = currentHourPos;// save the previous actual position so we can check if the hands need moving
// eg 52
int lastPos = displayHourPos;// now see if the hand position needs to change
// eg 54 - 52 = 2
int stepsToChange = newPos - lastPos;
if (stepsToChange != 0)
{
Serial.print("sethour:");
Serial.println(hour);
// update the global variable
displayHourPos = newPos;
changeHours(stepsToChange);
}}
void changeHours(int steps)
{
Serial.print("Incrementing hours position:");
Serial.println(steps);// make it positive
int absSteps = abs(steps);if (steps < 0)
{
// if it's negative, then DECREMENT
if (absSteps >= 1)
{
// only step if it's a full step
hourHand.step(absSteps, hoursDecrement, stepType);
}
}
else if (steps > 0)
{
// if it's positive then INCREMENT
if (absSteps >= 1)
{
// only step if it's a full step
hourHand.step(absSteps, hoursIncrement, stepType);
}
}Serial.print("Actual current hour position:");
Serial.println(displayHourPos);hourHand.release();
}void setMinute(int minute)
{
// work out the new position and set it globally
// eg 2.467 * 25 = 61.675
currentMinutePos = stepsPerMinute * minute;// round to integer
// eg 61
int newPos = currentMinutePos;// save the previous actual position so we can check if the hands need moving
// eg 59
int lastPos = displayMinutePos;// now see if the hand position needs to change
// eg 61 - 59 = 2
int stepsToChange = newPos - lastPos;
if (stepsToChange != 0)
{
Serial.print("setmin:");
Serial.println(minute);
// update the global variable
displayMinutePos = newPos;
changeMinutes(stepsToChange);
}
}void changeMinutes(int steps)
{
Serial.print("Incrementing minutes position:");
Serial.println(steps);// make it positive
int absSteps = abs(steps);if (steps < 0)
{
// if it's negative, then DECREMENT
if (absSteps >= 1)
{
// only step if it's a full step
minuteHand.step(absSteps, minutesDecrement, stepType);
}
}
else if (steps > 0)
{
// if it's positive then INCREMENT
if (absSteps >= 1)
{
// only step if it's a full step
minuteHand.step(absSteps, minutesIncrement, stepType);
}
}Serial.print("Actual current minute position:");
Serial.println(displayMinutePos);minuteHand.release();
}