first innit
This commit is contained in:
parent
2e4531c745
commit
4b2a838e6d
BIN
CAD/PCB_Adapter.stl
Normal file
BIN
CAD/PCB_Adapter.stl
Normal file
Binary file not shown.
BIN
CAD/motor_Adapter.stl
Normal file
BIN
CAD/motor_Adapter.stl
Normal file
Binary file not shown.
283
Firmware/orreryDriver.ino
Normal file
283
Firmware/orreryDriver.ino
Normal file
@ -0,0 +1,283 @@
|
||||
// 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!!");
|
||||
|
||||
}
|
||||
24
README.md
24
README.md
@ -1,2 +1,26 @@
|
||||
# OrreryDriver
|
||||

|
||||
[](https://ohwr.org/cern_ohl_s_v2.pdf)
|
||||
[](https://www.gnu.org/licenses/gpl-3.0.en.html#license-text)
|
||||
[](https://creativecommons.org/licenses/by-sa/4.0/)
|
||||
|
||||
|
||||
This repository contains all the files and documentation for the LEGO Orrery Driver Mod!
|
||||
- [Visit the DIY guide](https://gorkem.cc/projects/LegoOrreryMod) for details.
|
||||
|
||||
|
||||
File structure:
|
||||
+ `Firmware` contains the code and necessary drivers.
|
||||
+ `CAD` contains print ready .stl files.
|
||||
+ `PCB` contains gerber files.
|
||||
|
||||
Components list:
|
||||
- ESP32-C3 Super mini
|
||||
- DS3231 mini RTC Module
|
||||
- 10K Panel Mount Pot with a center detent
|
||||
- TMC 2208 Silent Stepper Driver Module
|
||||
- 2.54 PCB mount DC Jack
|
||||
- JST-EH 1x04 P2.50mm Horizontal Connector
|
||||
- JST-EH 1x06 P2.50mm Horizontal Connector
|
||||
- B3F-3152 Button
|
||||
- Male header pins
|
||||
|
||||
Loading…
Reference in New Issue
Block a user