My Doctor Who MonoChron Clock
Moderators: adafruit_support_bill, adafruit

My Doctor Who MonoChron Clock

by DanSlage on Fri Feb 03, 2012 1:19 pm

I am working on a Doctor Who inspired clock for the MonoChron. A video can be seen here. http://youtu.be/DHecR3Matss

The TARDIS travels through an wiggly wormhole. Pressing a button or switch (except "Menu") will cause the TARDIS to dematerialize and rematerialize a moment later in a random spot. My daughter plans on using this as her primary alarm clock once I figure out how to replace the alarm siren with the Doctor Who theme song.

I had to rewrite the wormhole code a few times to get it fast enough render correctly. The GLCD.h drawing routines are way too slow instead the wormhole uses glcdDataWrite()s directly to draw everything.

To speed things up I also EXTERMINATEd all division and modulus operations. For example to separate the hour into a high digit and low digit:

Traditional

Code: Select all | TOGGLE FULL SIZE
high_digit = hour/10;
low_digit = hour%10;

I found this to be much faster

Code: Select all | TOGGLE FULL SIZE
high_digit = 0;
low_digit = hour;
while (low_digit >= 10) {  // Count tens
  high_digit++;
  low_digit -= 10;
}

When you have as much motion as this clock does every clock cycle counts.
Last edited by DanSlage on Tue Jul 02, 2013 8:20 am, edited 1 time in total.
DanSlage
 
Posts: 4
Joined: Thu Jan 26, 2012 3:29 pm

Re: My Doctor Who MonoChron Clock

by adafruit_support_bill on Fri Feb 03, 2012 1:35 pm

Nice one! You should post this in this thead too: :D
http://forums.adafruit.com/viewtopic.php?f=41&t=14769
User avatar
adafruit_support_bill
 
Posts: 29181
Joined: Sat Feb 07, 2009 9:11 am

Re: My Doctor Who MonoChron Clock

by odometer on Sat Feb 04, 2012 4:12 pm

What datatype is "hour"?

This is good up to 99:
Code: Select all | TOGGLE FULL SIZE
high_digit = 0;
low_digit = something;
if (low_digit >= 60) {high_digit += 6; low_digit -= 60;}
if (low_digit >= 30) {high_digit += 3; low_digit -= 30;}
if (low_digit >= 20) {high_digit += 2; low_digit -= 20;}
if (low_digit >= 10) {high_digit += 1; low_digit -= 10;}
odometer
 
Posts: 98
Joined: Sun Aug 21, 2011 10:01 pm

Re: My Doctor Who MonoChron Clock

by DanSlage on Sat Feb 04, 2012 5:11 pm

Nice Odometer! The datatype is uint8_t but never goes larger than 59 in my program. My gut tells me your code would be faster than mine. I wonder if anyone has ever done any speed trials.
DanSlage
 
Posts: 4
Joined: Thu Jan 26, 2012 3:29 pm

Re: My Doctor Who MonoChron Clock

by Nicodemus_NJ on Wed May 23, 2012 11:20 am

I hate to be "that guy" but... It's TARDIS! (Time and Relative Dimension in Space)

:)
Nicodemus_NJ
 
Posts: 1
Joined: Wed Apr 27, 2011 10:36 am

Re: My Doctor Who MonoChron Clock

by kscharf on Wed May 23, 2012 12:29 pm

DanSlage wrote:I am working on a Doctor Who inspired clock for the MonoChron. A video can be seen here. http://youtu.be/DHecR3Matss

My daughter plans on using this as her primary alarm clock once I figure out how to replace the alarm siren with the Doctor Who theme song.


Sounds like you need to interface a wave shield to the clock some how.
User avatar
kscharf
 
Posts: 185
Joined: Wed Sep 10, 2008 9:29 am

Re: My Doctor Who MonoChron Clock

by JakeS on Wed May 23, 2012 4:41 pm

Hi-

Saw your project featured in the Adafruit blog- nice!

We did a Dr. Who song through a piezo speaker an on Arduino. I used an existing program for the piezo frequencies and sound generation, which I have forgotten and can't attribute, sorry! We only figured out the melody and the timing.

Code: Select all | TOGGLE FULL SIZE
const int  b=     4056;    // 261 Hz
const int  c=     3830;    // 261 Hz
const int  d=     3400;    // 294 Hz
const int  e=     3038;    // 329 Hz
const int  f=     2864;    // 349 Hz
const int  g=     2550;    // 392 Hz
const int  a=     2272;    // 440 Hz
const int  B=     2028;    // 493 Hz
const int  C=     1912;    // 523 Hz
const int  D=     1700;    // 523 Hz
const int  E=     1508;    // 523 Hz
const int  F=     1432;    // 523 Hz
const int  G=     1278;    // 523 Hz
const int  A=     1136;    // 523 Hz
// Define a special note, 'R', to represent a rest
const int  R=     0;

int speakerOut = 13;

int melody[] = { b,  C,  B,  D,  a,  B,  B, g,  d,  b,  d, c, b,R } ;
int beats[]  = { 8,  8, 48,  8,  8, 64,  8, 8,  8,  8, 16, 16,16,96 } ;
int MAX_COUNT = 14; // Melody length, for looping.

// Set overall tempo
long tempo = 10000;
// Set length of pause between notes
int pause = 1000;
int rest_count = 100; //<-BLETCHEROUS HACK; See NOTES

for(int js=0; js<20; js++) {
   for (int i=0; i<MAX_COUNT; i++) {
    tone_ = melody[i];
    beat = 4*beats[i];

    duration = beat * tempo; // Set up timing

    playTone();
    // A pause between notes...
    delayMicroseconds(pause);
   }
}

void playTone() {
  long elapsed_time = 0;
  if (tone_ > 0) { // if this isn't a Rest beat, while the tone has
    //  played less long than 'duration', pulse speaker HIGH and LOW
    while (elapsed_time < duration) {

      digitalWrite(speakerOut,HIGH);
      delayMicroseconds(tone_ / 2);

      // DOWN
      digitalWrite(speakerOut, LOW);
      delayMicroseconds(tone_ / 2);

      // Keep track of how long we pulsed
      elapsed_time += (tone_);
    }
  }
  else { // Rest beat; loop times delay
    for (int j = 0; j < rest_count; j++) { // See NOTE on rest_count
      delayMicroseconds(duration); 
    }                               
  }                                 
}
JakeS
 
Posts: 10
Joined: Tue Feb 22, 2011 11:15 am

Re: My Doctor Who MonoChron Clock

by adafruit on Thu May 24, 2012 5:31 pm

I second using the piezo to just play the theme, it sounds good on Tesla coils so a piezo should be fine too :)
User avatar
adafruit
 
Posts: 11671
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

Re: My Doctor Who MonoChron Clock

by richteel on Sat Feb 15, 2014 3:12 pm

JakeS,

I tried to run the posted code but it is incomplete. I was able to get it to run but it does not play anything recogizable. I suspect that there was a bit more left out of your code than I was able to quickly repair/replace.

Code: Select all | TOGGLE FULL SIZE
const int  b=     4056;    // 261 Hz
const int  c=     3830;    // 261 Hz
const int  d=     3400;    // 294 Hz
const int  e=     3038;    // 329 Hz
const int  f=     2864;    // 349 Hz
const int  g=     2550;    // 392 Hz
const int  a=     2272;    // 440 Hz
const int  B=     2028;    // 493 Hz
const int  C=     1912;    // 523 Hz
const int  D=     1700;    // 523 Hz
const int  E=     1508;    // 523 Hz
const int  F=     1432;    // 523 Hz
const int  G=     1278;    // 523 Hz
const int  A=     1136;    // 523 Hz
// Define a special note, 'R', to represent a rest
const int  R=     0;

int speakerOut = 9;

int melody[] = { b,  C,  B,  D,  a,  B,  B, g,  d,  b,  d, c, b,R } ;
int beats[]  = { 8,  8, 48,  8,  8, 64,  8, 8,  8,  8, 16, 16,16,96 } ;
int MAX_COUNT = 14; // Melody length, for looping.

// Set overall tempo
long tempo = 10000;
// Set length of pause between notes
int pause = 1000;
int rest_count = 100; //<-BLETCHEROUS HACK; See NOTES

int tone_=0;
int duration=0;

void setup() {
  pinMode(speakerOut, OUTPUT);
  drWhooTune();
}

void loop() {
}

void drWhooTune() {
  int beat=0;
 
  for(int js=0; js<20; js++) {
     for (int i=0; i<MAX_COUNT; i++) {
      tone_ = melody[i];
      beat = 4*beats[i];
 
      duration = beat * tempo; // Set up timing
 
      playTone();
      // A pause between notes...
      delayMicroseconds(pause);
     }
  }
}

void playTone() {
  long elapsed_time = 0;
  if (tone_ > 0) { // if this isn't a Rest beat, while the tone has
    //  played less long than 'duration', pulse speaker HIGH and LOW
    while (elapsed_time < duration) {

      digitalWrite(speakerOut,HIGH);
      delayMicroseconds(tone_ / 2);

      // DOWN
      digitalWrite(speakerOut, LOW);
      delayMicroseconds(tone_ / 2);

      // Keep track of how long we pulsed
      elapsed_time += (tone_);
    }
  }
  else { // Rest beat; loop times delay
    for (int j = 0; j < rest_count; j++) { // See NOTE on rest_count
      delayMicroseconds(duration); 
    }                               
  }                                 
}


This bit of code worked much better but still did not sound like anything from Doctor Who.

Code: Select all | TOGGLE FULL SIZE
/*
  Melody
 
 Plays a melody
 
 circuit:
 * 8-ohm speaker on digital pin 8
 
 created 21 Jan 2010
 modified 30 Aug 2011
 by Tom Igoe

This example code is in the public domain.
 
 http://arduino.cc/en/Tutorial/Tone
 
 */
#include "pitches.h"

#define spk_pin 9

// notes in the melody:
int melody[] = {NOTE_B3, NOTE_C4, NOTE_B3, NOTE_D4, NOTE_A4, NOTE_B3, NOTE_B3, NOTE_G4, NOTE_D4, NOTE_B3, NOTE_D4, NOTE_C4, NOTE_B3, 0};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {8, 8, 48, 8, 8, 64, 8, 8, 8, 8, 16, 16, 16, 96};

void setup() {
  pinMode(spk_pin, OUTPUT);
 
  // iterate over the notes of the melody:
  for (int thisNote = 0; thisNote < 8; thisNote++) {

    // to calculate the note duration, take one second
    // divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int noteDuration = 1000/noteDurations[thisNote];
    tone(spk_pin, melody[thisNote],noteDuration);

    // to distinguish the notes, set a minimum time between them.
    // the note's duration + 30% seems to work well:
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    // stop the tone playing:
    noTone(spk_pin);
  }
}

void loop() {
  // no need to repeat the melody.
}
richteel
 
Posts: 2
Joined: Fri Aug 31, 2012 10:04 pm

Re: My Doctor Who MonoChron Clock

by mulveyr on Sun Mar 02, 2014 5:16 pm

DanSlage wrote:I am working on a Doctor Who inspired clock for the MonoChron. A video can be seen here. http://youtu.be/DHecR3Matss

The TARDIS travels through an wiggly wormhole. Pressing a button or switch (except "Menu") will cause the TARDIS to dematerialize and rematerialize a moment later in a random spot. My daughter plans on using this as her primary alarm clock once I figure out how to replace the alarm siren with the Doctor Who theme song.

I had to rewrite the wormhole code a few times to get it fast enough render correctly. The GLCD.h drawing routines are way too slow instead the wormhole uses glcdDataWrite()s directly to draw everything.

To speed things up I also EXTERMINATEd all division and modulus operations. For example to separate the hour into a high digit and low digit:

Traditional

Code: Select all | TOGGLE FULL SIZE
high_digit = hour/10;
low_digit = hour%10;

I found this to be much faster

Code: Select all | TOGGLE FULL SIZE
high_digit = 0;
low_digit = hour;
while (low_digit >= 10) {  // Count tens
  high_digit++;
  low_digit -= 10;
}

When you have as much motion as this clock does every clock cycle counts.


Is there somewhere where we can download the compiled firmware? My son has a Monochron and would like to try the clock out.

Thanks!

- Rich
mulveyr
 
Posts: 12
Joined: Thu Dec 26, 2013 4:03 pm

Re: My Doctor Who MonoChron Clock

by DanSlage on Fri May 02, 2014 8:13 am

Sorry I haven't checked this thread in a while. My Doctor Who Monochron is still one of my favorite clocks. The laptop I used to program the clock broke but I will look through my backup files. If I can recover the code I will post it here.
DanSlage
 
Posts: 4
Joined: Thu Jan 26, 2012 3:29 pm