< week.12@martin.magal@fabacademy.2013

week 12: interface and application programming (Apr 10)


about the assignment

the idea is to use this assignment to (begin to) solve the programming part of my final project.
that is:

  • make my raspbery pi collect tweets from the net
  • transform them to speech
  • send the speech audio signal out
  • output a binary code that can potentially select one of 12 more speakers according to a "code" word in the tweet.

    that means i have to:

  • get a Raspberry Pi.
  • install its operating system, Raspbian "wheezy".
  • set up drivers etc. to connect to the internet with a WIFI dongle.
  • install and update python.
  • install the python GPIO libraries that will allow me to control the pins and program the binary codes.
  • install the FESTIVAL software, a linux Speech Synthesis System.
  • write or adapt existing python scripts to collect the tweets, parse them, send them to FESTIVAL, and direct the audio output (by means of the GIPO pins) to the corresponding loudspeaker according to specific words in the tweets.

    preliminary system setup

    there are many online tutorials for setting up the raspi (thats short for raspberry pi), the raspbian, the wifi, etc.
    the wifi dongle wasn't that simple to set up and took me many hours of "tinkering", i can write about it later.
    essentially, the RASPI is an ARM based computer with:

  • SD memory card
  • mini USB connector for 5v power supply
  • 2 usb ports, hdmi output, audio output, rca video connector, ethernet
  • can run different linux distros and also android
  • a connector with 26 GPIO (general purpose input output) programmable pins.
  • a price tag of $35!

    speech synthesis

    this was the easiest part. but before installing FESTIVAL it is best to update your system:

    $ sudo apt-get update
    $ sudo apt-get upgrade
    then you can install FESTIVAL:
    $ sudo apt-get install festival festival-freebsoft-utils
    to make it talk, you can give it commands from the linux command line, like this:
    $ echo "this fabacademy thing is finally getting to its end"| festival --tts
    or you can enter the FESTIVAL enviroment by writing:
    $ festival
    and then issuing a command as follws:
    > (SayText "this fabacademy thing is finally getting to its end")
    pay attention to upper and lower cases!

    The Centre for Speech Technology Research in the University of Edinburgh are the developers of this system, there's a lot of info in their page.
    you can see an example in whiskeytangohotel.com.
    and see what other speech synthesis solutions exist for Raspi's here: RPi Text to Speech (Speech Synthesis).

    GPIO control

    to control the GPIO pins from within PYTHON, you need to import the RPi.GPIO module, like this:

    import RPi.GPIO as GPIO
    now we can refer top it as just GPIO.
    There are two ways of numbering the IO pins on a Raspberry Pi within RPi.GPIO. The first is using the BOARD numbering system.
    This refers to the pin numbers on the P1 header of the Raspberry Pi board. The advantage of using this numbering system is that your hardware will always work,
    regardless of the board revision of the RPi. You will not need to rewire your connector or change your code.

    The second numbering system is the BCM numbers. This is a lower level way of working - it refers to the channel numbers on the Broadcom SOC.
    You have to always work with a diagram of which channel number goes to which pin on the RPi board. Your script could break between revisions of Raspberry Pi boards.
    To specify which you are using using (mandatory):
    GPIO.setmode(GPIO.BOARD)
    or
    GPIO.setmode(GPIO.BCM)
    to address 12 speakers i will need a 4 bit address, here i will use only 3 bits (can address up to 8 speakers).
    i will use pins no. 11, 13 and 15, and first will need to define if they are inputs or outputs like this:
    GPIO.setup(channel, GPIO.IN)
    GPIO.setup(channel, GPIO.OUT)
    where "channel" is the pin number according to the numbering system chosen, and "IN" or "OUT" defines them as inputs or outputs.

    To set the output state of a GPIO pin:
    GPIO.output(channel, state)
    State can be 0 / GPIO.LOW / False or 1 / GPIO.HIGH / True, for example:
    GPIO.output(13, GPIO.HIGH) GPIO.output(11, 1)
    sets pin 13 AND PIN 11 BOTH to state HIGH (or 1, or true).

    polling tweets

    to search for tweets you access the twitter API (Application Programming Interface) with the following URL adddress:

    http://search.twitter.com/search.json?q=searchterm
    where "searchterm" is the search term you are looking for.
    the results of the search are returned as data "human unreadable" JSON format.
    in order to access this URL from within PYTHON you will need the URLLIB module. the following example
    import urllib
    url = 'http://search.twitter.com/search.json?q=fablab'
    print urllib.urlopen(url).read()
    will print to the screen the results, as said, in JSON format.
    to make use of the resulting data, we will have to parse it using the JSON module.
    in the example:
    import json
    url = 'http://search.twitter.com/search.json?q=fablab'
    response = urllib.urlopen(url).read()
    data = json.loads(response)
    results = data['results']
    print results[0]['text']
    the printed resulted will be only the "original" tweets that matched the query.
    you can see more examples like the above here.

    the python script

    this a script that collects all tweets sent to handle (user) @italktothewalls, and looks inside them for a number between 1-7.
    if it finds such a tweet, it prints the tweet to the screen and also sets the GPIO pins to a binary number that will give the MUX/DEMUX an address to open the corresponding switch.

    # italktothewalls installation script
    # script adapted from: WhiskeyTangoHotel.com - APRIL 2013
    # Error traps entered due to json hitting web site that was down etc.
    # For next added to end of prog to blink LED to show program is running.
    # Import the urllib library to read data from webpages
    import urllib
    # Import the simplejson library to decode the data read from the webpage
    import json
    # Import the time library for delay and lapse time tracking
    import time
    CurrentTime = time.time()
    # Import the Raspberry Pi GPIO libraries
    import RPi.GPIO as GPIO
    # Set-up the GPIO pins
    # Clear the current set-up
    GPIO.cleanup()
    # Set up the GPIO library to use Raspberry Pi board pin numbers
    GPIO.setmode(GPIO.BOARD)
    # Set pin 11, 13, 15 on the GPIO header to be an output
    GPIO.setup(11,GPIO.OUT) #00X
    GPIO.setup(13,GPIO.OUT) #0X0
    GPIO.setup(15,GPIO.OUT) #X00
    GPIO.setup(7,GPIO.OUT) #Blinkie LED to let us know the prog is running
    # Start with all spkrs OFF
    GPIO.output(11,GPIO.LOW)
    GPIO.output(13,GPIO.LOW)
    GPIO.output(15,GPIO.LOW)
    Last_state = "OFF"
    Error_hit = 0
    print "speakers off. Waiting for Tweet...","\n"
    # Function to take Twitter handle (e.g. @Raspberry_Pi) as an argument and return the most recent tweet
    # Define the function name and show the arguments
    def Latest_Tweet_to_Twitter_Handle(twitter_handle):
    try:
    # Get the results of a search on Twitter for tweets containing the given handle
    Twitter_search_results = urllib.urlopen("http://search.twitter.com/search.json?q="+twitter_handle)
    # Decode the data that we got from the webpage to form a list of tweets
    result_list = json.loads(Twitter_search_results.read())
    # The function returns the first result in the list
    return result_list["results"][0]["text"]
    except:
    pass
    # Main body of the program - Get the latest tweet and check if it contains certain words
    # Loop to run forever
    #Twitter commands the WALL understands are:
    #1, 2, 3, 4, 5, 6, 7
    while(True):
    try:
    #Time since program start in seconds
    DeltaTime = int(time.time() - CurrentTime)
    # Function gets the latest tweet mentioning the handle given in next line
    Tweet=Latest_Tweet_to_Twitter_Handle("@italktothewalls")
    # START TEST(1): Check if tweet contains the word given in quotation marks
    if "1" in Tweet: # and Last_state != "1":
    Last_state = "1"
    # If it did contain the word then print out the tweet along with a message
    print DeltaTime,"seconds:",Tweet," - speaker 1","\n"
    # set DEMUX inputs
    GPIO.output(11,GPIO.HIGH)
    GPIO.output(13,GPIO.LOW)
    GPIO.output(15,GPIO.LOW)
    #---END TEST(1)---
    ...
    ...
    continues....
    the complete script can be found here.
    and i want to give credits to first place where i found out about the connection between the raspi
    and twitter, Hand of Pi, by whiskeytangohotel.com

    JULY 2013 UPDATE: well, it doesn't work anymore! )-:

    at the time of this weekly assignment the above script worked very nicely.
    but i was very sorry to find out that this method doesn't work no more.
    TWITTER changed their API from version 1.0 to version 1.1, and the old method of conducting searches has been DEPRECATED (that's the word for it), and twitter doesn't support it any more.
    for the final project i will have to learn the new ways of twitter, see the updated scripts on week 18.