線性
時鐘源程序:
/*
Linear Clock driver
Written by Sandy Noble (sandy.noble@gmail.com)
This version 8th Jan 2011
This 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
#include
// 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();
}
副程序2e#程序2:
/*
Linear Clock driver
Written by Sandy Noble (sandy.noble@gmail.com)
This version 8th Jan 2011
This 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
#include
#include
// 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 = 0;
int currentHours = 0;
int const millisPerSecond = 1000;
int const stepsPerClock = 592;
float const stepsPerMinute = stepsPerClock/60.0;
float const stepsPerHourMinute = stepsPerClock/720.0;
float const stepsPerHour = stepsPerClock/12.0;
boolean currentlyRunning = false;
Button hourSetButton = Button(9, PULLUP);
Button minuteSetButton = Button(10, PULLUP);
Button modeToggleButton = Button(2, PULLUP);
const int modeIndicatorPin = 13;
void setup()
{
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("LINEAR CLOCK!");
hourHand.setSpeed(motorRPM); // rpm
minuteHand.setSpeed(motorRPM); // rpm
pinMode(13, OUTPUT);
}
void loop()
{
// check if the clock is paused or is running
if (inRunMode())
{
// here we count the seconds and things
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();
}
}
}
else
{
// not in Run mode, so we aren't automatically counting time.
// instead we're anticipating getting some button pushes to increment the time.
if (hourSetTriggered())
{
if (currentHours == 11)
currentHours = 0;
else
currentHours ++;
}
else if (minuteSetTriggered())
{
if (currentMinutes == 59)
currentMinutes = 0;
else
currentMinutes ++;
}
}
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();
}
boolean inRunMode()
{
// observe the buttons
modeToggleButton.isPressed();
if (modeToggleButton.stateChanged())
{
if (modeToggleButton.wasPressed())
{
// a previously HIGH button has gone low (been released)
// so flip modes
if (currentlyRunning)
{
Serial.println("CLOCK PAUSED");
currentlyRunning = false;
}
else
{
Serial.println("CLOCK RUNNING");
currentlyRunning = true;
}
}
}
if (currentlyRunning)
digitalWrite(modeIndicatorPin, LOW);
else
digitalWrite(modeIndicatorPin, HIGH);
return currentlyRunning;
}
boolean hourSetTriggered()
{
hourSetButton.isPressed();
if (hourSetButton.stateChanged() && hourSetButton.wasPressed())
{
Serial.println("Hour set button.");
return true;
}
else
return false;
}
boolean minuteSetTriggered()
{
minuteSetButton.isPressed();
if (minuteSetButton.stateChanged() && minuteSetButton.wasPressed())
{
Serial.println("Minute set button.");
return true;
}
else
return false;
}