In today's fast-paced world, having a reliable alarm clock is essential. While many people rely on their smartphones, creating a custom alarm clock can be a rewarding project. This project aims to build an alarm clock using a PSoC6 board and MicroPython. The clock connects to WiFi to retrieve the current time, displays it on a dot matrix, and features a simple interface for setting the alarm. When the alarm goes off, NeoPixel lights flash, and a buzzer sounds, ensuring you wake up on time.
What you need for the Projectx1 PSoC6 Board: The brain of the project, running the MicroPython code.
x1 Dot Matrix Display: For displaying the current time and alarm settings.
x1 Toggle Switch: To switch between Time display mode\ Alarm setting mode.
x2 Spin Buttons: For setting the alarm hours and minutes.
x1 NeoPixel LED Strip: Provides a visual alert when the alarm goes off.
x1 Buzzer: Provides an audible alert when the alarm goes off.
Here is a full cabling diagram to help you connect everything correctly!
Neopixel Lights
See our last Protip here: https://www.hackster.io/Infineon_Team/controlling-neopixels-with-micropython-1ca0d6
MAX7219 Display Initialization
from machine import SPI, Pin
from max7219 import Max7219
# 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)
display = Max7219(32, 8, spi, cs, False)
The MAX7219 display is set up using SPI communication. The SPI pins and chip select pin (cs) are initialized to communicate with the display module.(Library down bellow)
PWM for Buzzer
from machine import PWM, Pin
# Initialize PWM for buzzer
pwm = PWM(Pin('P6_0'), freq=440, duty_u16=0) # Begin with duty cycle = 0 (off)
A PWM (Pulse Width Modulation) signal is used to control a buzzer. The buzzer is connected to pin P6_0
, and it starts off with a duty cycle of 0 (off).
Rotary Encoders for Time Setting
# Define pins for the rotary encoders
clk_pin_minutes = Pin('P8_6', Pin.IN, Pin.PULL_UP)
dt_pin_minutes = Pin('P8_4', Pin.IN, Pin.PULL_UP)
sw_pin_minutes = Pin('P8_3', Pin.IN, Pin.PULL_UP)
clk_pin_hours = Pin('P8_2', Pin.IN, Pin.PULL_UP)
dt_pin_hours = Pin('P1_0', Pin.IN, Pin.PULL_UP)
sw_pin_hours = Pin('P6_3', Pin.IN, Pin.PULL_UP)
# Push button to enter setting mode
tilt_switch = Pin('P8_7', Pin.IN, Pin.PULL_UP)
Rotary encoders are used to adjust the hours and minutes for the alarm. A tilt switch is used to toggle between time display and setting modes.
Utility FunctionsUpdating the 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()
This function updates the MAX7219 display with the current hours and minutes. It clears the display and then writes the new time string.
Clearing the Display
def clear_display():
display.fill(0)
display.show()
This function clears the display by filling it with zeros and then showing the cleared display.
Rotary Encoder HandlersMinutes Encoder Handler
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)
This interrupt service routine handles the rotation of the minutes encoder. It detects changes in the encoder's state and updates the minutes accordingly. If the encoder is rotated clockwise, the minutes are incremented; if counterclockwise, they are decremented. The display is then updated with the new minutes.
Hours Encoder Handle
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)
This interrupt service routine handles the rotation of the hours encoder. Similar to the minutes handler, it updates the hours based on the encoder's rotation and updates the display.
Wi-Fi and Time SynchronizationConnecting to Wi-Fi
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')
This function connects the device to a Wi-Fi network using the provided SSID and password. It attempts to connect for up to 30 seconds and prints the network configuration if successful.
Synchronizing Time with NTP Server
def sync_time():
try:
print('Synchronizing time with NTP server...')
ntptime.host = 'de.pool.ntp.org'
ntptime.settime()
print('Time synchronized.')
except Exception as e:
print('Failed to synchronize time:', e)
This function synchronizes the system time with an NTP server. It sets the NTP server host and attempts to update the time.
Main FunctionMain Function
def main():
ssid = 'your-ssid'
password = 'your-password'
connect_wifi(ssid, password)
sync_time()
display_time()
The main()
function connects the device to Wi-Fi, synchronizes the time with an NTP server, and starts displaying the current time. This function is the entry point of the program.
By focusing on these key parts, you can understand how the alarm clock is initialized, how it handles user input through the rotary encoders, how it connects to Wi-Fi and synchronizes the time, and how it displays the current time on the MAX7219 display.
At the end once your code is ready all you need to do is 3D-print this box and we are done!
OutcomeSwitching from time display to alarm setting mode.
Alarm setting --> Time display --> Alarm goes on! (with Buzzer but sadly you can't hear it on the GIF )
Comments
Please log in or sign up to comment.