Matthew Gutierrez
Published

ENGI 301 - Mechanical Jewelry Box

A cottage-core inspired jewelry box that uses a servo to motorize the main jewelry selection piece and adjustable lights for the box.

BeginnerWork in progress3 hours87
ENGI 301 - Mechanical Jewelry Box

Things used in this project

Hardware components

PocketBeagle
BeagleBoard.org PocketBeagle
×1
Resistor 1k ohm
Resistor 1k ohm
×4
DIYables Push Button with Cap
×4
Trimmer Potentiometer, w/ Knob
Trimmer Potentiometer, w/ Knob
×1
LED (generic)
LED (generic)
×3
SG90 Micro-servo motor
SG90 Micro-servo motor
×1
Elegoo 28BYJ-48 ULN2003 5V Stepper Motor + ULN2003 Driver Board
Component not used in current design, however is what the Cad Models are designed for and is what is planned to be used in future implementation
×1
Fairy Lights
Component not used in current design, however it is what is planned to be used in future implementation
×1

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Did not get to this step of the implementation, however the files that need to be 3D printed are included in the documentation later in this report.

Story

Read more

Custom parts and enclosures

Mushroom Head

3d print of the head of the mushroom

Mushroom Base

3d print of the base of the mushroom

Schematics

Pocket Beagle Pin Out

This is a diagram of the pocket beagles pin out

Code

Jewelry Box Code

Python
Main script that controls the jewelry box
"""
--------------------------------------------------------------------------
Jewelry Box
--------------------------------------------------------------------------
License:   
Copyright 2024 Matthew Gutierrez

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this 
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation 
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors 
may be used to endorse or promote products derived from this software without 
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------

Use the following hardware components to make a mechanical jewelry box:  
  - Button
  - Red LED
  - Green LED
  - Blue LED
  - Potentiometer (analog input)
  - Servo

Requirements:
  - Hardware:
    - Servo
        - Servo should stay in the last position it was placed in. Servo has 64 steps in complete rotation
    -Potentiometer
        - Potentiomter should read output and transform it into an frequency that will be defined as "Max_Brightness" which will control the brightness of the LEDs,
          and work as a dimmer for the system
    - Button
      - Each button will have its own function
        - "L_Button" will turn the servo by 1 step in the counter-clockwise direction
        - "R_Button" will turn the servo by 1 step in the clockwise direction
        - "Rand_Button" will turn the servo by a random number of steps between 1 and 16 in either the clockwise or counterclockwise direction
        - "Mode_Button" will change the way the LEDs are being lit up, by incrementing a counter on the variable "Mode_Count" which will determine what mode the
           the lights are in
    
Uses:
  - As a lovely gift to my mom

"""
import time
import button as BUTTON
import potentiometer as POT
import servo as SERVO
import led as LED
import random

# ------------------------------------------------------------------------
# Constants
# ------------------------------------------------------------------------
SERVO_PIN = "P1_36"
POT_PIN = "P1_19"
GREEN_LED_PIN = "P2_02"
RED_LED_PIN = "P2_04"
BLUE_LED_PIN = "P2_06"
L_BUTTON_PIN = "P2_25"
R_BUTTON_PIN = "P2_27"
RAND_BUTTON_PIN = "P2_29"
MODE_BUTTON_PIN = "P2_31"
MAX_BRIGHTNESS = 100  # Placeholder value

# ------------------------------------------------------------------------
# Global variables
# ------------------------------------------------------------------------
Mode_Count = 0

# ------------------------------------------------------------------------
# Functions / Classes
# ------------------------------------------------------------------------
class JewelryBox():
    """JewelryBox class"""
    
    def __init__(self):
        """Initialize components and setup"""
        self.servo = SERVO.Servo(SERVO_PIN)
        self.potentiometer = POT.Potentiometer(POT_PIN)
        self.green_led = LED.LED(GREEN_LED_PIN)
        self.red_led = LED.LED(RED_LED_PIN)
        self.blue_led = LED.LED(BLUE_LED_PIN)
        self.l_button = BUTTON.Button(L_BUTTON_PIN)
        self.r_button = BUTTON.Button(R_BUTTON_PIN)
        self.rand_button = BUTTON.Button(RAND_BUTTON_PIN)
        self.mode_button = BUTTON.Button(MODE_BUTTON_PIN)
        self.flashing_interval = 1.0  # Default flashing interval in seconds
        self.fade_interval = 0.1  # Default fade interval in seconds
        self.chase_interval = 0.1  # Default chase interval in seconds
        self.led_states = [False, False, False]  # Represent LED states

    def setup(self):
        """Setup hardware components"""
        self.l_button.set_pressed_callback(self.turn_servo_counter_clockwise)
        self.r_button.set_pressed_callback(self.turn_servo_clockwise)
        self.rand_button.set_pressed_callback(self.turn_servo_random)
        self.mode_button.set_pressed_callback(self.change_led_mode)

    def loop(self):
        """Main loop to control the jewelry box"""
        while True:
            self.update_led_brightness()
            self.update_led_mode()
            time.sleep(0.1)  # Adjust sleep time as needed

    def cleanup(self):
        """Cleanup hardware components"""
        self.servo.cleanup()
        self.potentiometer.cleanup()
        self.green_led.cleanup()
        self.red_led.cleanup()
        self.blue_led.cleanup()
        self.l_button.cleanup()
        self.r_button.cleanup()
        self.rand_button.cleanup()
        self.mode_button.cleanup()

    def turn_servo_counter_clockwise(self):
        """Turn servo by 1 step counter-clockwise"""
        self.servo.turn(-1)

    def turn_servo_clockwise(self):
        """Turn servo by 1 step clockwise"""
        self.servo.turn(1)

    def turn_servo_random(self):
        """Turn servo by a random number of steps in either direction"""
        steps = random.randint(1, 16)
        direction = random.choice([-1, 1])
        self.servo.turn(steps * direction)

    def change_led_mode(self):
        """Change LED mode by incrementing Mode_Count"""
        global Mode_Count
        Mode_Count = (Mode_Count + 1) % 4

    def update_led_brightness(self):
        """Update LED brightness based on potentiometer value"""
        pot_value = self.potentiometer.get_value()
        brightness = pot_value * MAX_BRIGHTNESS / 4095
        self.red_led.set_brightness(brightness)
        self.green_led.set_brightness(brightness)
        self.blue_led.set_brightness(brightness)

    def update_led_mode(self):
        """Update LED mode based on Mode_Count"""
        if Mode_Count == 0:
            # Static mode
            brightness = MAX_BRIGHTNESS
            self.red_led.set_brightness(brightness)
            self.green_led.set_brightness(brightness)
            self.blue_led.set_brightness(brightness)
        elif Mode_Count == 1:
            # Flashing mode
            self.toggle_leds_with_interval()
        elif Mode_Count == 2:
            # Fade mode
            self.fade_leds()
        elif Mode_Count == 3:
            # Chase mode
            self.chase_leds()

    def toggle_leds_with_interval(self):
        """Toggle LEDs on and off with adjustable interval"""
        brightness = MAX_BRIGHTNESS
        while Mode_Count == 1:
            self.red_led.set_brightness(brightness)
            self.green_led.set_brightness(brightness)
            self.blue_led.set_brightness(brightness)
            time.sleep(self.flashing_interval)
            self.red_led.off()
            self.green_led.off()
            self.blue_led.off()
            time.sleep(self.flashing_interval)

    def fade_leds(self):
        """Fade LEDs from Max_Brightness to 0 and back in a loop"""
        brightness = MAX_BRIGHTNESS
        direction = -1  # Start with fading out
        while Mode_Count == 2:
            # Update brightness based on direction
            brightness += direction
            # Change direction when reaching the limits
            if brightness <= 0:
                brightness = 0
                direction = 1
            elif brightness >= MAX_BRIGHTNESS:
                brightness = MAX_BRIGHTNESS
                direction = -1
            # Set brightness to LEDs
            self.red_led.set_brightness(brightness)
            self.green_led.set_brightness(brightness)
            self.blue_led.set_brightness(brightness)
            # Sleep for fade interval
            time.sleep(self.fade_interval)

    def chase_leds(self):
        """Chase LEDs in sequential order"""
        num_leds = len(self.led_states)
        while Mode_Count == 3:
            for i in range(num_leds):
                # Turn on current LED
                self.led_states[i] = True
                # Set LED states
                self.set_led_states()
                # Sleep for chase interval
                time.sleep(self.chase_interval)
                # Turn off current LED
                self.led_states[i] = False
                # Set LED states
                self.set_led_states()

    def set_led_states(self):
        """Set LED states based on self.led_states"""
        for i, state in enumerate(self.led_states):
            if state:
                self.turn_on_led(i)
            else:
                self.turn_off_led(i)

    def turn_on_led(self, index):
        """Turn on the LED at the specified index"""
        if index == 0:
            self.red_led.on()
        elif index == 1:
            self.green_led.on()
        elif index == 2:
            self.blue_led.on()

    def turn_off_led(self, index):
        """Turn off the LED at the specified index"""
        if index == 0:
            self.red_led.off()
        elif index == 1:
            self.green_led.off()
        elif index == 2:
            self.blue_led.off()

# ------------------------------------------------------------------------
# Main script
# ------------------------------------------------------------------------
if __name__ == '__main__':
    print("Jewelry Box Start")
    jewelry_box = JewelryBox()
    try:
        jewelry_box.setup()
        jewelry_box.loop()
    except KeyboardInterrupt:
        jewelry_box.cleanup()
    print("Jewelry Box Complete")

Hackster.io

For more information about my code as well as my set up and run scripts, please visit my repository

Credits

Matthew Gutierrez
1 project • 0 followers

Comments