Gudrun’s Final Project: The Moon Cycle Lamp

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

Link to the Google Doc

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

Discover more from Making Studio

Subscribe now to keep reading and get access to the full archive.

Continue reading