This was one of the most challenging projects I have done yet!



The Moon Phase Lamp Video
Link to My Instructables Project
Link to the Instructable Preview
The Idea
I wanted to make a moon cycle lamp that shows you the cycle/phase of the current moon.

How it works
A light is placed in the middle of the box and a dome spins around it casting a shadow on the moon. This allows you to see the current cycle of the motor.
The Process
The Box
I built a wooden box in the VFL, it was quite challenging because I wanted the box to be seamless and had to miter the edges to achieve that look.



3D Printing
I designed and 3d printed the domes, both the outer dome, which is the moon, and the inner dome that casts the shadow.




I had to design the inner dome a few times because of balance issues.
The Circuit
I have a stepper motor, a motor breakout board, an Arduino Nano, an LED light, and a 100-ohm resistor. I soldered the Arduino nano and the motor breakout board to the “solderable” breadboard and soldered wires to connect everything together.




The Code
I had a really hard time coding this.
I researched a lot about the moon phases and even tried to create a function that calculates the moon. In the end, I downloaded a library in Arduino called “Moonphase” by Cellie. Then I used an example from their GitHub.
Then I researched how to make a stepper motor move and created a function to make the motor move from The Arduino Website.
Currently, the motor moves, but the moon phase location is not working as I want.
#include <WiFi.h>
#include <moonPhase.h>
#include <Wire.h>
#include <RTClib.h>
const char * wifissid = "WiFi Name";
const char * wifipsk = "Password";
moonPhase moonPhase;
RTC_DS1307 RTC;
struct tm timeinfo = {0};
// Define motor pins
#define A_OUT_1 9
#define A_OUT_2 10
#define B_OUT_1 11
#define B_OUT_2 12
// Define the delay between steps in milliseconds
const int STEP_DELAY = 100; // Adjust for speed
int stepsMoved = 0;
// Define the step sequence for a bipolar stepper motor
const int stepSequence[4][4] = {
{HIGH, LOW, HIGH, LOW}, // Step 1
{LOW, HIGH, HIGH, LOW}, // Step 2
{LOW, HIGH, LOW, HIGH}, // Step 3
{HIGH, LOW, LOW, HIGH} // Step 4
};
void setup() {
pinMode(2, OUTPUT);
// put your setup code here, to run once:
Wire.begin();
// Set motor pins as outputs
pinMode(A_OUT_1, OUTPUT);
pinMode(A_OUT_2, OUTPUT);
pinMode(B_OUT_1, OUTPUT);
pinMode(B_OUT_2, OUTPUT);
//Moon Angle
//Serial.begin(115200);
//Serial.println();
//Serial.println();
//Serial.println( "moonPhase esp32-sntp example." );
//Serial.print( "Connecting to " );
//Serial.println( wifissid );
//WiFi.begin( wifissid, wifipsk );
//while ( !WiFi.isConnected() )
// delay(100);
//Serial.println();
//Serial.println( "Connected. Getting time..." );
//configTzTime( "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00", "0.pool.ntp.org" ); // Timezone: Amsterdam, Netherlands
//while ( !getLocalTime( &timeinfo, 0 ) )
// vTaskDelay( 10 / portTICK_PERIOD_MS );
}
void loop() {
//getLocalTime( &timeinfo );
//Serial.print( asctime( &timeinfo ) );
digitalWrite(2, HIGH);
stepsMoved = moveSteps(20);
moonData_t moon = moonPhase.getPhase();
Serial.print( "Moon phase angle: " );
Serial.print( moon.angle ); // angle is a integer between 0-360
Serial.print( " degrees. Moon surface lit: " );
Serial.printf( "%f%%\n", moon.percentLit * 100 ); // percentLit is a real between 0-1
Serial.println();
delay(30000);
}
// Function to move the motor a specific number of steps
int moveSteps(int steps) {
int stepCount = abs(steps); // Get the absolute number of steps
int direction = (steps > 0) ? 1 : -1; // Determine direction (1 = forward, -1 = backward)
int currentStep = 0; // Track current step in the sequence
for (int i = 0; i < stepCount; i++) {
// Calculate the next step index
currentStep = (currentStep + direction + 4) % 4;
// Set the motor coils according to the step sequence
digitalWrite(A_OUT_1, stepSequence[currentStep][0]);
digitalWrite(A_OUT_2, stepSequence[currentStep][1]);
digitalWrite(B_OUT_1, stepSequence[currentStep][2]);
digitalWrite(B_OUT_2, stepSequence[currentStep][3]);
// Delay to control the speed
delay(STEP_DELAY);
}
// Turn off all coils after motion
releaseMotor();
return stepCount; // Return the number of steps moved
}
// Function to release the motor (turn off all coils)
void releaseMotor() {
digitalWrite(A_OUT_1, LOW);
digitalWrite(A_OUT_2, LOW);
digitalWrite(B_OUT_1, LOW);
digitalWrite(B_OUT_2, LOW);
}
//Moving the Motor in phase with the real moon
// Function that changes position from % to step location f.e. 180° = 100 steps
// Function (angle) --> (position)
// For Loop that moves the motor
// position = 0;
// newPosition = 0;
// for ...
// if newPosition == position - 1
// move motor (1)
// position = newPosition
//
Link to the Google Doc draft tutorial
Future Constructions
There are many things that I need to fix and do differently in the future.
- I need to fix the moon angle code so it works properly
- Change the blue LED to a white LED light
- Switch out the current motor for a quieter one





















































































































