docs: finish write-up (#3)
							
								
								
									
										117
									
								
								README.md
									
									
									
									
									
								
							
							
						
						| @@ -1,23 +1,27 @@ | ||||
| # Rotary Phone Audio Guestbook | ||||
|  | ||||
| This project transforms a rotary phone into a voice recorder for use at special events (i.e. wedding audio guestbook, etc.). | ||||
|  | ||||
| - [Rotary Phone Audio Guestbook](#rotary-phone-audio-guestbook) | ||||
|   - [Background](#background) | ||||
|   - [Post-Event](#post-event) | ||||
|     - [Future Potential](#future-potential) | ||||
|     - [Future Work (Action Items)](#future-work-action-items) | ||||
|   - [Materials](#materials) | ||||
|   - [Setup](#setup) | ||||
|   - [Hardware](#hardware) | ||||
|     - [Wiring](#wiring) | ||||
|       - [Hook](#hook) | ||||
|       - [Phone Cord](#phone-cord) | ||||
|     - [Microphone Replacement (Optional)](#microphone-replacement-optional) | ||||
|   - [Software](#software) | ||||
|     - [Dev Environment](#dev-environment) | ||||
|     - [Dependencies](#dependencies) | ||||
|     - [Config](#config) | ||||
|     - [AudioInterface Class](#audiointerface-class) | ||||
|       - [rotaryGuestBook.service](#rotaryguestbookservice) | ||||
|       - [Operation Mode 1: rotaryGuestBook](#operation-mode-1-rotaryguestbook) | ||||
|       - [Operation Mode 2: rotaryGuestBookwithRotaryDialer](#operation-mode-2-rotaryguestbookwithrotarydialer) | ||||
|       - [audioGuestBook systemctl service](#audioguestbook-systemctl-service) | ||||
|     - [Operation Mode 1: audioGuestBook](#operation-mode-1-audioguestbook) | ||||
|     - [Operation Mode 2: audioGuestBookwithRotaryDialer](#operation-mode-2-audioguestbookwithrotarydialer) | ||||
|  | ||||
| This project transforms a rotary phone into a voice recorder for use at special events (i.e. wedding audio guestbook, etc.). | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Background | ||||
|  | ||||
| @@ -27,13 +31,15 @@ Below you will find a parts list and detailed setup guide. Please feel free to r | ||||
|  | ||||
| ## Post-Event | ||||
|  | ||||
| Since this was a trial by fire type of scenario there ended up being a few gotchas at the real event which I've since accounted for. Namely setting a time limit on the recording length as we had some youngsters leaving 5+ minute messages repeatedly and this ended up draining the battery. | ||||
| Since this was a trial by fire type of scenario there ended up being a few gotchas at the real event which I've since accounted for. Namely setting a time limit on the recording length as we had some youngsters leaving 5+ minute messages repeatedly and this ended up draining the battery. Alternatively, depending on your scenario, it might be preferable to attach directly to a 5V power supply. | ||||
|  | ||||
| ### Future Potential | ||||
| ### Future Work (Action Items) | ||||
|  | ||||
| A few weeks before the wedding I had the code registering dialed numbers from the rotary encoder with the goal of playing back special messages for certain guests who dialed a certain combination (i.e. dial an area code to hear a special message to my old roomates). The details of this operation mode are described in Mode 2 below. In order to activate this mode I had to wait for input when the phone was off the hook. This required an extra step of dialing zero before leaving a normal voice message. In the end we decided to keep it simple and I've thus migrated this code to the dev branch along with the code to run through post-porcessing the audio in a separate process. | ||||
| A few weeks before the wedding I had the code registering dialed numbers from the rotary encoder with the goal of playing back special messages for certain guests who dialed a certain combination (i.e. dial an area code to hear a special message to my old roomates). The details of this operation mode are described in [Mode 2](#operation-mode-2-rotaryguestbookwithrotarydialer) below. In order to activate this mode I had to wait for input when the phone was off the hook. This required an extra step of dialing zero before leaving a normal voice message. In the end we decided to keep it simple and I've thus migrated this code to the dev branch along with the code to run through post-porcessing the audio in a separate process. | ||||
| If any one is interested in expanding this please feel free. | ||||
|  | ||||
| I would also like to thread the audio playback so I can have a monitor/watchdog service terminate the thread upon hook callback so that the message doesn't continue playing once the user hangs up. | ||||
|  | ||||
| ## Materials | ||||
|  | ||||
| | Part|Notes|Quantity|Cost| | ||||
| @@ -44,6 +50,8 @@ If any one is interested in expanding this please feel free. | ||||
| | [micro SD card](https://a.co/d/1gb2zhC) | Any high capacity/throughput micro SD card that is rpi compatible | 1 | $8.99 | | ||||
| | [USB Audio Adapter](https://www.adafruit.com/product/1475) | Note: I removed the external plastic shell and directly soldered the wires instead of using the female 3.5mm receptacle. | 1 | $4.95 | | ||||
| | [USB OTG Host Cable - MicroB OTG male to A female](https://www.adafruit.com/product/1099) | | 1 | $2.50 | | ||||
| | --- | **--- If you don't want to solder anything ---** | --- | --- | | ||||
| | [3.5mm Male to Screw Terminal Connector](https://www.parts-express.com/3.5mm-Male-to-Screw-Terminal-Connector-090-110?quantity=1&utm_source=google&utm_medium=cpc&utm_campaign=18395892906&utm_content=145242146127&gadid=623430178298&gclid=CjwKCAiAioifBhAXEiwApzCztl7aVb18WP4hDxnlQUCHsb62oIcnduFCSCbn9LFkZovYTQdr6omb3RoCD_gQAvD_BwE) | Optional: can connect the handset cables directly to the USB audio interface via these screw terminals | 2 | $1.37 | | ||||
| | --- | **--- If running off a battery ---** | --- | --- | | ||||
| | [LiPo Battery](https://www.adafruit.com/product/2011)| Optional: maximize capacity based on what will fit within your rotary enclosure. |1| $12.50 | | ||||
| | [LiPo Shim](https://www.adafruit.com/product/3196)| Optional: if you plan to run this off a LiPo I would recommend something like this to interface with the rpi zero. |1| $9.95 | | ||||
| @@ -51,13 +59,43 @@ If any one is interested in expanding this please feel free. | ||||
| | --- | **--- If replacing the built-it microphone ---** | --- | --- | | ||||
| | [LavMic](https://www.amazon.com/dp/B01N6P80OQ?ref=nb_sb_ss_w_as-reorder-t1_ypp_rep_k3_1_9&=&crid=15WZEWMZ17EM9&=&sprefix=saramonic) | Optional: if you'd like to replace the carbon microphone. This is an omnidirectional lavalier mic and outputs via a 3.5mm TRS | 1 | $24.95 | | ||||
|  | ||||
| ## Setup | ||||
| ## Hardware | ||||
|  | ||||
| ### Hardware | ||||
| ### Wiring | ||||
|  | ||||
| #### Wiring | ||||
| #### Hook | ||||
|  | ||||
| #### Microphone Replacement (Optional) | ||||
| - Use multimeter to do a continuity check to find out which pins control the hook: | ||||
|    | ||||
| | On-hook --> Open circuit (Value == 1)  | Off-hook --> Current flowing | | ||||
| | ------------- | ------------- | | ||||
| |  |   | | ||||
|  | ||||
| - The B screw terminal on the rotary phone is connected to the black wire which is grounded to the rpi. | ||||
| - The L2 screw terminal on the rotary phone is connected to the white wire which is connected to GPIO pin 22 on the rpi. | ||||
|  | ||||
|    | ||||
|  | ||||
| - *Note: the green wire was used for the experimental rotary encoder feature identified in the [future work](#future-work-action-items) section.* | ||||
|  | ||||
| | Rotary Phone Block Terminal  | Top-down view | | ||||
| | ------------- | ------------- | | ||||
| |  |   | | ||||
|    | ||||
| #### Phone Cord | ||||
|  | ||||
| - The wires from the handset cord need to be connected to the USB audio interface | ||||
|   - I soldered it but you can alternatively use 2x [3.5mm Male to Screw Terminal Connector](https://www.parts-express.com/3.5mm-Male-to-Screw-Terminal-Connector-090-110?quantity=1&utm_source=google&utm_medium=cpc&utm_campaign=18395892906&utm_content=145242146127&gadid=623430178298&gclid=CjwKCAiAioifBhAXEiwApzCztl7aVb18WP4hDxnlQUCHsb62oIcnduFCSCbn9LFkZovYTQdr6omb3RoCD_gQAvD_BwE) which plug directly into the rpi. | ||||
|     - *Note: The USB audio interface looks weird in the pics since I stripped the plastic shell off in order to solder directly to the mic/speaker leads* | ||||
|  | ||||
|  | ||||
|  | ||||
| - Use this ALSA command from the command line to test if the mic is working on the rpi before you set up the rotary phone: `aplay -l` | ||||
|   - You might have a different hardware mapping than I did, in which case you would change the `alsa_hw_mapping` in the [config.yaml](config.yaml). | ||||
|   - [Here's](https://superuser.com/questions/53957/what-do-alsa-devices-like-hw0-0-mean-how-do-i-figure-out-which-to-use) a good reference to device selection. | ||||
|   - You can also check [this](https://stackoverflow.com/questions/32838279/getting-list-of-audio-input-devices-in-python) from Python. | ||||
|  | ||||
| ### Microphone Replacement (Optional) | ||||
|  | ||||
| I found the sound quality of the built-in [carbon microphone](https://en.wikipedia.org/wiki/Carbon_microphone) on the rotary phone to be quite lacking in terms of amplitude, dynamic range and overall vocal quality. I tried boosting the gain from the digital (ALSA driver) side but this introduced an incredible amount of noise as expected. I then approached this from the analog domain and tried alternative circuitry to boost the sound quality based off this [carbon-to-dynamic converter](https://www.circuits-diy.com/mic-converter-circuit/). | ||||
|  | ||||
| @@ -70,12 +108,21 @@ To replace: | ||||
| - Unscrew mouthpiece and remove the carbon mic | ||||
| - Pop out the plastic terminal housing with the two metal leads | ||||
| - Unscrew red and black wires from terminal | ||||
| - Prepare your lav mic | ||||
|   - I pulled off the 3.5mm male headphone pin since it is usually coated and annoyingly difficult to solder directly on to. | ||||
|   - Carefully separate the two wires from the lav mic and spiral up the surrounding copper. This will act as our ground signal. | ||||
| - Extend the green wire from the phone cord clip to the ground point of the lav mic. | ||||
| - Red to red, black to blue as per the following diagram: | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ### Software | ||||
|  | ||||
|  | ||||
| #### Dev Environment | ||||
|  | ||||
|  | ||||
| ## Software | ||||
|  | ||||
| ### Dev Environment | ||||
|  | ||||
| - rpi image: [Rasbian](https://www.raspberrypi.com/documentation/computers/getting-started.html) w/ SSH enabled | ||||
| - rpi on same network as development machine | ||||
| @@ -83,7 +130,7 @@ To replace: | ||||
|  | ||||
| [Here's](https://jayproulx.medium.com/headless-raspberry-pi-zero-w-setup-with-ssh-and-wi-fi-8ddd8c4d2742) a great guide to get the rpi setup headless w/ SSH & WiFi dialed in. | ||||
|  | ||||
| #### Dependencies | ||||
| ### Dependencies | ||||
|  | ||||
| - `pip3 install -r requirements.txt` or pip install each manually: | ||||
|   - [GPIOZero](https://gpiozero.readthedocs.io) | ||||
| @@ -91,22 +138,44 @@ To replace: | ||||
|   - [PyAudio](https://people.csail.mit.edu/hubert/pyaudio/) | ||||
|   - [PyYAML](https://pyyaml.org/) | ||||
|  | ||||
| #### [AudioInterface Class](audioInterface.py) | ||||
| ### [Config](config.yaml) | ||||
|  | ||||
| #### [rotaryGuestBook.service](rotaryGuestBook.service) | ||||
| - This file allows you to customize your own set up (edit rpi pins, audio reduction, alsa mapping, etc), modify the yaml as necessary. | ||||
|  | ||||
| - For GPIO mapping, refer to the wiring diagram specific to your rpi: | ||||
|    | ||||
|  | ||||
| ### [AudioInterface Class](audioInterface.py) | ||||
|  | ||||
| - Utilizes pydub and pyaudio extensively. | ||||
| - Houses the main playback/record logic and has future #TODO expansion for postprocessing the audio. Would like to test on an rpi4 to see if it can handle it better for real-time applications. | ||||
|  | ||||
| #### [audioGuestBook systemctl service](/audioGuestBook.service) | ||||
|  | ||||
| This service starts the python script on boot. Place it in the `/etc/systemd/system` directory. | ||||
|  | ||||
| `systemctl enable audioGuestBook.service` | ||||
| `systemctl start audioGuestBook.service` | ||||
| ```sh | ||||
| systemctl enable audioGuestBook.service | ||||
| systemctl start audioGuestBook.service | ||||
| ``` | ||||
|  | ||||
| ### Operation Mode 1: [audioGuestBook](/audioGuestBook.py) | ||||
|  | ||||
| #### Operation Mode 1: [rotaryGuestBook](rotaryGuestBook.py) | ||||
| - This is the main operation mode of the device. | ||||
| - There are two callbacks in main which poll the gpio pins for the specified activity (hook depressed, hook released). | ||||
| - Once triggered the appropriate function is called. | ||||
| - On hook (depressed) | ||||
|   - Nothing happens | ||||
| - Off hook (released) | ||||
|   - Plays back your own welcome message located in `/sounds/voicemail.wav` followed by the beep indicating ready to record. | ||||
|   - Begins recording the guests voice message. | ||||
|   - Guest hangs up, recording is stopped and stored to the `/recordings/` directory. | ||||
|  | ||||
| #### Operation Mode 2: [rotaryGuestBookwithRotaryDialer](rotaryGuestBookwithRotaryDialer.py) | ||||
| ### Operation Mode 2: [audioGuestBookwithRotaryDialer](./todo/audioGuestBookwithRotaryDialer.py) | ||||
|  | ||||
| ***Note*:** Untested - decided not to go this route for my own wedding | ||||
|  | ||||
| - This mode is a special modification of the normal operation and requires a slightly different wiring connection since it accepts input from the rotary dialer. | ||||
| - The idea was to playback special messages when particular users dial a certain number combination (i.e. 909 would play back a message for certain guests who lived with the groom in that area code). | ||||
| - In this mode of operation the users will need to dial 0 on the rotary dialer in order to initiate the voicemail. | ||||
| - The rotary dialer is a bit more complex to set up, you need a pull up resistor connected between the F screw terminal and 5V on the rpi and the other end on GPIO 23. #TODO: Diagram | ||||
|   | ||||
| Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB | 
| Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB | 
| Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB | 
							
								
								
									
										
											BIN
										
									
								
								images/final_result.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 360 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images/final_result_2.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 640 KiB | 
| Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB | 
| Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB | 
							
								
								
									
										
											BIN
										
									
								
								images/hook_test_1.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.0 MiB | 
							
								
								
									
										
											BIN
										
									
								
								images/hook_test_2.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.0 MiB | 
| Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images/pi_block_terminal_wiring.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 15 KiB | 
| Before Width: | Height: | Size: 667 KiB After Width: | Height: | Size: 667 KiB | 
| Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 2.0 MiB | 
 Nick Pourazima
					Nick Pourazima