first innit

This commit is contained in:
Görkem 2026-02-09 16:56:11 -08:00
parent 2e4531c745
commit 4b2a838e6d
4 changed files with 307 additions and 0 deletions

BIN
CAD/PCB_Adapter.stl Normal file

Binary file not shown.

BIN
CAD/motor_Adapter.stl Normal file

Binary file not shown.

283
Firmware/orreryDriver.ino Normal file
View 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!!");
}

View File

@ -1,2 +1,26 @@
# OrreryDriver
![Human made](https://img.shields.io/badge/human-coded-green?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0ibHVjaWRlIGx1Y2lkZS1wZXJzb24tc3RhbmRpbmctaWNvbiBsdWNpZGUtcGVyc29uLXN0YW5kaW5nIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjUiIHI9IjEiLz48cGF0aCBkPSJtOSAyMCAzLTYgMyA2Ii8+PHBhdGggZD0ibTYgOCA2IDIgNi0yIi8+PHBhdGggZD0iTTEyIDEwdjQiLz48L3N2Zz4=)
[![License: CERN-OHL-S](https://img.shields.io/badge/Hardware%20License-CERN--OHL--S%20v2-blueviolet)](https://ohwr.org/cern_ohl_s_v2.pdf)
[![License: GNU General Public License v3.0](https://img.shields.io/badge/Firmware%20License-GNU%20GPL--v3.0-yellow)](https://www.gnu.org/licenses/gpl-3.0.en.html#license-text)
[![License: CC BY-SA 4.0](https://img.shields.io/badge/Documentation%20License-CC_BY--SA_4.0-lightgrey)](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