Jesse Friedman
Created March 14, 2017 © GPL3+

Pi-in-a-Box

Make your Raspberry Pi calculate and read out the digits of π in real time!

BeginnerFull instructions provided15 minutes54
Pi-in-a-Box

Things used in this project

Hardware components

Raspberry Pi 1 Model B+
Raspberry Pi 1 Model B+
Any Pi with a 3.5mm audio jack works.
×1
Toggle switch
Any toggle switch works as long as it's SPDT or DPDT (or 3PDT, or 4PDT, or πPDT... you get the idea.)
×1
Project enclosure
As long as it's big enough to fit your Pi and the switch above it, it should work fine. Plastic is fast to drill for those about to catch a flight to Iceland, but whatever floats your boat (err, airplane.) Bonus points for using an actual pie.
×1

Story

Read more

Code

main.py

Python
Main program file - listens to the switch and tells pi.py to start/stop the playback of digits. You'll need the RPi.GPIO and simpleaudio packages installed, and you'll probably need to run the script as root. simpleaudio is Python 3-only, so this only works on 3.
import atexit
import time
import RPi.GPIO as GPIO

from pi import Pi

SWITCH_ON_PIN = 16  # on throw of the switch
SWITCH_OFF_PIN = 20 # off throw of the switch

GPIO.setmode(GPIO.BCM)
GPIO.setup(SWITCH_ON_PIN, GPIO.IN)
GPIO.setup(SWITCH_OFF_PIN, GPIO.IN)
atexit.register(GPIO.cleanup)

pi = Pi()

def callback(channel):
    if channel == SWITCH_ON_PIN and pi.running == False:
        print('Starting Pi...')
        pi.start()
    elif channel == SWITCH_OFF_PIN and pi.running == True:
        print('Stopping Pi...')
        pi.stop()

if GPIO.input(SWITCH_ON_PIN) is GPIO.HIGH:
    # switch is starting in on position
    # script is starting with switch on, so we act as if it was just switched on
    callback(SWITCH_ON_PIN)

GPIO.add_event_detect(SWITCH_ON_PIN, GPIO.RISING, callback=callback, bouncetime=200)
GPIO.add_event_detect(SWITCH_OFF_PIN, GPIO.RISING, callback=callback, bouncetime=200)

print('Listening for switch...')

while True:
    time.sleep(1)

pi.py

Python
Module that actually calculates the digits of π and plays the appropriate audio files. You'll need the simpleaudio package installed.
import _thread
import time
import simpleaudio as sa

class Pi():
    def __init__(self):
        self.audio = {
            name: sa.WaveObject.from_wave_file('audio/{}.wav'.format(name))
            for name in range(10)
        }
        self.audio['point'] = sa.WaveObject.from_wave_file('audio/point.wav')
        self.running = False
    
    def pi_generator(self):
        # Adapted from https://gist.github.com/deeplook/4947835
        k, a, b, a1, b1 = 2, 4, 1, 12, 4
        while True:
            p, q, k = k * k, 2 * k + 1, k + 1
            a, b, a1, b1 = a1, b1, p * a + q * a1, p * b + q * b1
            d, d1 = a / b, a1 / b1
            while d == d1:
                yield int(d)
                a, a1 = 10 * (a % b), 10 * (a1 % b1)
                d, d1 = a / b, a1 / b1
    
    def start(self):
        _thread.start_new_thread(self._start, ())
    
    def _start(self):
        self.pi = self.pi_generator()
        next(self.pi)
        self.running = True
        
        print('3.')
        self.audio[3].play().wait_done()
        self.audio['point'].play().wait_done()
        while self.running is True:
            n = next(self.pi)
            print(n)
            play_obj = self.audio[n].play()
            play_obj.wait_done()
            play_obj.stop()
            del play_obj
    
    def stop(self):
        self.running = False
        pass

if __name__ == '__main__':
    pi = Pi()
    pi.start()

Audio files

Plain text
Text-to-speech audio of the digits 0-9 and the word "point", generated with Amazon Polly. Should be flat in a folder named "audio" that is sibling to main.py and pi.py.
No preview (download only).

Credits

Jesse Friedman

Jesse Friedman

6 projects • 3 followers

Comments