From 4e965c7d9a66d6a72b24c7b319c10d8006f2026e Mon Sep 17 00:00:00 2001 From: Mark Powers Date: Tue, 19 Jul 2022 21:12:41 -0500 Subject: Initial Commit --- content/blog/rotary_phone_running_linux.md | 276 +++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 content/blog/rotary_phone_running_linux.md (limited to 'content/blog/rotary_phone_running_linux.md') diff --git a/content/blog/rotary_phone_running_linux.md b/content/blog/rotary_phone_running_linux.md new file mode 100644 index 0000000..bf74f86 --- /dev/null +++ b/content/blog/rotary_phone_running_linux.md @@ -0,0 +1,276 @@ +--- +title: "Rotary phone running Linux" +date: 2022-04-14T21:52:01-05:00 +--- +# How to connect a vintage rotary phone to raspberry pi (and use it as a wedding guestbook) + +I'm a software engineer, and am not very familiar with the inner workings of +most electronics. I had an idea for using an old rotary phone as a Linux +peripheral device. In this blog post, I'll show you what I learned, and how to +connect an old rotary phone to a Raspberry Pi. + + + +## Requirements + +To do this project, you won't need any electronics knowledge. It is basically as +simple as unscrewing a few connections, plugging together wires, and taping them +down. I assume you have some knowledge of running Linux programs on the +Raspberry Pi, and in particular a bit of Python experience. + +The materials needed for this project are also simple. + +* First, you will need a Raspberry Pi. You could use a Raspberry Pi zero for + this, but my understanding is that connecting to GPIO on the zero is + trickier. On a normal-sized pi, you can instead use jumper cables. You will + also need an SD card and power supply. +* You will need some wires to connect the componants to your pi. I got some + jumper cables ([these](https://www.adafruit.com/product/4944) and + [these](https://www.adafruit.com/product/1956)). You could use any wires + really. I used the ones mentioned above, and taped them as needed to form a + connection. If you are comfortable soldering, that is fine too. +* To use audio, you will need a [USB audio + adapter](https://www.adafruit.com/product/1475). I have an older pi, which + has a 3.5 mm output jack on the board. If you didn't need audio in, you + could get away with just using that. Any USB audio adapter that works on the + pi should be fine. +* Now, you will need something to plug into the 3.5 mm jacks on the adapter. I + used [these](https://www.adafruit.com/product/4181), which makes it very + easy to connect the phone wires to a 3.5 mm jack. Alternatively, you could + just use an old 3.5 mm cable, and splice it onto the phone's wires. +* You will need a rotary phone. I got mine from an antique store, and I think it + is from the 70s or 80s. Make sure the phone you choose is a rotary phone if + you want to use the dial. There are some phones that appear to have dials, + but the dial does not spin, and the numbers are actually buttons instead. + You probably could get these to work if you tinkered around yourself, but I + have no experience with them. [JWZ + wrote](https://www.jwz.org/blog/2016/01/my-payphone-runs-linux-now/) this + post about using a more modern payphone. If you search ebay for "rotary + phone" you will find lots that fit the bill. +* You will need some screwdrivers to take apart the phone. My phone just uses + regular screws. + +In total, the pi and phone are by far the most expensive part of this project. +Most phones I've seen have been around $40, or more for fancy colors. So +overall, you could probably complete this project on a budget of $45-$100 +depending on your selection of phone, and if you have an old Raspberry Pi lying around. + +An old-fashioned rotary phone is a very simple device. The hook (the button to +know if the phone is picked up) is just a basic button. The rotary dial may seem +complicated, but ultimately, it is just a pair of basic buttons. The speaker and +microphone are just analog audio componants. I'll first describe how each of +these individual parts can be connected to the Raspberry Pi. + +Since I've already done this process on my phone, I don't have photos in +progress, but hopefully it should be self explanitory to take things apart. Your +phone may look different on the inside anyway, but the concepts will likely be +similar. + +The first thing to do is to take your phone apart. No actions here need to be +desctructive, or at least weren't for me. Everything was just unscrewing +connections. I removed as many wires as possible. The ones that are required for +use will be connected to the componants we are interested in a way that can't be +removed. I also took out the bell, since this was very large. It functions via +electromagnet, and I haven't figured out the best way to run it via the Pi. + +## Connecting audio + +The phone handset is connected to the base by 4 wires. These form two pairs, one +for the microphone, and one for the speaker. They operate like a normal analog +audio cable. + + + +I was able to differentiate the pairs by unscrewing the plastic on +the headset, after doing so I could see the color wires that connected to the +speaker, which here are white and green. The remaining wires went to the +microphone. + + + +I used the 3.5 mm clips, +and taped them to these wires. Then I plugged in the 3.5 mm cables into the USB +audio adapter. I plugged this into my laptop, and tested both the microphone and +speaker worked by recording with audacity, and playing a YouTube video. + +My microphone is very clippy, which is to be expected of +something so old. Perhaps your phone will be better. I accidently bought the +wrong adapter here, and needed to add an auxillery cable, so my cables look very +messy. + + + +## Connecting the "hook" + +Next, I wanted to connect the "hook" switch. Basically, this is a button that is +pressed when the phone is set down on the phone, and released when it is picked +up. Under the switch on the phone, there were a series of plates and wires. To +simplify things, I removed all of these wires but two. This actually complicated +things, since it was tricky getting the plates to compress correctly with the +wires missing. I added cardboard to pad the space. + + + +I took the two wires, and taped them to jumper cables. Next, I connected them to the +GPIO pins, one to ground, and one to a general purpose pin. I booted my pi, and +ran the following python program to test it worked. + +```python +import RPi.GPIO as GPIO +import time + +BUTTON_GPIO = 24 # Change to the pin you are using +GPIO.setmode(GPIO.BCM) +GPIO.setup(BUTTON_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP) + +while True: + if not GPIO.input(BUTTON_GPIO): + print("phone is on hook") + else: + print("phone is picked up") + time.sleep(1) +``` + +While running it, you can pick up and set down the phone handset to see if the +wires are connected correctly. + +## Connecting the dial + +The dial is the most complex part of the phone, but it basically is just two +buttons. + + + +The first here on the left is formed by the green and blue wires. For each +number the dial rotates past, the circuit is closed. For example, if you dial a +4, the plates connected to these wires touch 4 times, and so the Pi sees this as +4 button presses. + +The second button formed by the two white wires is closed while the dial is in +motion. To simplify my wiring, I ignored this button, and instead just timed the +first button, by counting how many times the button is pressed before 0.3 +seconds without any change (to signify the dial reached the end). + +I used tape and jumper cables to connect the green and blue wires to the GPIO on +my Pi. Then I used this program to test the dial is working. It should print +out the number dialed. The `REST_TIME` parameter may need tweaking if your dial +moves very slowly. + +```python +from datetime import datetime, timedelta +import RPi.GPIO as GPIO +import time + +BUTTON_GPIO = 25 # Change to the pin you are using +GPIO.setmode(GPIO.BCM) +GPIO.setup(BUTTON_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP) +REST_TIME = 0.3 # seconds + +rest_start = datetime.now() +count = 0 +printed = True +pressed = True +while True: + # If there is a new press of the button + if not GPIO.input(BUTTON_GPIO): + if not pressed: + # Count how many times the button is pressed + count+=1 + pressed = True + printed = False + else: + # End the current button press + if pressed: + rest_start = datetime.now() + pressed = False + # If it has been REST_TIME seconds since the button was pressed, and we + # haven't printed the result, print it + if datetime.now() - rest_start > timedelta(seconds=REST_TIME) and not printed: + # Only add this dial to queue if we should accept numbers at this time + print(count % 10) # wrap 10 presses to 0 + # Reset values + count = 0 + printed = True + time.sleep(0.01) +``` + +## More programs to try + +From the first two programs, you can get some idea of how to read the dial and +the hook button. To play and record audio, I found the programs `aplay` and +`arecord` work best, and can be easily invoked via Python's subprocess module. +I also like to use `espeak` to have the Pi read text. + +### Wedding Guestbook program + +Here is a simple program to create a wedding guestbook. This is an idea I, and +many others had, as a cool retro thing to have at a wedding reception to have +guests leave recordings at. + +It is very basic, feel free to adjust it to your needs. The way it works is when +someone picks up the phone, the recorder +will start, and save the recording to a timestamped file. When the phone is hung +up, the recording ends. If you want the user to interact with the dial, I +recommend the general purpose phone program listed later. + +Note, this requires you to have the program `arecord` installed. + +```python +import subprocess +import time +import threading + +# Events allow us to wait until a variable is set +phone_hung_up = threading.Event() +phone_hung_up.set() +phone_picked_up = threading.Event() +phone_picked_up.clear() + +# This thread sets the variables based on the status of the "hook" button +class HangUpThread(threading.Thread): + def __init__(self, phone_hung_up, phone_picked_up): + threading.Thread.__init__(self, args=(), kwargs=None) + self.daemon = True + + self.phone_picked_up = phone_picked_up + self.phone_hung_up = phone_hung_up + GPIO.setmode(GPIO.BCM) + GPIO.setup(BUTTON_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP) + + def run(self): + while True: + if not GPIO.input(BUTTON_GPIO): + self.phone.phone_picked_up.clear() + self.phone.phone_hung_up.set() + else: + self.phone.phone_picked_up.set() + self.phone.phone_hung_up.clear() + time.sleep(0.1) + +HangUpThread(phone_hung_up, phone_picked_up).start() +while True: + # Wait until the phone is picked up + phone_picked_up.wait() + # Start the recording process + process = subprocess.Popen(["arecord", f"{datetime.now().strftime('%Y%m%d-%H%M%S')}.wav"]) + # Record until the phone is hung up + phone_hung_up.wait(): + # Kill the process + process.terminate() +``` + +### General purpose phone + +I wrote [this](https://git.marks.kitchen/?p=rotary_pi;a=summary) program that is +a general purpose way to run commands when a number is dialed. For example, you +can dial a specific number, and it will play a song, or read the weather, or let +your record a message. My configuration is similar to the default. I added some +fun Wav file events, such as one to the George's voicemail song from Seinfeld: +``` +52=events.WavEvent /etc/phone/sound/seinfeld.wav +``` + +If you have any questions about this, please email me (check my website's footer +for my address). I've just moved apartments, and so wasn't able to fully verify +all of the sample programs here work perfectly. + -- cgit v1.2.3