The Finished Product
The timer is currently undergoing final software adjustments and isscheduled for its debut on Monday April 26. Here it is in its final form. The digital clock is clearly labeled with the Most Significant Bit
and Least Significant Bit
, and the buttons for all features as well as the unlabeled "mystery button".
The thing in the bottom left corner is the small speaker, which does surprisingly well (much better in the case than just flopping around on a wire while prototyping). Next to the speaker is the power on/off toggle.Here is the code
- Battery operated using rechargeable AA batteries
- Set by default for 20 minute interval timing
- Buttons to add or remove one minute from the clock
- Pause/Resume timer button
- Spoken announcements at 5 minute intervals, one minute, and final ten second countdown
- Button to announce current number of minutes remaining
- Button to speak a random phrase for general amusement, some of which pertain to poker
- Visual display of minutes remaining in binary format using 5 LEDs
- Blink LEDs when paused
- At 50 seconds remaining, all LEDs light, and one by one turn off each 10 seconds
A Typical Monday Night Game
My buddy Mike hosts a weekly no limit Texas Hold 'Em tournament with 20 minute rounds. Blinds go up every 20 minutes, and there is a high hand jackpot awarded after the 4th round, when re-buys stop. So keeping track of the time is pretty critical, and knowing when you are in the last minute or so especially so.
To date we usually use someones iPhone timer. This can be problematic when that person busts out and wants to slink away early (thereby missing out on the post-game festivities at Ed's Kort Haus
). And you can't tell what time it is without asking the timekeeper. I've used a timer on my Nexus One as well, which some players enjoyed as it featured speech synthesized announcements of each 5 minute interval.
I've been looking for a fun Arduino project. I was going to build a lager temperature controller for my home brewery, but the loan of Dave's Johnson temp controller has removed the urgency from that project. For my birthday, Kim got me a copy of Practical Arduino: Cool Projects for Open Source Hardware, which features a sample project with speech synthesis based on the SpeakJet chip. I decided it was GO TIME for my first Arduino project, a talking poker timer.
Credit and Inspiration
Giving credit where it is due:
Prototyping and Debugging
As noted above this project was inspired by the speech synthesis project in the book Practical Arduino. I used the SpeakJet speech synthesis chip recommended in that sample project. The SpeakJet chip uses "allophones" which are elementary word sounds. For example, the word POKER can be said by stringing together the SpeakJet allophones PO,OW,KE, and AXRR. It also has some canned sound effects such as gunshots, R2D2-like squeaks, alarms, etc, and can vary the pitch and speed...so you can make it sing.
I found that SparkFun sells a pre-built Arduino shield (called the Voice Box Shield) with the SpeakJet, including a low powered audio amplifier circuit and speaker connections. It was only $15 more than the bare SpeakJet chip, so I figured it was worth it to avoid building up the amplifier myself and having it mount easily on the Arduino. Just a bare prototyping shield is at least $10. So $5 to get the amplifier and save myself some soldering was a good ROI.
I did find the Voice Box Shield has what sees to me to be a bit of an oversight, the lack of a connection to the SpeakJet's Buffer Half Full pin. Monitoring the state of the SpeakJet buffer is critical if you are throwing much at it. The buffer is 64 bytes, and if it is full and you keep throwing allophones at it, it throws data away. No biggie, I just wired up my own connection.
So to hook things up I needed to:
- Wire up the SpeakJet Buffer Half Full Pin (pin 15) to an Arduino pin, with a resistor inline
- Wire up 5 LEDs for the binary clock display, again with resistors
- Wire up 5 momentary push buttons (start/pause/resume, add a minute, subtract a minute, announce time remaining, utter a random phrase)
- Put a power toggle switch between the batteries and the Arduino
Pretty basic stuff as far as Arduino goes. This is only my fourth real custom electronics project though, and my soldering skills are still developing, so it seemed about right for my skill level.
What's up with the binary clock you may wonder. Sure I could have put a numeric LED or LCD display into this project, but that seems too easy and not quite high enough on the geek street cred scale. And most of our poker players are versed in binary. We do have a union boss and high school English teacher in the group...they can press the button to announce the time.
Code speaks for itself right? Here is the code
I got the allophone codes for Daisy Bell from the SpeakJet Yahoo! Group, which is a great resource for tinkering with this chip. Not a lot of Arduino traffic there though.
Hacking this up in C was a trip down memory lane giving me deja vu of 1990 and coding for OS/2. I had forgotten all about having to deal with pointers, null terminating strings, and the nuances of accessing the size of a given byte array when given an array of pointers to those arrays of byte arrays. That last one sent me running to Stack Overflow for answers to this question
I'm sure there is some clever way to do the binary clock LED updates in just 3 lines of code, but I was proud to employ the bitwise '&' operator one digit at a time.
I was concerned about keeping the time accurate even with events like the announcements taking varying amounts of time out of the loop. I started off using the Time and Alarm libraries, but bailed on them because they were losing time whenever the SpeakJet spoke. I switched to manually tracking milliseconds elapsed and remaining using millis().
One thing I vacillated on was whether to display the minutes remaining last announced, or the "true" minutes remaining. So for example, if there are 14 minutes 15 seconds on the timer currently, should the binary clock show 14 or 15? I decided to set the LEDs to show the minimum number of minutes remaining, which is consistent with what you would see on a timer that shows minutes and seconds, but with the seconds not displayed. Nobody really cares too much about the time until we are in the final minute, which is announced and then followed by LED indication of the final five 10 second intervals passing, and a final 10 second spoken countdown. And if all that is still too confusion for mere mortals, I made the time announcement button say "between x and y minutes remaining" to clearly communicate where we are in the countdown.
I learned a ton, some of it being stuff I really wish I learned earlier in the execution of the project.
I wish I learned earlier about the internal pull-up resistors on the Arduino pins and how they can be used with input switches to avoid the need to wire up an external resistor. The Arduino tutorials should be updated to expose this simple solution.
I wish I purchased a PanaVise earlier. I have a "Helping Hands" thingy with a magnifying glass and adjustable clips to hold parts, but it pales in comparison to the PanaVise for securely holding parts for soldering. Also since I love my magnifying visor, the magnifying glass on the Helping Hands was superfluous to my needs.
Stupid item: plumber's solder is no substitute for electrical solder. I had a devil of a time melting plumbing solder even with my soldering iron cranked up to 700 degrees.
I am still working on implementing a Fisher-Yates shuffle algorithm to randomize the sequence of playback for the random phrases. Until then they will always play in the same order.
I want to try implementing something to read the battery charge state and announce it so we know when to change the batteries.
I'm sure I will also be tweaking the speech codes to make them more intelligible, and adding many more "random" phrases. My intention is to fill up the remaining memory on the Arduino with phrases. I've used about 8k of the 30k available so far, so there is plenty of room for more.