Go Down

Topic: Fairy Tale Phone (Read 1 time) previous topic - next topic

rediculum

Dec 13, 2013, 08:16 am Last Edit: Dec 13, 2013, 08:21 am by rediculum Reason: 1
Hello Arduino Community

Here's my recent project as a X-Mas gift for my daughters. Using an old telephone with dial wheel and build in a Pro Mini with SD Card to play fairy tales over the ear phone.
I am not yet finished since I am waiting for the SD break out. Until now I soldered some pins on a MicroSD Adapter and a L78L33 regulator to get the stuff working properly

Here's some impressions:




Fist try to catch the impulse signal from the dial wheel and count them. Also playing with tone().
http://www.youtube.com/watch?v=l-A5vHzMmnc

Prototype with all components
http://www.youtube.com/watch?v=m8wOoVreoVI

And here's the code with the TMRpcm library
Code: [Select]
/*
=============================================================================================
Fairy Tale Phone 1.0
by ReDiculum (Oct. - Dez. 2013)
-------------------------------
X-Mas 2013 Arduino project.
Using an old Zellweger Modell 70 (anno 1982) telephone with dial wheel.
The wheel can be spinned to count impulses and then playing one of ten different
audio fairies stored as 8bit 16.000khz mono WAV files named from 1.wav to 10.wav

SD Card > Arduino pinout:

CS (1)   -> Pin 4 (Chip select)
MOSI (2) -> Pin 11
MISO (7) -> Pin 12
SCK  (5) -> Pin 13

Ear phone  -> Pin 9 (protect with Diode against Pin 3) and GND
Dial wheel -> Pin 2 and GND

=============================================================================================

TMRh20's pcm library for Arduino
https://github.com/TMRh20/TMRpcm
*/
#include <SD.h>
#include <TMRpcm.h>
#include <SPI.h>

#define IMPULSE_PIN 2 // Digital Pin 2
#define PHONE_PIN 3 // Digital Pin 3 (PWM)
#define SD_CHIPSELECT_PIN 4  // SD
#define LED_PIN 13 // Digital Pin 13
#define TIME_WAIT 2000 // Waiting 2sec during dial wheel turns. Sufficient to catch 10 impulses
int countImpulse = 0;
unsigned long timeWait = 0;

TMRpcm music;  // Create object "music" from class "TMRpcm"

/* Sum of running millis and TIME_WAIT.
Must be long integer if kids are not dialing quickly :)
*/
unsigned long timeWaitEnd = 0;

void setup() {
 Serial.begin(57600); // Set console to 57600 baud
 Serial.println("=== FairyTalePhone based on TMRpcm ===");  

 pinMode(LED_PIN, OUTPUT); // onboard LED
 
 music.speakerPin = 9; // Set Pin for SD card audio output

 /* Turn on internal pullup resistor, because we pull the pin to ground.
 When the wheel gives impulse, the contact is opened (no current). That's
 when we have a digitalRead = 1.
 */
 digitalWrite(IMPULSE_PIN, HIGH);

 Serial.println("Ready to dial ...");

 // Play tone and wait here until the dial wheel has sent his first impulse
 tone(PHONE_PIN,420);
 while (digitalRead(IMPULSE_PIN) == 0) {
   delay(1);
 }
 noTone(PHONE_PIN); // Pssht! Here we go!

 Serial.print("Counting impulses ");
 timeWaitEnd = millis() + TIME_WAIT; // Summarize already passed millis since Arduino runs and TIME_WAIT.

 // Count all the dialed impulses until timeWaitEnd has reached
 while (millis() < timeWaitEnd ) {      
   if (digitalRead(IMPULSE_PIN) == 1) {
     /* Increment the amount of impulses if the contacts are opened.
     The wheel pulses with an interval of approx 70ms
     */
     countImpulse++;
     Serial.print(".");
     digitalWrite(LED_PIN, HIGH); // Blink LED ...
     tone(PHONE_PIN,1000); // ... and short tone (70ms) of 1khz to fill the gap
     delay(70);
     digitalWrite(LED_PIN,LOW);
     noTone(PHONE_PIN);
   }
 }

 Serial.println(" "); // New line

 /* If the dial wheel has been turned more than once by nervous kids
 and the amount of counted impulses exceeds 10, we just restart Arduino
 */
 if (countImpulse > 10) {
   Serial.print("Count exceeded 10 ("); Serial.print(countImpulse); Serial.println("), restarting");
   hangOff();
   asm volatile ("  jmp 0"); // Soft Reset
 } else {    
   Serial.print("Preparing fairy tale number "); Serial.println(countImpulse);
   
   // Initialize SD Card with library SimpleSDAudio
   if (!SD.begin(SD_CHIPSELECT_PIN)) {
     tone(PHONE_PIN,100); delay(250); noTone(PHONE_PIN); delay(400);
     tone(PHONE_PIN,80); delay(600); noTone(PHONE_PIN);
     Serial.println("Error initializing SD Card");
     while(1);
   }

   /* define a char array with an index size of 6 and convert
   integer "countImpulse" to char "track" using utoa() function
   http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html
   */
   char track[6];
   utoa(countImpulse,track,10);
   // Append the suffix .wav to the char array
   strcat(track, ".wav");
   
   // Play the audio file
   music.play(track);
   Serial.print("Playing..."); Serial.println(track);
   while (music.isPlaying() == 1) {
     true; // play WAV file number and wait until it's finished
   }
   hangOff(); // That's it, we jump into loop() function    
 }
}

void loop() {
 ;// Nothing to do
 //asm volatile ("  jmp 0"); // Soft Reset
}

void hangOff(){
 // Hang off tone 5x
 delay(1000);
 tone(PHONE_PIN,450); delay(250);
 noTone(PHONE_PIN); delay(250);
 tone(PHONE_PIN,450); delay(250);
 noTone(PHONE_PIN); delay(250);
 tone(PHONE_PIN,450); delay(250);
 noTone(PHONE_PIN); delay(250);
 tone(PHONE_PIN,450); delay(250);
 noTone(PHONE_PIN); delay(250);
 tone(PHONE_PIN,450); delay(250);
 noTone(PHONE_PIN); delay(250);
}
Regards
ReDiculum

Project:
LASERino

Paul__B

You say "fairy tales"; unless they are very short, are you including a function to remember the present position (and rewind a couple of seconds) when it goes on-hook?

rediculum


You say "fairy tales"; unless they are very short, are you including a function to remember the present position (and rewind a couple of seconds) when it goes on-hook?
I will upload max 5min swiss fairy tales which I ripped form old compact cassettes (tapes).
By hooking on, the power will interrupt the Pro Mini. Hooking off will power on the board. No store of current playing position.
Regards
ReDiculum

Project:
LASERino

fungus

This is a cool project...
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

rediculum

#4
Jan 06, 2014, 10:41 am Last Edit: Jan 06, 2014, 11:35 am by rediculum Reason: 1
Finally I also used the SimpleSDAudio library and finished the project. Here's the final code and some pictures
Code: [Select]

/*
=============================================================================================
Fairy Tale Phone 1.0
by ReDiculum (Oct. - Dez. 2013)
-------------------------------
X-Mas 2013 Arduino project.
Using an old Zellweger Modell 70 (anno 1982) telephone with dial wheel.
The wheel can be spinned to count impulses and then playing one of ten different
audio fairies stored as 8bit full-rate (62500) mono PCM files named from 1.PCM to 10.PCM

SD Card > Arduino pinout:

CS (1)   -> Pin 10 (Chip select)
MOSI (2) -> Pin 11
MISO (7) -> Pin 12
SCK  (5) -> Pin 13

Ear phone  -> Pin 9 (protect with Diode against Pin 3) and GND
Dial wheel -> Pin 2 and GND

=============================================================================================

SimpleSDAudio library for audio playback from SD card
http://www.hackerspace-ffm.de/wiki/index.php?title=SimpleSDAudio
*/
#include <SimpleSDAudio.h>

#define IMPULSE_PIN 2 // Digital Pin 2. Read impulses
#define PHONE_PIN 3 // Digital Pin 3 (PWM) for phone tone output (protect with Diode against Pin 9)
#define SD_CHIPSELECT_PIN 10  // Digital Pin 10. SD Card chip select.
#define LED_PIN 13 // Digital Pin 13
#define TIME_WAIT 2000 // Waiting 2sec during dial wheel turns. Sufficient to catch 10 impulses
int countImpulse = 0; // The magic number to "dial" the music track number.

/* Sum of running millis and TIME_WAIT.
Must be long integer if kids are not dialing quickly :)
*/
unsigned long timeWaitEnd = 0;

void setup() {
 Serial.begin(57600); // Set console to 57600 baud
 Serial.println("=== FairyTalePhone based on SSDA ===");  

 pinMode(LED_PIN, OUTPUT); // onboard LED

 /* Turn on internal pullup resistor, because we pull the pin to ground.
 When the wheel gives impulse, the contact is opened (no current). That's
 when we have a digitalRead = 1.
 */
 digitalWrite(IMPULSE_PIN, HIGH);

 Serial.println("Ready to dial ...");

 // Play tone and wait here until the dial wheel has sent his first impulse
 tone(PHONE_PIN,420);
 while (digitalRead(IMPULSE_PIN) == 0) {
   delay(1);
 }
 noTone(PHONE_PIN); // Pssht! Here we go!

 Serial.print("Counting impulses ");
 timeWaitEnd = millis() + TIME_WAIT; // Summarize already passed millis since Arduino runs and TIME_WAIT.

 // Count all the dialed impulses until timeWaitEnd has reached
 while (millis() < timeWaitEnd ) {      
   if (digitalRead(IMPULSE_PIN) == 1) {
     /* Increment the amount of impulses if the contacts are opened.
     The wheel pulses with an interval of approx 70ms
     */
     countImpulse++;
     Serial.print(".");
     digitalWrite(LED_PIN, HIGH); // Blink LED ...
     tone(PHONE_PIN,1000); // ... and short tone (70ms) of 1khz to fill the gap
     delay(70);
     digitalWrite(LED_PIN,LOW);
     noTone(PHONE_PIN);
   }
 }

 Serial.println(" "); // New line

 /* If the dial wheel has been turned more than once by nervous kids
 and the amount of counted impulses exceeds 10, we just restart Arduino
 */
 if (countImpulse > 10) {
   Serial.print("Count exceeded 10 ("); Serial.print(countImpulse); Serial.println("), restarting");
   hangOff();
   asm volatile ("  jmp 0"); // Soft Reset
 } else {
   Serial.print("Preparing fairy tale number "); Serial.println(countImpulse);
   

   // Set Chip Select Pin
   SdPlay.setSDCSPin(SD_CHIPSELECT_PIN);
   // Initialize SD Card with library SimpleSDAudio
   if (!SdPlay.init(SSDA_MODE_FULLRATE | SSDA_MODE_MONO | SSDA_MODE_AUTOWORKER)) {
     tone(PHONE_PIN,100); delay(250); noTone(PHONE_PIN); delay(400);
     tone(PHONE_PIN,80); delay(600); noTone(PHONE_PIN);
     Serial.println("Error initializing SD Card");
     while(1);
   }

   /* define a char array with an index size of 6 and convert
   integer "countImpulse" to char "track" using utoa() function
   http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html
   */
   char track[6];
   utoa(countImpulse,track,10);
   // Append the suffix .PCM to the char array
   strcat(track, ".PCM");
   
   // Set the audio file if it exists and play it
   if (SdPlay.setFile(track)) {
     Serial.print("Playing..."); Serial.println(track);
     SdPlay.play();
     while(!SdPlay.isStopped()) {
       ;
     }
     SdPlay.deInit();
     hangOff();
     // That's it, we jump into loop() function
   } else {
     SdPlay.deInit();
     Serial.print("File "); Serial.print(track); Serial.println(" not found");
     tone(PHONE_PIN,80); delay(250); noTone(PHONE_PIN); delay(400);
     tone(PHONE_PIN,120); delay(600); noTone(PHONE_PIN);
   }
 }
}

void loop(void) {
   ; // Nothing to do here
   //asm volatile ("  jmp 0"); // or Soft Reset?
}

void hangOff(){
 // Hang off tone 5x
 delay(1000);
 tone(PHONE_PIN,450); delay(250);
 noTone(PHONE_PIN); delay(250);
 tone(PHONE_PIN,450); delay(250);
 noTone(PHONE_PIN); delay(250);
 tone(PHONE_PIN,450); delay(250);
 noTone(PHONE_PIN); delay(250);
 tone(PHONE_PIN,450); delay(250);
 noTone(PHONE_PIN); delay(250);
 tone(PHONE_PIN,450); delay(250);
 noTone(PHONE_PIN); delay(250);
}


Fritzing Layout






Regards
ReDiculum

Project:
LASERino

Thanks for sharing, this is an absolutely awesome project.

robtillaart

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up