Introduction: 1970s Raspberry Pi Amazon AlexaPhone
This is a 1970s-style trimphone that I've converted to house a Raspberry Pi running Amazon's Alexa voice search service.
To use it you just lift the handset, speak your query, hang up and Alexa's response is delivered via a built-in speaker. It has a colour-changing LED to show what it's up to and plays an authentic trimphone sound to indicate when Alexa is ready to receive your instructions.
Check out the AlexaPhone Video to see it in action!
Step 1: Background and Research
It was exciting to read a few weeks ago that Amazon had released some new code enabling Raspberry Pi tinkerers to connect their projects to the Alexa voice service, and especially to see it covered in the mainstream news a few days later.
I experimented with voice search a while back with my Google Voice Search-O-Matic project, but being able to do something similar with a Pi opened up a whole range of new possibilities. I had a project in mind straightaway, to convert a now-obsolete piece of tech to work with this new service. I began by looking through the Amazon Alexa documentation on GitHub, and my first reaction was that it seemed like an awful lot of complicated hoops to jump through!
The first stage is to register for an Amazon Developer account, then set up a device profile on the Amazon website - this process provides you with the security codes and ID numbers that are passed from your project to the Alexa service. I found it easiest to set this up on my laptop and drop all the codes into a self-addressed email so that I could later retrieve them on the Pi via Claws Mail - the IDs are very long strings of characters and you definitely don't want to be typing them in manually!
At this point I looked a bit more closely into the Amazon instructions and found that my excitement may have been a bit premature - the official instructions do get Alexa workiing on the Pi, but they're based on having a network cable and monitor attached, activating the voice search by clicking a software button on screen. This wasn't really the code I was looking for - I was interested in building a standalone wireless enabled "headless" device, with no monitor and some kind of hardware switch to activate the voice search. After a bit of searching around I came across Sam Machin's excellent AlexaPi code on GitHub. This seemed a lot simpler than the published Amazon version, and was written in Python, so felt much more accessible. After a few evenings of fiddling and a dig through the Open & Closed Issues on GitHub I got it working on my Raspberry Pi 3, using a hardware push-button to get Alexa to "Listen Up!", an old ipod dock to play back the sound and a near-obsolete USB VOIP Phone (kindly donated by my Mother-in-law) to capture the sound.
Step 2: Getting the Pi Alexa-ready
I won't go into all the detail of the code here as it's well documented on GitHub and seems (from all the Watch notifications I get) to be in active development so may change often. With it working on my Pi 3 I had the idea to build the AlexaPhone in parallel with my original project, starting from scratch with my Pi 2 (unfortunately meaning no RetroPie temporarily). Having set it up once already I managed to complete the Pi & code configuration in a single evening - this is the process I followed:
First I set up a new device called AlexaPhone on the Amazon website, following the process in Section 3.4 of the ReadMe. The only change needed to support the AlexaPi code was to replace amazon's suggested https://localhost:3000 with https://localhost:5000 in the "Web Settings" section of the Security Profile. We'll come back to the web settings a bit later on. With the device set up I sent myself all the codes by email and turned my attention to the Pi.
I started by downloading & writing a fresh installation of Raspbian to an 8gb SD card - you could also use NOOBS, this worked for me on the Pi 3. With a monitor & network cable attached I did the following after the first boot:
- Expand the filesystem (open a terminal session, type raspi-config, select option 1)
- Still in raspi-config set the Audio to force 3.5mm output instead of HDMI (Advanced Options - Audio)
- Still in raspi-config change the Hostname to AlexaPhone - if you have multiple Pis on the wireless network this makes it easier to tell them apart
- Still in the terminal type lsusb - listing the USB devices to make sure the USB phone was detected
- From the desktop set up the Microphone level to maximum (Preferences > Audio Device Settings)
- From the desktop set up the WiFi by clicking on the network icon in the taskbar
From here I rebooted the Pi and then switched back to the laptop temporarily to...
- Log into the WiFi router and set the Pi to have a "Reserved IP Address" - the MAC address of the Pi's WiFi adaptor should be obvious in your router's list of Attached Devices, especially if you changed the hostname.
- Make a note of the Pi's IP address, log back into the Amazon website and add two new lines to the Web Settings of the Security Profile, so that in Allowed Origins there's one line that says https://localhost:5000 and below it a new one that says https://YourPiIpAddress:5000. The same for Allowed Return URLs so there's https://localhost:5000/authresponse and https://YourPiIpAddress:5000/authresponse showing.
Now to set up the AlexaPi code! I followed the instructions from GitHub which were well-written, I'll just add my personal experiences:
- Make sure you're logged in as root (sudo su in terminal) before you do the Git Clone bit
- Make sure you're in the Root folder before you do the Git Clone bit (cd /root/ in terminal)
- After the Git Clone bit is done you'll need to edit the file setup.sh if want to use wi-fi - switch to the AlexaPi directory (cd AlexaPi) then manually edit (sudo nano setup.sh) the file - replacing ip=ifconfig eth0 with ip=ifconfig wlan0
- Now you can run setup.sh, which prompts you for all the long codes that were generated on the Amazon website while setting up the device profile. I found it easiest to copy & paste these from Claws Mail.
- For me the setup.sh script gave an error at the end, though it may well work fine for you - all I needed to do was manually edit the creds.py file in the AlexaPi folder, pasting in the security IDs again.
- From here I manually ran auth_web.py (sudo python auth_web.py), then opened a web browser window and typed https://localhost:5000 - this brought up an Amazon login page to complete the process
I'm not certain that all 100% of the processes above were necessary, but that was what worked for me. After a reboot the AlexaPi service started automatically when the Pi booted, making me jump when it gave its "Hello" greeting.
The main part of the code is appropriately called main.py, and this contains the instructions for capturing the audio query, uploading it to Alexa and retrieving/playing back the response, as well as defining the GPIO pins for the switch and indicator LEDs. The code is designed for a three-legged Tri Colour LED, which was perfect for me as I wanted to keep the phone exterior as uncluttered as possible. The only thing I amended for this project was the filename of the .mp3 file played on startup, replacing it with the name of the trimphone ringtone. With the code thankfully working perfectly I left it well alone, disconnected the monitor and network cable and moved on to the construction.
Step 3: Button and Microphone
When I was experimenting with the first Alexa build I was really impressed at the hardware support of the Pi - the old USB VOIP phone worked straightaway, as did an equally old webcam with built-in mic, I had fully expected to need to wrestle with extra code or buy a modern USB microphone so it was great to be able to re-use what I had lying around.
I was trying to decide whether to crack open the USB phone's case when I noticed it had 3.5mm sockets in the side, presumably to attach an external microphone and speaker. At this point I had a Eureka moment and wondered whether an old phone handset could be plugged in here - I'd done something similar once before, converting a rotary phone into a bluetooth headset, so was intrigued to try it! I butchered a 3.5mm audio cable, plugged it into the USB phone and experimented with test leads connecting it to the various cables inside the phone, having taped up the USB phone's internal microphone. It worked after trying a few different combinations, and I found that using the phone handset I could practically whisper my search query and it was recognised.
Next came the button - the AlexaPi code needs the hardware button to be continually pressed while speaking, which I found a little bit counter-intuitive in testing. I wanted to use the phone's receiver switch to trigger the code, so that lifting the handset would start Alexa listening and replacing it would tell her to go fetch the response. I was very glad at this point that I'd decided to use the reproduction trimphone rather than one of my other "original" rotary phones - inside the case a lovely modern ribbon cable was poking out directly from the receiver switch. By experimenting with jumper cables, breadboard and an LED I hit upon a combination of connections that closed the switch when the handset was lifted and opened it again when it was replaced. The mic and button had gone really well - now it was time to sort out the speaker.
Step 4: Pirate Content
When I was kicking around my Alexa ideas I knew that it would be important to have a small and decently loud battery powered speaker. I didn't want to have an extra power supply coming from the phone, just the power lead for the Pi.
I stumbled across a solution at the local Maplin, a KitSound Mini Buddy - this seemed ideal as it was small, had a micro-usb-rechargeable battery and was cheap at under £5. The packaging claimed it was surprisingly loud which I took with a pinch of salt, but honestly I was impressed at the volume. As we'd bought the "pirate" version my son asked if that would make Alexa talk like a pirate - I think that'd be a great development for the future!
The speaker worked well in testing with the Pi, so the next thing was to take it apart - no way was the whole pirate case going to fit inside the phone body. After removing four screws the case split open in two pieces (and his ears fell off), One side held the speaker, the other the circuit board and tiny pillow-like battery. If you want to do the same thing I'd say take it really slowly, the wires are super thin in there!
The speaker was securely stuck to the grille, so I scored carefully around the outside edge with a little screwdriver and craft knife to remove the glue, narrowly avoiding poking a hole through the speaker cone. The circuit board was a bit more tricky, it was held in by a screw and hot glue, which I removed a tiny bit at a time with a scalpel under a magnifying lamp.
Eventually the delicate circuit, battery and speaker were free of the case and ready to add to the phone (after testing to make sure they still worked). Initially I'd planned to have the speaker "always on" and constantly connected to the Pi for charging, but started to worry how this might interfere with the Pi's power and whether constant charging would make the weeny battery go pop. I decided to mount the circuit board in the phone case, cutting out a slot to make the charging port and switch accessible without dismantling the phone. I drilled a 25mm hole in the base of the case for the speaker and then hot-glued the board in place.
Step 5: Phone Box Challenge
With everything working while strewn across the bench the next step was to fit all of the components into the phone body - a bit daunting as the space was really tight and the mechanical receiver switch needed a lot of space to move freely up & down. As the speaker was already in place I was left with just the Pi, USB Phone and connecting cables to fit in. After inspecting the voip handset I was sure I couldn't crack it open without breaking it, so spent a good while trying different layouts.
It was tricky working around all the left-over plastic posts and clips in the base so to make things easier I took a Dremel cutting wheel to any protruding bits of plastic, leaving an almost flat surface to work with. The case is held closed by a single screw, so everything but its post could be removed. This made all the difference, so after double-checking the layout I drilled holes to fit the Pi's bolts and the cable ties that would hold everything in place.
Step 6: Final Touches
It was a satisfying moment to finally get the phone sitting there on its own, with all the components tucked away inside. One of the last jobs was to fit the colour-changing LED into the hole in the side of the body. In the trimphone's previous life as a bluetooth headset this hole had been filled by a 3.5mm audio socket, so it was a bit bigger than the 5mm LED. I didn't want to just hot-glue the LED in place, so I secured it with a rubber washer on either side of the case.
After that I downloaded a Raspberry Pi logo to cut out (poorly - how do you easily cut precise circles in paper?) for the dial insert, which finished it off nicely.
Step 7: Ready Alexa?
This is definitely one of my favourite ever projects, it has just the right combination of old and new tech that I love and (unlike normally) it's practical, useful and I like the final look of it. It's also been great fun testing it with the kids and hearing the kind of things they ask Alexa. I have a pretty good idea of what "she" will and won't be able to cope with, but they approach it with more open minds, (when is my Birthday?) and are surprised when she's stumped by something like "how do I build a Redstone clock". I love the way voice integration is developing and look forward to other services being made pi-friendly in the near future.
The AlexaPi code is also developing all the time, to include new features like reminders and music playback, so it's worth keeping an eye on GitHub for the latest releases.
Now I must get back to my "original" Alexa project! I was totally sidetracked by the idea of the AlexaPhone, but it's been great fun - I now slightly wish I'd bought the cool 70s CB Radio I saw at a car boot recently, that would work really well, with its microphone and push-to-talk button...