Smart Glasses
This project is a compact wearable computer, in the form of glasses. It will have a few simple functions such as displaying time, date, or documents, and voice commands using text recognition. It will utilize a Raspberry Pi 0 W for the “brains” of the glasses, since the model has built-in bluetooth and wifi capabilities. It will use a reflection from a .96 inch OLED screen to display information in front of the wearer’s eyes. The Pi will control the other components and run all the required code, including the OLED screen, a discreet earpiece, and software function.
Engineer | School | Area of Interest | Grade |
---|---|---|---|
Jamie L | Archbishop Mitty | Programming, Mechanical/Electrical Engineering | Sophomore |
Final Milestone
I programmed some basic functions into my glasses at my third milestone. These include a simple boot screen, time function with a clock diagram, and image/file display. Since I usually do not program in Python and therefore had to get introduced to a completely new language, it took me a little to learn the fundamental keywords and their respective syntaxes. Additionally, I had to use many different libraries and modules. I also set up SSH and VNC on my Raspberry Pi so that I could access its screen and terminal on the monitor of my laptop without having to use an external monitor and keyboard/mouse. Howver, the Wifi settings at the school seem to be made so that it blocks the signals, so unfortunately it did not work.
Second Milestone
By the end of the second milestone, I had finished all hardware design and assembly, and enabled the headless setup on my Raspberry Pi. With Onshape, I made the componenets that would attatch the Raspberry Pi, OLED screen, and reflector to an arm that would extend out of the glasses. For the arm, I had to go through three iterations due to faulty printing as well as some design issues, such as durability and arm length. I then assembled the printed parts and adjusted the angle of the reflector so that the user could properly see the image. My next goal would be to program the glasses for its functions.
First Milestone
For my first milestone, I set up a desktop environment on my Raspberry Pi, and soldered all of my componenets and ensured that they work properly. I had a lot of trouble with the initial transparent screen that I was using for the display, and I eventually had to switch to an alternative design, which used a smaller screen and its reflection to show the user information. I also had to transition from a SPI connection to I2C. In my future milestones, I will CAD and 3D-print a casing for the Pi to rest in next to the glasses, then get started with the code. I have only basic skills on CAD and programming, so those would be my next main challenges.
Starter Project
Links: Product page, Instructions
I chose the 006 Useless Box as my starter project since it involved multiple aspects of engineering; it required soldering, motor control, and physical assembly. A useless box is, as demonstrated above, a device that turns itself off when activated. When the lever on the box is flipped, the servo with an arm attatched is powered, coming up to the top of the box and flipping the lever so that the servo turns the other way instead. When it goes back to its original position inside the box, it hits a switch that turns itself off.
Schematics
This is a Raspberry Pi 3B, while my Pi was a Zero W. They, however, do share the same pinouts. This wiring is the one I used for my screen.
Code
from bs4 import BeautifulSoup as soup
from urllib.request import urlopen
import os
from luma.core.interface.serial import i2c
from luma.core.render import canvas
from luma.oled.device import ssd1306
import time
import datetime
import wolframalpha
# import speech_recognition as sr
# import pyaudio
import wikipedia
# WOLFRAM
app_id = ''
# Put your app id here (You can sign up for one at the Wolfram Alpha website.)
client = wolframalpha.Client(app_id)
res = client.query('What is the temperature in ______')
# Put any place here.
answer = next(res.results).text
str1 = answer
str2 = str1.split('(', 1)[0]
bad_chars = [';', '|', '(', ')', '+', '=', '1']
num = ["05", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55", "0"]
def dateTime():
cdt = datetime.datetime.now()
min1 = str(cdt.minute)
hour = str(cdt.hour)
with canvas(device) as draw:
draw.text((0, 0), hour, fill = "blue")
draw.text((11, 0),":", fill = "blue")
draw.text((15, 0), min1, fill = "blue")
draw.text((0, 0), "___________", fill = "yellow")
draw.text((33, 0), str2, fill = "white")
draw.text((0, 115), "...", fill = "white")
def listen():
print('listening...')
time.sleep(5)
dateTime()
global val
val = input()
#os.system('arecord -d 4 -f cd -t wav -D bluealsa:DEV=00:00:00:00:00:00,PROFILE=sco test.wav') #Replace the MAC address with that of your hedset
def say(statement):
statement1 = statement.replace(" ", "_")
os.system('espeak ' + str(statement1) + ' -ven+f3 -k5 -s130 --stdout | aplay -D bluealsa:DEV=00:00:00:00:00:00,PROFILE=sco') #Change the MAC address here as well
def query(query):
client = wolframalpha.Client(app_id)
res = client.query(query)
answer = next(res.results).text
answer1 = answer.partition('\n')[0]
print(answer1)
def start_up():
hour1 = int(datetime.datetime.now().hour)
if hour1 >= 0 and hour1 < 12:
print('Good morning.')
#say('good morning')
elif hour1 >= 12 and hour1 < 20:
print('Good afternoon.')
#say('good afternoon')
else:
print('Good evening.')
#say('good evening')
print('How may I help you?')
# say('how may i help you)
serial = i2c(port=1, address=0x3C)
# Put in the address of your display instead of 0x3C, it may be 0x3C.
device = ssd1306(serial, rotate=0)
text = ("What would you like to say? ")
text1 = ('\n'.join([text[i:i+11] for i in range(0, len(text), 11)]))
cdt = datetime.datetime.now()
start_up()
def utilitys():
cdt = datetime.datetime.now()
min1 = str(cdt.minute)
hour = str(cdt.hour)
with canvas(device) as draw:
draw.text((0, 0), hour, fill = "blue")
draw.text((11, 0),":", fill = "blue")
draw.text((15, 0), min1, fill = "blue")
draw.text((0, 0), "___________", fill = "yellow")
draw.text((33, 0), str2, fill = "white")
if min1 in num:
client = wolframalpha.Client(app_id)
res = client.query('What is the temperature in San Fransisco')
answer = next(res.results).text
str1 = answer
str3 = str1.split('(', 1)[0]
draw.text((33, 0), str3, fill = "white")
def util(func1):
cdt = datetime.datetime.now()
min1 = str(cdt.minute)
hour = str(cdt.hour)
with canvas(device) as draw:
draw.text((0, 0), hour, fill = "blue")
draw.text((11, 0),":", fill = "blue")
draw.text((15, 0), min1, fill = "blue")
draw.text((0, 0), "___________", fill = "yellow")
#draw.text((0, 9), date, fill = "white")
draw.text((33, 0), str2, fill = "white")
draw.text((0, 64), func1, fill = "white")
while True:
utilitys()
listen()
try:
if len(val) >= 2:
if 'news' in val:
news_url="https://news.google.com/news/rss"
Client=urlopen(news_url)
xml_page=Client.read()
Client.close()
soup_page=soup(xml_page,"xml")
news_list=soup_page.findAll("item")
i = 0
util('news...')
for news in news_list:
print(news.title.text + "\n")
print(news.link.text)
i += 1
time.sleep(1)
if i == 3:
break
del val
util("news...")
time.sleep(3)
if 'exit program' in val:
os.system('pkill -f edited.py')
del val
if 'time' in val:
cdt1 = datetime.datetime.now()
h = cdt1.hour
m = cdt1.minute
print(str(h) + ':' + str(m))
say(str(h))
say(str(m))
del val
util("time...")
time.sleep(3)
if 'play my music' in val:
util("music...")
time.sleep(2)
# Replace the 00:00:00:00:00:00 with the MAC address of your headset
os.system('aplay -D bluealsa:DEV=00:00:00:00:00:00,PROFILE=sco /home/pi/Desktop/Imagine.wav')
del val
say('Would you like me to play the next song')
listen()
if 'Yes' in val:
os.system('aplay -D bluealsa:DEV=00:00:00:00:00:00,PROFILE=sco /home/pi/Desktop/BeautifulName.wav')
del val
say('would you like me to play the next song')
listen()
if 'Yes' in val:
os.system('aplay -D bluealsa:DEV=00:00:00:00:00:00,PROFILE=sco /home/pi/Desktop/Oceans.wav')
del val
if 'No' in val:
del val
continue
try:
client1 = wolframalpha.Client(app_id)
res1 = client1.query(val)
answer1 = next(res1.results).text
answer2 = answer1.partition('\n')[0]
for i in bad_chars:
answer2 = answer2.replace(i, '')
print(answer2)
except:
try:
print(wikipedia.summary(val, sentences = 1))
except:
print('')
del val
except:
print(' ')
Sadly, the bluealsa library (aplay, arecord) here does not work on Bullseye distribution. I was however succesful in bypassing such restrictions by using Bookworm from instructions here: https://robotzero.one/raspberry-pi-zero-voice-controller/
Bill of Materials
Part | Note | Price | Link |
---|---|---|---|
Raspberry Pi Zero W | Brains of the glasses | $15.00 | Link |
Bluetooth Earbuds | Audio information | $11.99 | Link |
.96in OLED Display | Visual information | $7.29 | Link |
Battery Bank | Power Source | $17.99 | Link |
Power Supply Cable | RasPi Power | $9.95 | Link |
HDMI Cable (Mini to Full) | RasPi to monitor | $8.79 | Link |
Micro SD Card | RasPi OS | $5.60 | Link |
Keyboard and Mouse | Navigate RasPi on desktop | $15.19 | Link |
Non-prescription Glasses | Base of project | $10.99 | Link |
Documents Referenced
Initial Idea, Screen Configuration, Speech Recognition Library