Adafruit_Learning_System_Gu.../CircuitPython_Talking_Adabot_Clock/code.py
2023-08-25 11:35:43 -04:00

174 lines
5.6 KiB
Python

# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import os
import time
import board
import audiocore
import audiobusio
import audiomixer
import adafruit_ds3231
from digitalio import DigitalInOut, Direction
import neopixel
import keypad
# enable external power pin
# provides power to the external components
external_power = DigitalInOut(board.EXTERNAL_POWER)
external_power.direction = Direction.OUTPUT
external_power.value = True
# setup external button pin as a keypad object
key = keypad.Keys((board.EXTERNAL_BUTTON,), value_when_pressed=False, pull=True)
# neopixel mouth setup
pixels = neopixel.NeoPixel(board.EXTERNAL_NEOPIXELS, 8, auto_write=True, brightness=0.2)
blue = (0, 0, 255)
off = (0, 0, 0)
pixels.fill(off)
# rtc module
i2c = board.I2C()
rtc = adafruit_ds3231.DS3231(i2c)
# pylint: disable-msg=using-constant-test
if False: # change to True if you want to set the time!
# year, mon, date, hour, min, sec, wday, yday, isdst
t = time.struct_time((2023, 8, 22, 16, 47, 00, 1, -1, -1))
# you must set year, mon, date, hour, min, sec and weekday
# yearday is not supported, isdst can be set but we don't do anything with it at this time
print("Setting time to:", t) # uncomment for debugging
rtc.datetime = t
print()
# pylint: enable-msg=using-constant-test
# sound arrays
bookend_sounds = []
hour_sounds = []
min_sounds = []
clock_queue = []
# bring in the audio files and put them into the different arrays
for filename in os.listdir('/clock_sounds'):
if filename.lower().endswith('.wav') and not filename.startswith('.'):
if filename.startswith('h'):
hour_sounds.append("/clock_sounds/"+filename)
elif filename.startswith('m'):
min_sounds.append("/clock_sounds/"+filename)
else:
bookend_sounds.append("/clock_sounds/"+filename)
# sort the arrays alphabetically
bookend_sounds.sort()
hour_sounds.sort()
min_sounds.sort()
print(hour_sounds)
print(min_sounds)
print(bookend_sounds)
# i2s amp setup with mixer
audio = audiobusio.I2SOut(board.I2S_BIT_CLOCK, board.I2S_WORD_SELECT, board.I2S_DATA)
mixer = audiomixer.Mixer(voice_count=1, sample_rate=22050, channel_count=1,
bits_per_sample=16, samples_signed=True)
audio.play(mixer)
mixer.voice[0].level = 0.5
# function for queueing wave files
def open_audio(wavs, num):
n = wavs[num]
f = open(n, "rb")
w = audiocore.WaveFile(f)
clock_queue.append(w)
return w
# queue boot up sound to play before going into the loop
boot_sound = open_audio(bookend_sounds, 2)
# function for gathering clock audio files
def prep_clock(hour_num, minute_num):
# queues "the time is.."
open_audio(bookend_sounds, 1)
# convert 24 hour time from RTC to 12 hour
if hour_num > 12:
hour_num = hour_num - 12
# set PM
ampm_num = 3
# otherwise its the morning
else:
# set AM
ampm_num = 0
# queueing hour, single digit waves have a 0 before the number
if hour_num <= 9:
print(hour_num)
h = hour_sounds.index(f'/clock_sounds/h0{hour_num}.wav')
else:
print(hour_num)
h = hour_sounds.index(f'/clock_sounds/h{hour_num}.wav')
# open wave file for the hour
open_audio(hour_sounds, h)
# if the minute is divisible by 10 (10, 20, 30, etc)
if minute_num % 10 == 0:
# check for on the hour (1:00, 2:00, etc)
if minute_num == 0:
m = min_sounds.index(f'/clock_sounds/m{minute_num}0.wav')
else:
m = min_sounds.index(f'/clock_sounds/m{minute_num}.wav')
print(minute_num)
# individual wave files exist for 1-19
elif minute_num <= 19:
print(minute_num)
# if it's a single digit number, bring in the "oh" wave file
if minute_num <= 9:
mm = min_sounds.index('/clock_sounds/m0x.wav')
open_audio(min_sounds, mm)
m = min_sounds.index(f'/clock_sounds/m{minute_num}.wav')
# otherwise, for minutes 21-59 that are not divisible by 10
else:
# we need to seperate the minutes digits
digits = list(map(int, str(minute_num)))
#print(digits)
# get the tens spot (30, 40, etc)
mm = min_sounds.index(f'/clock_sounds/m{digits[0]}x.wav')
# add the wav to the array
open_audio(min_sounds, mm)
# get the ones spot (1, 2, etc)
m = min_sounds.index(f'/clock_sounds/m{digits[1]}.wav')
# combined it will say ex: "30...5"
# add the wav to the array
open_audio(min_sounds, m)
# finish with am or pm
open_audio(bookend_sounds, ampm_num)
# initial RTC read
t = rtc.datetime
print(t)
# say the time on boot
pixels.fill(blue)
prep_clock(t.tm_hour, t.tm_min)
for i in range(len(clock_queue)):
mixer.voice[0].play(clock_queue[i], loop=False)
while mixer.playing:
pass
# clear the audio file queue
clock_queue.clear()
pixels.fill(off)
while True:
# listen for button input
event = key.events.get()
if event:
# if the button is pressed
if event.pressed:
# read from RTC module
t = rtc.datetime
# turn on neopixels
pixels.fill(blue)
# gather the audio files based on RTC reading
prep_clock(t.tm_hour, t.tm_min)
# play through each wave one by one
for i in range(len(clock_queue)):
mixer.voice[0].play(clock_queue[i], loop=False)
while mixer.playing:
pass
# afterwards clear out the queue
clock_queue.clear()
# turn off neopixels
pixels.fill(off)