Introduction: Voiceberry Pi!

This instructable is the final one in the series, leading up to the Voiceberry Pi!

I work from home as a computer consultant.  I spend a good deal of time on conference calls, and needed a second line to handle these calls.  I explored my options, and decided to go with Magic Jack.  You know the adds.  Phone service for just $19.99 a year. That's $1.70 a month. WIth Magic Jack.

The quality is good, and the product works. But, to cut down on costs, they don't let you dial toll numbers to conference calls (if they know about it).  Many of my conference calls only have toll numbers, so I needed a way to around this limitation.

Enter Google Voice.  At first I thought about using my USB headset to make calls using the VoIP features of Google Voice, but the quality wasn't that great, and people complained. But I found out that you can make Google Voice call your phone, then connect you with another phone, anywhere in the US, for free.

So, I started doing that.  If I needed to call a toll conference call, I'd tell Google Voice to call it, but connect it to my Magic Jack number.  My phone would ring, I'd pick up, and then I'd hear ringing on the other end.  It was as though i called it directly, but Google Voice did it for me. Perfect.

Except it is a pain in the butt to log into Google Voice every time I need to make a call.  Enter Voiceberry Pi.

Voiceberry Pi, when complete (it's in an alpha stage now, but worthy of an instructable all the same), will be a small appliance that sits on your desk, and is much like a phone.  It will allow you to dial a phone number, like you would on a phone, and then it will tell Google to connect that call using your phone.  Google Voice will call you, and you are connected to your line.

Other features for the future, and some gotchas will be detailed in the final step.

Step 1: Hook Up the Display Part 1: the Shift Register

The first step is to hook up a display so you can see what you're dialing and what you're doing.  Before that can be done, because of a limited number of pins, I like to hook up a shift register to drive the display.

You can follow the steps in my other instructable on hooking up the shift register, then come back here.

Step 2: Hook Up the Display Part 2: Adding the Display

The next step is to actually hook up the display.  My instructable on running an HD44780 based display covers this in detail.  Hop on over and follow that setup, then come back for the next step.

Step 3: Adding the Keypad

You can't dial without a keypad.  This instructable, also mine, details how to do just that.  Although the GPIO pins used in the Voiceberry Pi are different, the end result is the same.

Step 4: Pulling It All Togehter With Code

Attached is my code to make this run.  It's built using pygooglevoice, a pretty powerful interface between Python and Google Voice.  Login credentials can be stored directly in the pygooglevoice settings, which they are in my case.  That's why you won't see them in the code.

I would love to show a video of it working, but it's going to have my actual phone numbers, and I don't want them out on the web.  I trust the actual instructables folks, but given how targeted we are for SPAM, I don't want to give them out here.  Nothing personal.

How it works:

The code first logs in using credentials stored in the pygooglevoice library.  While that is happening, "Logging In" is displayed on the screen.  Next, it waits for user input, displaying "Waiting".  If you press the "*" key on the keypad, the display changes to "Dialing", and you are in dialing mode.  Dial the phone number to call, and if you make a mistake, hit the "*" key again to clear the number.  When you've dialed the number, press the "#" key to place the call, and the display updates to "Calling". When the call has been placed, the display updates to "Call Placed", waits a short time, and then goes back to waiting.

Your call gets placed using Google Voice, to the phone number you've configured in your account. Errors in logging in or connecting are displayed as well, if necessary.

Step 5: Next Steps, New Features, and Thoughts

To start with, the code runs at 100% CPU usage, which is unacceptable.  I need to find a way to cut down on that, and still have the thing function.  Not sure how I'm going to do that, to be honest.

Next, of course, would be to put this into some sort of permanent home, and not just have wires lying on my desk.

The code currently has no functionality to cancel the call. Once you start dialing, you need to finish the process.  That needs to be added to the code.

I'd like to use a bigger keypad, more like this one.  The added buttons would make it easier to use--Press A to start dialing, and B to place the call. That kind of thing.  Also, it's a straight 4x4 matrix, and comes with the 8 header pins already in place.  A much better solution, but it cost more than the two keypads I got combined.

I'd like to explore other features of Google Voice.  Perhaps hookup a speaker to the audio out of the Raspberry Pi, and play back voicemail. Or check for incoming SMS messages (outgoing would be tough on this small keypad, but then again, it wouldn't be impossible).

There's a ton of features that can be implemented.  The fun has just begun!

Step 6: Updates: a Living Instructable (11/3/12)

I am so happy that this instructable won me a prize, I've desided to revisit it, and update it with changes I've made.  Two quick changes this morning

  1. I added a sleep statement at the beginning of the loop.  The logic is "If state=waiting, then wait 1 second."  This means I have to hold down the * key to start dialing, but it's a small price to pay to go from 100% CPU utilization to 25% utilization.  Code:

    if (state==waiting):
      time.sleep(1)
  2. I added the ability to stop dialing.  Previously, while waiting, you'd press * to start dialing, then if you made a mistake, you'd press * again to start dialing all over again.  I've added some code that checks to see if there is a current number in the buffer.  If there is, it will reset dialing, but if not, it will go back to waiting.  Code:

    ...
    elif (state==dialing):
      if (keyPressed=="*"):
        if (string1==""):
          state=waiting
          showStrings("","Waiting")
        else:
          string1=""
          showStrings("","Dialing")
So that's two things that I was able to "knock off my list" of "what's next" from the last step.  There might be more coming!