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
|
# 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