Paul__B:
Totally ridiculous!
What we have not seen so far, is the code. And the answer is in the code.
It is unbelievably simple. The dialling rate is ten impulses per second. (I have a meter here which if it had batteries in it, tests a dial and indicates with resonant reeds, also indicating the mark-space ratio with a common d'Arsonval meter.) So you simply time breaks in the current - to do which you have apparently already implemented a circuit.
If the break lasts for more than 200 ms, it is an "on hook" indication. If it does not, you count it and if there is longer than 500 ms between breaks, that digit dialled is complete.
This all sounds very clever if it could work! Here is the code, let me know how if it seems possible.
// DEFINES
#define DEBUG
// INCLUDES
#include <SPI.h> // Generic SPI interface, which is used to access the card reader
#include <SD.h> // Provides functionality for reading/writing to SD cards
// Provides audio playback functionality
// Download from https://github.com/TMRh20/TMRpcm
// Note that the buffSize declaration in pcmConfig.h was increased to 254 in order to reduce crackle.
#include <TMRpcm.h>
// CONSTANTS
// Configuration
// Also plug in white wire from telephone to Arduino GND
const byte phonePin = 9; // Red wire from telephone
const byte hookPin = 8; // Green wire from telephone
const byte lockPin = 2; // Connected to relay
const byte chipSelectPin = 4;
const unsigned long debounceDelay = 5; // ms
// The max separation (in ms) between pulses of a digit being dialled
const unsigned long maxPulseInterval = 250; // ms
const int numDigitsInPhoneNumber = 5;
// GLOBALS
// Declare a global TMRpcm object for controlling audio playback
TMRpcm tmrpcm;
// The char representation of the number dialled (+1 to allow for string-terminating character \0)
char number[numDigitsInPhoneNumber + 1];
// The digit number currently being dialled
int currentDigit;
// How many pulses have been detected for the current digit
int pulseCount;
// States in which the telephone can be
typedef enum { ON_HOOK, OFF_HOOK, DIALLING, CONNECTED } stateType;
// Assume that the handset starts "on hook" (i.e. placed on the base unit)
stateType state = ON_HOOK;
// In order to record "pulses" on the line, we keep track of the last pin reading...
int previousPinReading = HIGH;
// ...the time at which the pin last changed value...
unsigned long timePinChanged;
// ...and the current time
unsigned long now = millis ();
void setup () {
// Both pins will initially be set as inputs (with internal pullup resistors), although
// may be reassigned as outputs later
pinMode(phonePin, INPUT_PULLUP);
pinMode(hookPin, INPUT_PULLUP);
// The lock pin will receive a LOW signal to release
digitalWrite(lockPin, HIGH);
pinMode(lockPin, OUTPUT);
// Start the serial connection
Serial.begin (9600);
Serial.println (F("Serial connection started"));
// Open the connection to the SD card
if (!SD.begin(chipSelectPin)) { // see if the card is present and can be initialized:
Serial.println("SD card initialization failed!");
return; // don't do anything more if not
}
// Volume range from 0 to 7
tmrpcm.setVolume(4);
// Enable 2x oversampling
tmrpcm.quality(1);
Serial.println("Setup Complete");
}
void loop () {
// Is the receiver lifted off the handset?
int hookValue = digitalRead(hookPin);
// If the receiver is lifted, but wasn't previously
if(hookValue == 0 && state == ON_HOOK) {
// Print some debug info
#ifdef DEBUG
Serial.println("Receiver Lifted");
#endif
// Update the state
state = OFF_HOOK;
}
// If the receiver is on the hook, but wasn't previously
else if(hookValue == 1 && state != ON_HOOK){
// Print some debug info
#ifdef DEBUG
Serial.println("Receiver Replaced");
#endif
// Update the puzzle state
state = ON_HOOK;
// Clear any information about the number we were dialling
pulseCount = 0;
currentDigit = 0;
// Stop any audio
tmrpcm.stopPlayback();
// Put the pin back into input state
pinMode(phonePin, INPUT_PULLUP);
}
if(state == OFF_HOOK || state == DIALLING){
// Record the current timestamp
now = millis();
// Test the value of the phone pin
int pinReading = digitalRead (phonePin);
// If the value has changed
if (pinReading != previousPinReading) {
// The user is dialling a number
state = DIALLING;
// "Debouncing" method to ignore jittery fluctations in readings
// If the time elapsed since the last time this pin was changed is only a small amount of time
if (now - timePinChanged < debounceDelay) {
// Don't do anything
return;
}
// A HIGH signal means that a dialling pulse has been detected
if(pinReading == HIGH){
pulseCount++;
}
// Update the stored time and reading values for further comparison
timePinChanged = now;
previousPinReading = pinReading;
}
// We've recorded a sequence of pulses, and the time since the last pulse was detected
// is longer than the maxPulseInterval
if (((now - timePinChanged) >= maxPulseInterval) && pulseCount > 0) {
// If we haven't yet dialled a complete number
if (currentDigit < numDigitsInPhoneNumber) {
// The digit '0' is represented by 10 pulses
if (pulseCount == 10) { pulseCount = 0; }
#ifdef DEBUG
Serial.print (F("Digit dialled: "));
Serial.println (pulseCount);
#endif
// Append the most recent digit dialled onto the end of the number array
number[currentDigit] = pulseCount | '0';
// Increment the counter
currentDigit++;
// Initialise the next value
number[currentDigit] = 0;
}
// If we've dialled the correct number of digits
if (currentDigit == numDigitsInPhoneNumber) {
// Print some debug information
#ifdef DEBUG
Serial.print (F("Number dialled: "));
Serial.println (number);
#endif
// This number plays a recorded message
if(strcmp(number, "21800") == 0){
#ifdef DEBUG
Serial.println (F("Playing sound"));
#endif
// Now, we set the pin as OUTPUT for the audio signal
pinMode(phonePin, OUTPUT);
// Set the TMRPCM library to use the pin for output
tmrpcm.speakerPin = 9; // Must be 5, 6, 11 or 46 on MEGA, 9 on UNO, Nano, etc
// Play the appropriate sound file
tmrpcm.play("shoe.wav");
// Wait until the receiver is replaced on the handset
while(!digitalRead(hookPin)){ delay(1000); }
}
// If an incorrect number was dialled
else {
// Set the pin as OUTPUT
pinMode(phonePin, OUTPUT);
// Set the TMRPCM library to use the pin for output
tmrpcm.speakerPin = 9; // Must be 5, 6, 11 or 46 on MEGA, 9 on UNO, Nano, etc
// Play the appropriate sound file
tmrpcm.play("BOMB.WAV");
// Now wait for the audio to play
delay(2500);
}
// Set the puzzle state to complete
state = CONNECTED;
}
// This digit has been processed, so reset the pulse counter for the next digit
pulseCount = 0;
}
}
}