283 lines
6.4 KiB
C++
283 lines
6.4 KiB
C++
// defines pins
|
|
#define stepPin 3
|
|
#define dirPin 4
|
|
#define potPin 0
|
|
#define buttonPin 7
|
|
#define motorEnablePin 10
|
|
|
|
#include "RTClib.h"
|
|
#include <AccelStepper.h>
|
|
#include <TM1637.h>
|
|
#include <Preferences.h>
|
|
|
|
unsigned int oldVal;
|
|
|
|
// Define variables for timing
|
|
unsigned long lastUpdate = 0;
|
|
const int updateInterval = 100; // Update display every 100ms
|
|
|
|
const unsigned long rtcSyncInterval = 600000; // 172 seconds in milliseconds
|
|
unsigned long lastRtcSync = 0;
|
|
|
|
unsigned long lastDebugTime = 0;
|
|
const int debugInterval = 500; // Only check RTC/Print every 500ms
|
|
|
|
//motor values
|
|
uint32_t totalSecondsinYear = 31536000;
|
|
//uint32_t fullRotationMotorSteps = 194400;
|
|
uint32_t fullRotationMotorSteps = 183348;
|
|
|
|
bool isCalibrated = false;
|
|
bool homingComplete = false;
|
|
bool realTime = false;
|
|
|
|
int count=0;
|
|
|
|
long targetPos;
|
|
|
|
//inititate EEPROM with preferences library
|
|
Preferences preferences;
|
|
|
|
// Instantiation and pins configurations
|
|
// Pin 2 - > DIO
|
|
// Pin 1 - > CLK
|
|
TM1637 tm(1, 2);
|
|
TM1637 tm2(5, 6);
|
|
int potValue = 0;
|
|
|
|
RTC_DS3231 rtc;
|
|
|
|
AccelStepper stepper1(1, stepPin, dirPin);
|
|
|
|
//define state machine
|
|
enum {calibrationMode, manualMode, realTimeMode};
|
|
unsigned char machineState;
|
|
|
|
void setup() {
|
|
pinMode(buttonPin, INPUT_PULLDOWN);
|
|
pinMode(motorEnablePin,OUTPUT);
|
|
Serial.begin(115200);
|
|
//preferences.begin("persistent-mem", false);
|
|
//oldVal = preferences.getUInt("oldVal", 0);
|
|
tm.init();
|
|
tm2.init();
|
|
tm.setBrightnessPercent(5);
|
|
tm2.setBrightnessPercent(5);
|
|
rtc.begin();
|
|
// rtc.adjust(DateTime(2026, 4, 1, 12, 0, 0));
|
|
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
|
|
|
|
stepper1.setMaxSpeed(4000);
|
|
stepper1.setAcceleration(500);
|
|
stepper1.setSpeed(4000);
|
|
//enable motor
|
|
digitalWrite(motorEnablePin ,LOW);
|
|
}
|
|
void loop()
|
|
{
|
|
|
|
switch (machineState){
|
|
case calibrationMode:
|
|
calibrateOrrery();
|
|
break;
|
|
case realTimeMode:
|
|
if (digitalRead(buttonPin) == HIGH){
|
|
tm.display("real");
|
|
tm2.display("time");
|
|
realTime=true;
|
|
|
|
updateMotor();
|
|
Serial.println("Real time switch");
|
|
|
|
}
|
|
|
|
|
|
if (realTime && (millis() - lastRtcSync >= rtcSyncInterval)) {
|
|
lastRtcSync = millis();
|
|
updateMotor(); // Calculates new targetPos based on RTC
|
|
Serial.println("Periodic RTC Sync Triggered");
|
|
}
|
|
|
|
manualControl(isCalibrated);
|
|
break;
|
|
case manualMode:
|
|
break;
|
|
default:
|
|
Serial.println("Default Mode");
|
|
// first check if theres state in memorty
|
|
if(oldVal == 0){
|
|
machineState = calibrationMode;
|
|
}else{
|
|
stepper1.setCurrentPosition(oldVal);
|
|
isCalibrated = true;
|
|
realTime=true;
|
|
updateMotor();
|
|
machineState = realTimeMode;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
void calibrateOrrery(){
|
|
if (digitalRead(buttonPin) == HIGH && !homingComplete) {
|
|
tm.display("clbr");
|
|
tm2.display("set");
|
|
|
|
stepper1.setCurrentPosition(1500);
|
|
|
|
updateMotor();
|
|
homingComplete = true;
|
|
|
|
|
|
}
|
|
else if(!homingComplete) {
|
|
tm.display("clbr");
|
|
tm2.display("reqd");
|
|
manualControl(isCalibrated);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
if (stepper1.distanceToGo() == 0){
|
|
isCalibrated = true;
|
|
machineState = realTimeMode;
|
|
tm.display("done");
|
|
realTime = true;
|
|
Serial.println("DONE");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
long currentMotorPos(){
|
|
DateTime now = rtc.now();
|
|
DateTime newYear(2026, 1, 1, 0, 0, 0);
|
|
uint32_t nowUnixTime = now.unixtime();
|
|
uint32_t newYearUnixTime = newYear.unixtime();
|
|
uint32_t secondsSinceNewYear = nowUnixTime - newYearUnixTime;
|
|
|
|
uint32_t motorPosRT = (uint64_t) secondsSinceNewYear * fullRotationMotorSteps / totalSecondsinYear;
|
|
// preferences.putUInt("oldVal", motorPosRT);
|
|
return motorPosRT;
|
|
}
|
|
|
|
void manualControl(bool calibrated){
|
|
|
|
potValue = analogRead(potPin);
|
|
potValue = map(potValue, 0, 4095, 3000, -3000);
|
|
|
|
if(potValue > -900 && potValue<300){
|
|
}else{
|
|
stepper1.setSpeed(potValue);
|
|
stepper1.runSpeed();
|
|
realTime=false;
|
|
}
|
|
|
|
|
|
if (calibrated && (millis() - lastUpdate >= updateInterval)) {
|
|
lastUpdate = millis();
|
|
if (realTime) {
|
|
displayTime(rtc.now());
|
|
} else {
|
|
displayTime(simulatedTime(stepper1.currentPosition()));
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void displayTime(DateTime timeObject) {
|
|
char timeStr[10]; // Buffer to hold the formatted string
|
|
int h = timeObject.hour();
|
|
int m = timeObject.minute();
|
|
// Determine if we show the dot (colon)
|
|
bool showDot = (millis() / 1000) % 2;
|
|
bool screenUpdate = (millis() / 500) % 2;
|
|
if(realTime){
|
|
if (showDot) {
|
|
snprintf(timeStr, sizeof(timeStr), "%02d.%02d", h, m);
|
|
} else {
|
|
snprintf(timeStr, sizeof(timeStr), "%02d%02d", h, m);
|
|
}
|
|
|
|
|
|
if (screenUpdate) {
|
|
tm.display(String(timeStr));
|
|
tm2.display(formatDate(timeObject.month(), timeObject.day()));
|
|
}
|
|
|
|
} else {
|
|
tm.display((int)timeObject.year());
|
|
tm2.display(formatDate(timeObject.month(), timeObject.day()));
|
|
//tm.display(timeStr);
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
DateTime simulatedTime(long motorPosition) {
|
|
uint32_t secondsSince2026 = (uint32_t)((uint64_t)totalSecondsinYear * motorPosition / fullRotationMotorSteps);
|
|
|
|
return DateTime(DateTime(2026, 1, 1, 0, 0, 0).unixtime() + secondsSince2026);
|
|
}
|
|
|
|
String formatDate(int month, int day) {
|
|
|
|
String months[] = {"Ja", "Fe", "mr", "Al", "ma", "Jn","Jl", "Au", "Se", "Oc", "No", "De"};
|
|
|
|
String dayStr = (day < 10) ? "0" + String(day) : String(day);
|
|
|
|
String monthStr = months[month - 1];
|
|
|
|
return monthStr + dayStr;
|
|
}
|
|
|
|
int motorStep2seconds(int motorStep){
|
|
// return motorStep*1460.0/9.0;
|
|
return motorStep*172;
|
|
}
|
|
|
|
void updateMotor(){
|
|
targetPos = currentMotorPos();
|
|
stepper1.moveTo(targetPos);
|
|
|
|
Serial.print("Target updated to: ");
|
|
Serial.println(targetPos);
|
|
Serial.print("Current Pos: ");
|
|
Serial.print(stepper1.currentPosition());
|
|
Serial.print(" Distance to go: ");
|
|
Serial.println(stepper1.distanceToGo());
|
|
Serial.println("RUNING!");
|
|
stepper1.runToPosition();
|
|
Serial.print("Current Pos: ");
|
|
Serial.print(stepper1.currentPosition());
|
|
Serial.print(" Distance to go: ");
|
|
Serial.println(stepper1.distanceToGo());
|
|
Serial.println("DONE!!");
|
|
}
|
|
|
|
void updateMotorManual(){
|
|
manual
|
|
stepper1.moveTo(97200);
|
|
|
|
Serial.print("Target updated to: ");
|
|
Serial.println(targetPos);
|
|
Serial.print("Current Pos: ");
|
|
Serial.print(stepper1.currentPosition());
|
|
Serial.print(" Distance to go: ");
|
|
Serial.println(stepper1.distanceToGo());
|
|
Serial.println("RUNING!");
|
|
stepper1.runToPosition();
|
|
Serial.print("Current Pos: ");
|
|
Serial.print(stepper1.currentPosition());
|
|
Serial.print(" Distance to go: ");
|
|
Serial.println(stepper1.distanceToGo());
|
|
Serial.println("DONE!!");
|
|
|
|
} |