DTMF Generator/Gate Controller

I’ve built a DTMF generator/controller based on the Imp. I have an automated gate at the end of a 1/4 mile driveway. It is controlled by our home phone, using dial tones (DTMF). I wanted to be able to control it using my iPhone, from “anywhere in the world”. There is no wifi at the gate.

Rather than building a DTMF interface, I bought a serial “voice/fax” modem, like we used to use for dial-up Internet. I also bought a converter to convert the 3.3v serial UART signals of the Imp to the RS-232 voltage levels (12v) expected by the modem. Connection to the modem is from the Imp to the converter using two lines (TX and RX), and from the converter to the modem using an RS-232 cable. I had to jury-rig a male-to-male cross-over converter for the RS-232 connection (just GND, TX, and RX).

Communication with the modem is very simple, especially since I am not looking at the responses from the modem. Instead, I have just inserted delays so that the modem has ample time to respond to each command. I included some code to keep the receive buffer cleared, although I doubt it’s necessary. Technically, I could even disconnect RX line of the Imp UART since I’m not looking at any received data.

I’m waiting on parts to build a DTMF/line interface without the modem.

`
//Get a single character from the UART, if available
function getChar() {
local retval;
retval = hardware.uart12.read();
if(retval > -1)
return format("%c", retval);
else
return “”;
}

//Clear out the UART receive buffer
function clear_receive_buffer() {
local retval;
retval = getChar();
while (retval != “”)
retval = getChar();
}

//sents a character string to the modem with an appended CR
//Doesn’t wait for a response
function sendString(str1) {
str1 += format("%c",’\r’); //appends CR
server.log(str1)
foreach(i, val in str1)
hardware.uart12.write(val);
}

function sendTones(str1) {
str1 = str1.toupper();
sendString(“AT+FCLASS=8”); //Put the modem into voice mode
imp.sleep(1);
sendString(“ATH1”) //Take phone line off-hook
imp.sleep(2);
foreach(i, val in str1) {
if((val >= ‘0’ && val <= ‘9’) || val == ‘*’ || val == ‘#’ || (val >= ‘A’ && val <= ‘D’)) {
sendString(“AT+VTS=” + format("%c",val)); //create DTMF tone
imp.sleep(0.5)
}
else if(val == ‘,’) { //allow insertion of 1 sec delays into dial string
server.log(“delay”);
imp.sleep(1);
}
}
sendString(“ATH0”); //Put the modem back on-hook
imp.sleep(1);
clear_receive_buffer(); //just to keep the serial buffer clean
}

// input class for Gate control channel
class input extends InputPort {
// This defines the port name and type
name = “gate control”
//type = “string” //The web app will send the dial string
type = “number” //OR the web app sends a code

function set(value) {
    //sendTones(value)          //Send the dial string to the modem
    if(value == 0) {            //OR generate the dial string based on received code
      sendTones("*7,,7");       //close gate
    }
    else if(value == 1) {
      sendTones("*7,,8");       //open gate
    }  
    else if(value == 2) {
      sendTones("*7,,9");       //briefly open gate
    }
}

}

//The modem detects serial data rate (baud rate) automatically
//The serial connecction uses only two lines: TX and RX
hardware.uart12.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS);

// Register with the server
imp.configure(“Gate-Opener-1”, [input()], []);

sendString(“ATZ”); //reset the modem
imp.sleep(2);

sendString(“ATE0”); //turn off modem character echo
imp.sleep(1);

clear_receive_buffer();

// End of code.

`

That is a pretty awesome hack! Well done :slight_smile: