Vanha puhelin (Arduino gadget)

Vanha puhelin pakopelilaitteeksi!

Vanha lankapuhelin on monella tapaa käyttökelpoinen ja mielenkiintoinen gadget. Se luo itsessään jo hauskaa ja jopa mystistä tunnelmaa. Vanhemmalle väelle tämä on lämminhenkinen tuulahdus menneisyydestä. Nuoremmille kyseessä on taas aika historiallinen laite, jota on jännittävä päästä kokeilemaan.

Jos pelaajat ovat nuorempia henkilöitä, kannattaa laittaa puhelimen oheen käyttöohjeet. (esimerkiksi täältä nettisivulta.)

Voit ohjelmoida puhelimen numeroavaruutta vapaasti. Alla on ohjelma, johon on ohjelmoitu yksi oikea viisi numeroinen puhelinnumero (12345), johon soittamalla ohjelma toistaa ennalta äänitetyn .wav tiedoston. Jos soitetaan väärään numeroon, käynnistyy toinen nauhoite. Tässä ideana oli, että puhelin oli yhden pulmatehtävän keskiössä - pelaajien piti selvittää oikea puhelinnumero kahdesta erilaisesta pulmatehtävästä. Puhelin sopisi myös erinomaisesti koko pakopelin keskiöön: jokaisesta pulmatehtävästä saisi uuden puhelinnumeron, johon pitäisi soittaa. Oikeaan numeroon soittaessa saa aina osan isompaa "pääkoodia". Tämä pitäisi onnistua muokkaamalla nykyistä koodia, monistamalla sopivia kohtia.

Puhelimella voi myös ohjata vaikkapa magneettilukkoa tai mitä vain. "Soita oikeaan numeroon ja oven lukko aukeaa". 

Puhelimen säätämäminen pakopelilaitteeksi on itseasiassa yllättävän helppoa. Sen sijaan ohjelmointi on hieman mutkikkaampi aloittelijalle. Toisaalta täältä löydät valmiin koodin, jossa on myös muutamia selityksiä. Voit kopioida koodin vapaasti.

Tarvikkeet:
- Vanha toimiva kiekkomallinen lankapuhelin (Tässä käytetty Ericsonin puhelinta)
- SD-kortti -moduli, SD-kortti, SD-kortin lukija (on monissa läppäreissä kiinteästi).
- Arduino + USB-johto + läppäri
- Kytkentäjohtoja, 3kpl alligaattorijohtoja
- Ruuvimeisseli
- johdon kuorintapihdit tms. (johdon kuorinta onnistuu myös veitsellä tai hampailla, mutta se ei ole ehkä suositeltavaa...)
- Johtoliitin (yhdistä kaksi johtoa toisiinsa) tai kolvi. Nämä eivät välttämättömiä.

1. Avaa puhelimen koppa avamaalla kiinnitysruuvi. Puhelimen kannen etuosassa on "klipsit" eli nosta peräosa ensin ja työnnä kanttaa avatessa hieman eteenpäin (muista myöhemmin suljettaessa nuo klipsit).


2. Irroita puhelimenjohdon päässä oleva pistoke. Irroita johdot pistokkeesta. Voit heittää pistokkeen osat kierrätykseen, niitä ei enää tarvita. Näkyvillä pitäisi olla johdot: musta, punainen, vihreä ja keltainen. 

3. Katso puhelimen sisälle. Kiinnitä huomio yllä mainittuun puhelinjohtoon. Puhelimesta tähän pitäisi olla yhdistettynä punainen ja vihreä johto. Musta ja keltainen ovat kytkemättä, eivätkä ole näkyvissä. Kuori johtoa sen verran, että saat mustan johdon selvästi näkyviin. Kuori mustan johdon päätä. Tähän liitetään johto.


4. Katso puhelimen toiselle puolelle. Näen siellä valkoisen johdon, joka on kiinnitetty puhelimessa liittimeen numero 10. Tämä on GND eli maa. Tästä pitäisi vetää johto äsken kuorimaasi mustaan johtoon. Itse liitin johdon kyseisen ruuvin alle ja sulatin vielä hieman tinaa kiinnikkeeksi. Kohdan 3 puhelinjohtoon liitin johdon pyörittämällä johdot keskenään ja vahvistin liitoksen tinalla. Johtoliittimet olisi varmasti parempi vaihtoehto.

5. Tarkasta vielä, että johdoilla on jokin vedonpoisto. Kohdan 3 kuvasta näet, että puhelinjohtoon on lisätty nippuside. Kun kansi on kiinni ja johdosta vetää, veto kohdistuu ensin tuohon nippusiteeseen eikä johtoliitoksiin. Luurijohdossa on vedonpoisto valmiina (johto paksunee). Sulje puhelimen kansi, kiristä ruuvi.

6. Kytke puhelinjohdon johtoihin alligaattorijohdot. Keltainen jää käyttämättä.


6. Kytke alligaattorijohtojen toiseen päähän tavallinen kytkentäjohto ja yhdistä johdot:
Vihreä: digital PIN 9
Punainen: digital PIN 8
Musta: GND

7. Kytke SD-korttimoduli Arduinoon:
CS: digital PIN 4
SCK: digital PIN 13
MOSI: digital PIN 11
VCC: 5V
GND: GND

Nyt kaikki tarvittavat kytkennät on tehty!

Tallenna SD-kortille äänitiedosto (kytke siis kortti tietokoneeseen). Tiedoston tulee olla muodossa .WAV. Lisäksi tiedostoon kannattaa tehdä seuraavat muutokset online audio converterilla:
Change bit resolution: 8bit
- Change sampling rate: joko 8000Hz tai 11025Hz
-Change audio channels: Mono

Nimeä tiedosto vastaamaan koodissa olevaa nimeä. Esimerkkikoodissa nimet ovat 1.WAV ja 2.WAV. Lataa tiedostot SD-kortille. Pistä kortti kiinni SD-korttimoduliin.

Nyt on ohjelman paikka, eli yhdistä Arduino USB-johdolla tietokoneeseen ja avaa IDE. Jos et ole ohjelmoinut tai et tiedä miten ohjelma saadaan ladattua Arduinoon, niin älä pelästy: löydät ohjeet täältä. Koodin voit kopioida alta.

JOS PUHELIN EI TOIMI HALUTUSTI ?, TARKISTA KYTKENNÄT. Jos ei edelleenkään toimi, tarkasta puhelimen merkki ja alkuperäismaa. Eri maissa johdoissa on käytetty eri värejä ja niiden kytkennöissä saattaa olla pieniä eroja. Löydät nämä googlaamalla. Kokeile myös hakusanan "Arduino" lisäämistä. Joku on ehkä tehty juuri siitä "made in East Germany" puhelimesta samanlaisen!

Ohjelma

#include <SPI.h>

#include <SD.h>

#include <pcmRF.h>
#include <pcmConfig.h>
#include <TMRpcm.h>


#define DEBUG
//CONSTANTS
//Configuration
//Also plug in white wire from phone to Arduino GND
// TÄMÄ ON TOIMIVA VERSIO!

const byte phonePin = 9; //red wire from phone, ääni
const byte hookPin = 8; // green wire from phone, pulssi, luuri hook tai unhook
const byte chipSelectPin = 4;
const unsigned long debounceDelay = 5; //ms, pulssit erottava aika
const unsigned long maxPulseInterval = 250; //ms
const int numDigitsInPhoneNumber = 5;

//GLOBALS
//Declare a global TMRpcm object for controlling audio playback
TMRpcm tmrpcm;
// The char representing of the number dialled (+1 to allow for string-terminating character \o)
char number [numDigitsInPhoneNumber + 1];
// The digit number currently beeing dialled
int currentDigit;
//How many pulses have been detected for current digit
int pulseCount;
//States in which the phone can be
typedef enum { ON_HOOK, OFF_HOOK, DIALLING, CONNECTED } stateType;
// Assume that the handset starts "on hook" eli luuri paikallaan
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);

// Start the serial connection
Serial.begin (9600);
Serial.println (F("Serial connection started"));

// Open connection to the SD card
if (!SD.begin(chipSelectPin)) { //see if card is present and can be initialized:
Serial.println("SD card initialization failed!");
return; // don't do anything more if not working
}

// Volume range from 0 to 7
tmrpcm.setVolume (4);
// Enable 2x oversampling
tmrpcm.quality (1);
Serial.println ("Setup Complete");
}

void loop () {

// Is the receicer is lifted off the handset?
int hookValue = digitalRead(hookPin);

// If the receiver is lifted, but was not 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++;

// Initialize the next value
number[currentDigit] = 0;
}

// If we've dialed 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, "12345") == 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 9 on UNO
// Play the appropriate sound file
tmrpcm.play("1.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 9 with UNO
//Play the appropriate sound file
tmrpcm.play("2.WAV");
// Now wait for the audio to play
delay(8500);
}

// Set the puzzle state to complere
state = CONNECTED;
}

// This digit has been processed, so reset the pulse counter for the next digit
pulseCount = 0;
}

}}

Peda.net käyttää vain välttämättömiä evästeitä istunnon ylläpitämiseen ja anonyymiin tekniseen tilastointiin. Peda.net ei koskaan käytä evästeitä markkinointiin tai kerää yksilöityjä tilastoja. Lisää tietoa evästeistä