Arduino-based pill timer that makes phone calls

In this article I will explain the operation and construction of a pill timer that can make phone calls via a cordless telephone handset. I will explain the individual parts of the device and explain the logic that controls the pill timer and telephone.

Operation of the pill timer

The pill timer connects to a keypad, an LCD, and a telephone handset. when the user powers on the pill timer, they must enter the current time using the keypad. To start the timer, the user presses tha "1" key on the keypad. The pill timer determines at what times the user needs to take their pills according to a schedule that has been hard-coded into the pill timer. When it is time for the user to take a pill, the timer will initiate a call to a pre-programmed number. Once the user has picked up, it will play a recorded message. Specifically, this recorded message is "It is time for pill box number" followed by a number.

Schematic and explanation

Memory chip

The Arduino is connected to a W25Q64JV 64 megabit flash chip that stores the voice messages. The first part of the message ("It is time for pill box number") is stored as a WAV file at address 0x000000. The numbers 1-7 are stored as WAV files at addresses 0x030000, 0x040000, and so on. Since the memory chip is a 3.3 volt device, resistor dividers were needed to make the voltages compatible.

Telephone

The Arduino communicates with and controls the telephone handset via the phone's serial port (For more details on hacking the phone, see below). ADC inputs 0 and 1 are configured as a differential input and receive a signal from the handset's speaker output. This allows the Arduino to identify call progress tones. To play the voice messages, the Arduino uses an R2R DAC (resistors R1-R18) to generate an analog signal from a digital port.

The phone is powered using a regulator circuit based on Q1. The power supply to the phone can be switched using pin L3. When pin L3 is high, C2 charges via the potentiometer. Q1 acts as an emitter follower and buffers the voltage on C2. C3 stabilizes the output. The voltage fed to the phone may be adjusted using the potentiometer so that it is around 3.5 volts.

Making calls with an Arduino

During the call, the Arduino must detect and identify the following call progress tones:
Name Frequency 1 Frequency 2 Cadence Description
Dial tone 350Hz 440Hz Continuous Present if the line is not in use
Busy tone 480Hz 620Hz 0.5s on, 0.5s off Present if the called party is using the phone
Reorder tone 480Hz 620Hz 0.25s on, 0.25s off Present after the called party hangs up
Ringing tone 440Hz 480Hz 2s on, 4s off Present after the calling party has dialled but before the called party has picked up
DTMF * 941Hz 1209Hz Continuous Present when the called party presses the "*" button

To do this, the Arduino collects 250 samples from the speaker output pins of the handset at a sample frequency of 8000 samples per second. A discrete Fourier transform (DFT) is applied to the collected samples. However, to save time and memory, the DFT is only calculated at the particular frequencies needed to identify the above tones (350, 440, 480, and 620Hz). To further speed up this process, a table of sine and cosine values for each frequency is precomputed and stored in program memory.

After computing the DFT, one is left with a "magnitude" for each frequency. For each of the above tones, the Arduino checks if the magnitudes of the frequencies involved in that tone are above a certain threshold. In this way, the Arduino can determine the state of the call.

Before placing a call, the Arduino tells the handset to enter the off-hook state. The Arduino then checks for a dial tone to verify that the line is not already in use. If it is, no call is placed. If the dial tone is detected, it will tell the handset to dial a pre-programmed number stored in the handset's phonebook. The Arduino will then listen to the output of the handset, and if it identifies a busy tone, it hangs up. If the phone begins to ring, the Arduino will count the number of rings. After the phone rings four times, the Arduino tells the handset to hang up to avoid leaving a message. If the user picks up before then, the phone will pause and then play the message. When the user hangs up, the Arduino will hear the reorder tone and hang up as well. Since the reorder tone and busy tone have the same frequencies and are both a reason to hang up, there is no need to measure the cadence of the received tone.

Hacking the phone handset

The handset (KX-TGFA51) has pads on its PCB that are configured as a 19.2kbps serial port. The handset can accept commands through its serial port that control the phone or read information from it. A command consists of a 3 letter name followed by zero or more arguments separated by spaces, followed by a newline. Very little information is available about what these commands are or do. Some information can be extracted from the service manuals of similar phone systems. I have compiled a list the commands that I have been able to identify.

Command Description
key <num> Simulates a button press on one of the keys. Note that the value of num for #, *, and 0-9 is the corresponding ASCII value.
Value of num Equivalent key
1Up arrow
2Down arrow
3Right arrow
4Left arrow
5Left screen button
7Right screen button
10TALK
12SP-PHONE
13OFF
23#
2A*
300
311
399
epr <addr[1]> <addr[0]> <num> Read from the EEPROM
addr[1]: The upper byte of the address as hex string
addr[0]: The lower byte of the address as a hex string
num: The number of bytes the be read, as a hex string
epw <addr[1]> <addr[0]> <num> [<data>...] Write to the EEPROM
addr[1]: The upper byte of the address as hex string
addr[0]: The lower byte of the address as a hex string
num: The number of bytes to be written, as a hex string
[<data>...]: One or more data bytes
epv Returns the checksum of the EEPROM. The algorithm is not known.
idr Returns the ID of the device. Equivalent to epr 00 01 05
led <val> led <val> for val < 8 seems to turn the screen backlight off and led a seems to turn the screen backlight on. Aside from these values, I do not know what this command does.
sfr [<val[1]> <val[0]>] This command is used to calibrate the main oscillator. If no argument is given, this command will return the current calibration value. If an argument is given, the calibration value will be set
vdd [<val>] This command is used to calibrate the 1.8V power rail. It works similarly to the sfr command, except with only one byte
ad1 This command is used to measure the charging voltage. Returns one byte as a hex string
tst [<data>...] This command seems to be used to test the wireless transmitter in conjunction with a DECT tester.
I have found the following commands by trial and error or by reading the service manual. Executing them independently has no obvious effect. They are not explained in the serivce manual
  • crx <p1> <p2>
  • pad
  • lcd <val>

WARNING: executing the epf command will brick the handset! If there is a need to use it for some reason, make a backup of the EEPROM contents.

To pick up the phone, the Arduino sends the command key 12, which is equivalent to the speakerphone key. If a dial tone is detected, the Arduino sends the command key 13 to hang up the phone. Then, it sends key 4, then key 2, then key 3 to select the appropriate entry in the phonebook. Finally, it sends key 12 again to pick up the handset. If no dialtone is detected, or the call is to be ended, then the Arduino sends key 13 to end the call before powering off the handset

Images

Outside image:
Arduino with circuit board:
Modified telephone:

Comments

Popular posts from this blog

Improving and calibrating the capacitive water sensor

Turn a buck converter module into a buck-boost converter with only two components

Self-starting inverter