GSM conversion for rotary phone, using Arduino Pro Mini with Atmega328, a QCX601 SLIC module and a SIM800 breakout board.
To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
slic-gsm-rotary-schematic.pngSchematics of the conversion.Portable Network Graphics (PNG) - 94.13 kB - 12/09/2016 at 17:36 |
|
|
SLIC-GSM-rotary-phone.inoArduino code for the project.ino - 10.00 kB - 12/09/2016 at 17:35 |
|
Now this needed some more attention. The switch hook pin (SHK) of the QCX601 not only tells us if the receiver is on hook or not. Due to the way pulse dialing works, it also presents us with the pulses from the rotary dial. To keep track of everything that's happening on that pin, we have to do some timing work again.
With the receiver on hook SHK is LOW, and off hook SHK is HIGH, so pulses coming in will be SHK going low about 60 milliseconds for every pulse. If the time since the last pulse is more than 500 ms we know we just got a complete digit. For accuracy and immunity against false pulses we want 10 to 15 ms of debouncing, so that's another timing thing to the list. To know when we have a complete number, we assume that ten digits is a complete number (you can easily change this) and if the number is shorter, it will be dialed anyway if there are no new pulses for six seconds. Finally, if we put the receiver back on hook for two seconds or more, the dialing should be aborted and we should go back to the idle state. So, we have a bunch of timings to define...
#define tNewDig 500 // time since last SHK rising edge before counting for next digit
#define tHup 2000 // time since last SHK falling edge before hanging up/flushing number
#define tComplete 6000 // time since last SHK rising edge before starting call
#define tDebounce 15 // debounce time
And then the code being looped while in the number getting state:
// count groups of pulses on SHK (loop disconnect) until complete number
// if single digit, fetch stored number
// then make call
if (pulses && (unsigned long)(currentMillis - lastShkRise) > tNewDig) {
// if there are pulses, check rising edge timer for complete digit timeout
digit = pulses - 1; // one pulse is zero, ten pulses is nine (swedish system)
// for systems where ten pulses is zero, use code below instead:
// digit = pulses % 10;
Serial.println(digit); // just for debug
// add digit to number string
number += (int)digit;
digits++;
pulses = 0;
}
if ((shkState == LOW) && (edge == 0)) {
edge = 1;
} else if ((shkState == HIGH) && (edge == 1)) {
pulses++;
Serial.print(". "); // just for debug . . . . .
edge = 0;
}
if ((digits && (shkState == HIGH) && ((unsigned long)(currentMillis - lastShkRise) > tComplete)) || digits == 10) {
// if completed number (full 10 digits or timeout with at least one digit)
// check if shortnumber/fave and then tell GSM board to initiate call
if (digits == 1) getFave();
Serial.print("Number complete, calling: ");
Serial.println(number);
number.toCharArray(numArray, 11);
#if defined(GSM_MODULE)
call.Call(numArray);
#endif
state = ACTIVE_CALL;
}
if ((shkState == LOW) && (unsigned long)(currentMillis - lastShkFall) > tHup) {
// reciever on hook, flush everything and go to idle state
flushNumber();
Serial.println("On hook. Flushing everything. Going idle.");
state = IDLE_WAIT;
}
Like that. As you can see, I also put in a speed dial function where single digit numbers are checked against a list with the getFave() function and replaced with complete numbers. Also, you can see the default state of the code is for use with Swedish phones where the dial goes from 0 to 9. That's the line saying...
digit = pulses - 1;
Most likely you don't want that, so you should use this line instead...digit = pulses % 10;
That % in there (modulo) makes the digit value the remainder when dividing the number of pulses by ten. Basically it's using wrap around to get 0 instead of 10. I stole this little gem, I admit that. Looks so much nicer than the if-based alternative, and I got smarter by looking the % thing up ;) As for the debouncing of SHK, it's done whatever state we are in, and it looks like this. The currentMillis used for all timings is set here too.
currentMillis = millis(); // get snapshot of time for debouncing and timing
// read and debounce hook pin
currentShkReading = digitalRead(shkPin);
if (currentShkReading != lastShkReading) {
// reset debouncing timer
lastShkDebounce...
Read more »
Ok, so the main things I had to do dealing with the SLIC module was to have it create the ring signal, and to make the pulses and states of the switch hook pin control the actions of the phone. The ringing was the easier part, as it was pretty much exactly described in the QCX601 datasheet.
Early on I had decided to base my code on timings using the millis() function, so the "ringing" took this form, based on that diagram:
// Ringing interval
// How much time has passed, accounting for rollover with subtraction!
if ((unsigned long)(currentMillis - ringPreviousMillis) >= ringInterval) {
digitalWrite (rcPin,1); // Ring
// Use the snapshot to set track time until next event
ringPreviousMillis = currentMillis;
}
if (digitalRead(rcPin) && ((unsigned long)(currentMillis - ringPreviousMillis) >= ringDuration)) {
digitalWrite(rcPin, 0); // Silent after ring duration
}
// 25Hz oscillation
// How much time has passed, accounting for rollover with subtraction!
if ((unsigned long)(currentMillis - oscPreviousMillis) >= oscInterval) {
// It's time to do something!
if (digitalRead(rcPin)) {
digitalWrite(hzPin, !digitalRead(hzPin)); // Toggle the 25Hz pin
}
// Use the snapshot to set track time until next event
oscPreviousMillis = currentMillis;
}
The rflPin is set to be LOW all the time, and the timings are defined like this for typical Swedish ringing:#define oscInterval 20
#define ringInterval 6000
#define ringDuration 1200
Basically, for every lap in the loop when in ringing state it does this...If it's time to sound the bell again, put the RC pin HIGH, then reset the time for this (wait 6 seconds until next go).
If the RC pin is HIGH, and it has been 1.2 seconds since it was put HIGH, set the RC pin LOW to stop ringing.
If it has been more than 20 ms since last toggle of the 25Hz pin, reset the time for this and toggle the 25Hz pin should the RC pin be HIGH.
(And then there are checks if we should stop all the ringing and go to some other state, of course.)
Plan the placement of components inside the telephone. I had no
problem fitting the SIM800 mini board with antenna on the right, and the
rest of the stuff on the left side. Using perf board, you can create a
nice and compact PCB to fit in there, maybe even screw in place with a
bracket.
Program your Arduino Pro Mini. You need to download and install the SIM900 library first. Then you edit the project Arduino code to set these two things:
1: The kind of rotary dial you have. In Sweden where I live, the dial starts with 0 and ends with 9. This means that one pulse sent is a zero, and ten pulses equals number nine. If this is the case with your phone, you don't have to change anything. Otherwise, you edit the code where it says..
digit = pulses - 1; // one pulse is zero, ten pulses is nine (swedish system)
// for systems where ten pulses is zero, use code below instead:
// digit = pulses % 10;
...into...//digit = pulses - 1; // one pulse is zero, ten pulses is nine (swedish system)
// for systems where ten pulses is zero, use code below instead:
digit = pulses % 10;
That way, it sets the digit to the number of pulses sent, unless there are ten pulses, in which case the digit should be zero. Hook up your Pro Mini using the FTDI programmer and upload the sketch.
Solder stuff together (or use pins and dupont connectors where suitable) according to the schematic. Using a socket for the Pro Mini is a good idea. Makes it easy to replace it or remove it for re-programming.
Create an account to leave a comment. Already have an account? Log In.
The project seems interesting - however I think I’m taking the easy way out to give my Ericsson Dialog new life in 2019 - I’m connecting it to a GSM gateway that understands pulse dialing. The questions I have are -
1) is the voltage (12V or so) a regular gateway would supply enough to ring the bell of the Dialog?
2) I’m stuck at the very first step - how to open the phone for replacing the phone socket plug wire with a modular plug wire? How do you open this thing?
Nice project, so nice that I must have that also. Just got all of components and next phase is to choose color of phone and assemble it ;)
Hi Johan!
I know it has been some time since you completed and posted your conversion but if you by any chance still remember/reads this thread. I would like to know if you had to do anything about the original speaker in the phone? Did you swap it for another speaker element or are you using the original one? And how are you driving it? When i drive mine straight from my Adafruit Phona, the volume is still so low that its basically impossible to hear anything :)
Hi, I guess that depends a lot on how hard the speaker element is to drive, and what the Adafriut Phona is capable of. I used the original speaker, and it worked fine with the GSM board I was using. If you are using a SLIC board like I did, you could try running the audio through the SLIC, not removing the handset wires from their original screw posts in the telephone. I got more interference that way, but it worked that too.
FYI: Here is an open source DIY SLIC built using AVR/Arduino for those who are more adventurous.
Rowetel.com "A $10 ATA"
part 1: http://www.rowetel.com/?p=26
part2: http://www.rowetel.com/?p=44
part 3: http://www.rowetel.com/?p=1776
part 4: http://www.rowetel.com/?p=1807
part 5: http://www.rowetel.com/?paged=15
this could be adapted to a working version of Maxwell smarts (agent 86) shoe phone
Become a member to follow this project and never miss any updates
ola
I am building this
but it has problems reconizing the on-hook switch
and the serial gets spammed with sim900 data
can you help me?