Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
Infineon Team
Published © MIT

Luminous Awakening: PSoC6 MicroPython & NeoPixel Alarm Clock

Powered by MicroPython on PSoC6, this fancy alarm clock uses NeoPixel lights to help you start your day with full energy!

IntermediateFull instructions provided12 hours220

Things used in this project

Hardware components

CY8CPROTO-062-4343W
Infineon CY8CPROTO-062-4343W
×1
Adafruit NeoPixel Digital RGB LED Strip 144 LED, 1m White
Adafruit NeoPixel Digital RGB LED Strip 144 LED, 1m White
×1
LED Matrix
×1
Developer boards - rotation angle encoders
×2
Toggle Switch, Toggle
Toggle Switch, Toggle
×2

Software apps and online services

MicroPython
MicroPython
Thonny

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

3D box.stl

Sketchfab still processing.

3D Box.ipt

3D deckel.ipt

3Ddeckel.stl

Sketchfab still processing.

Schematics

Schematic

Code

Full code

MicroPython
import utime
import network
import ntptime
from machine import SPI, Pin, RTC, bitstream, PWM
from max7219 import Max7219
import time

# Initialize the MAX7219 display
spi = SPI(baudrate=4000000, polarity=1, phase=0, sck='P9_2', mosi='P9_0', miso='P9_1')
cs = Pin('P9_7', Pin.OUT)
pwm = PWM(Pin('P6_0'), freq=440, duty_u16=0)  # Begin with duty cycle = 0 (off)
display = Max7219(32, 8, spi, cs, False)

# Define pins for the rotary encoder for minutes
clk_pin_minutes = Pin('P8_6', Pin.IN, Pin.PULL_UP, value=1)  # CLK
dt_pin_minutes = Pin('P8_4', Pin.IN, Pin.PULL_UP, value=1)   # DT
sw_pin_minutes = Pin('P8_3', Pin.IN, Pin.PULL_UP, value=1)   # Optional SW (Switch)

# Define pins for the rotary encoder for hours
clk_pin_hours = Pin('P8_2', Pin.IN, Pin.PULL_UP, value=1)  # CLK
dt_pin_hours = Pin('P1_0', Pin.IN, Pin.PULL_UP, value=1)   # DT
sw_pin_hours = Pin('P6_3', Pin.IN, Pin.PULL_UP, value=1)   # Optional SW (Switch)

# Push button to enter setting mode
tilt_switch = Pin('P8_7', Pin.IN, Pin.PULL_UP)

# Variables to store the state
last_clk_state_minutes = clk_pin_minutes.value()
last_clk_state_hours = clk_pin_hours.value()
encoder_pos_minutes = 0
encoder_pos_hours = 0
minutes = 0
hours = 0

# Define the timing for the bitstream based on the LED's datasheet
timing = [500, 1125, 800, 750]

# Set up the data pin for the LEDs
DIN1 = Pin('P10_3', Pin.OUT, value=0)
ONOFF = Pin('P10_1', Pin.IN, Pin.PULL_DOWN)

def manualLightAll(buf):
    bitstream(DIN1, 0, timing, buf)

def create_color(red, green, blue):
    return bytearray([red, green, blue])

def animation_cycle(amount, cycles, delay):
    for cycle in range(cycles):  # Number of cycles of the animation
        for i in range(amount):  # Amount of LEDs
            buf = bytearray()
            # Create a color pattern that will cycle through each LED
            for j in range(amount):
                if j == i:
                    buf.extend(create_color(255, 0, 0))  # Red color
                elif j == (i + 1) % amount:
                    buf.extend(create_color(0, 255, 0))  # Green color
                elif j == (i + 2) % amount:
                    buf.extend(create_color(0, 0, 255))  # Blue color
                else:
                    buf.extend(create_color(0, 0, 0))   # Turn off the LED if not in use
            manualLightAll(buf)
            time.sleep(delay) 

def rainbow_cycle(amount, cycles, delay):
    rainbow_colors = [
        (255, 0, 0), (255, 127, 0), (255, 255, 0),
        (0, 255, 0), (0, 0, 255), (75, 0, 130), (143, 0, 255)
    ]
   
    for cycle in range(cycles):
        if ONOFF.value() == 1:
            buf = bytearray([0, 0, 0] * amount)
            pwm.duty_u16(0)
            manualLightAll(buf)
            break
        for i in range(amount):
            if ONOFF.value() == 1:
                buf = bytearray([0, 0, 0] * amount)
                pwm.duty_u16(0)
                manualLightAll(buf)
                break
            buf = bytearray()
            for j in range(amount):
                color = rainbow_colors[(i + j) % len(rainbow_colors)]
                buf.extend(create_color(*color))
            manualLightAll(buf)
            time.sleep(delay)
            pwm.duty_u16(16000)  # 50% Duty Cycle (65535 / 2)
            time.sleep(1)        # Wait one second
            pwm.duty_u16(0)      # 0% Duty Cycle (off)
            time.sleep(1)

# Clear the display
def clear_display():
    display.fill(0)
    display.show()

# Function to update the MAX7219 display
def update_display(hours, minutes):
    display.fill(0)
    time_str = f"{hours:02}{minutes:02}"
    for i, char in enumerate(time_str):
        display.text(char, (i * 8), 0, 1)
    display.show()

def clear_lights(amount):
    buf = bytearray([0, 0, 0] * amount)
    manualLightAll(buf)

def detect_rotation_minutes(arg):
    global last_clk_state_minutes, encoder_pos_minutes, minutes
    if tilt_switch.value() == 0:
        current_clk_state = clk_pin_minutes.value()
        current_dt_state = dt_pin_minutes.value()
        if current_clk_state != last_clk_state_minutes:
            if current_dt_state != current_clk_state:
                encoder_pos_minutes += 1
                minutes = (minutes + 1) % 60
                print("Minutes Clockwise")
            else:
                encoder_pos_minutes -= 1
                minutes = (minutes - 1) % 60
                print("Minutes Counterclockwise")
            last_clk_state_minutes = current_clk_state
            print("Minutes Encoder Position:", encoder_pos_minutes)
            update_display(hours, minutes)

def detect_rotation_hours(arg):
    global last_clk_state_hours, encoder_pos_hours, hours
    if tilt_switch.value() == 0:
        current_clk_state = clk_pin_hours.value()
        current_dt_state = dt_pin_hours.value()
        if current_clk_state != last_clk_state_hours:
            if current_dt_state != current_clk_state:
                encoder_pos_hours += 1
                hours = (hours + 1) % 24
                print("Hours Clockwise")
            else:
                encoder_pos_hours -= 1
                hours = (hours - 1) % 24
                print("Hours Counterclockwise")
            last_clk_state_hours = current_clk_state
            print("Hours Encoder Position:", encoder_pos_hours)
            update_display(hours, minutes)

# Wi-Fi connection
def connect_wifi(ssid, password):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if wlan.isconnected():
        print('Already connected to Wi-Fi. Network config:', wlan.ifconfig())
        return
    print('Connecting to Wi-Fi...')
    wlan.connect(ssid, password)
    for _ in range(30):
        if wlan.isconnected():
            break
        time.sleep(1)
    if wlan.isconnected():
        print('Connected to Wi-Fi. Network config:', wlan.ifconfig())
    else:
        print('Failed to connect to Wi-Fi')

# Synchronize time with NTP server
def sync_time():
    try:
        print('Synchronizing time with NTP server...')
        ntptime.host = 'de.pool.ntp.org'
        ntptime.settime(timezone=2)
        print('Time synchronized.')
    except Exception as e:
        print('Failed to synchronize time:', e)

# Display the current time
def display_time():
    rtc = RTC()
    while True:
        current_time = rtc.datetime()
        if tilt_switch.value() == 1:
            formatted_time = '{:02}{:02}'.format(current_time[4], current_time[5])
            print('Current time:', formatted_time)
            clear_display()
            display.text(formatted_time, 0, 0)
            display.show()
            time.sleep(1)
        else:
            # In setting mode, display the manually set hours and minutes
            update_display(hours, minutes)
            time.sleep(0.1)
        if current_time[4] == hours and current_time[5] == minutes:
            
            amount_of_leds = 100         # Number of LEDs in your strip
            animation_cycles = 3         # How many times the animation should run
            frame_delay = 0.1            # Delay between each color change in seconds
            rainbow_cycle(amount_of_leds, animation_cycles, frame_delay)
          

# Set up interrupts for the rotary encoders
clk_pin_minutes.irq(handler=detect_rotation_minutes, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING)
clk_pin_hours.irq(handler=detect_rotation_hours, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING)

# Main function
def main():
    ssid = '####'          # Replace with your Wi-Fi SSID
    password = '123456789' # Replace with your Wi-Fi password
    connect_wifi(ssid, password)
    sync_time()
    display_time()

if __name__ == '__main__':
    main()

MicroPython library for MAX7219

Credits

Infineon Team
102 projects • 165 followers
Contact

Comments

Please log in or sign up to comment.