Steam Clock code

    November 11th, 2009

    As promised, here is the steam clock source code.

    It uses two non-standard Arduino libraries:

    1. Stepper – with half-stepping
    2. DateTime – a software clock

    The code is pretty straightforward. move() does most of the stepper work. hour() and minute() do the minimal calculation needed to point at the right places on the dial. minute() is used for seconds as well. wiggle() bounces the needle around the current point. Its fun to look at and makes a nice noise.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    
    #include <DateTime.h>
    #include <Stepper.h>
     
    #define TIME_MSG_LEN  11   // time sync to PC is HEADER and unix time_t as ten ascii digits
    #define TIME_HEADER  't'   // Header tag for serial time sync message
    #define TZ 8               // How many hours off of GMT are you?
     
    Stepper s(200, 4,5,6,7, 1);  // Stepper is on pins 4, 5, 6, 7.  Using the enhanced Stepper library with half-stepping.
     
    int p = 0;
     
    void setup() {
      Serial.begin(9600);
      Serial.println("Steam Clock 0.8");
     
      DateTime.sync(10000000);  // Needs to come from RTC.
     
      pinMode(2, INPUT);  // home sensor
      pinMode(3, OUTPUT); // home ir led
     
      find_home();
      allminutes();
      allhours();
      bouncehome();
    }
     
    void find_home() {
      digitalWrite(3, HIGH);  // turn on LED
      digitalWrite(2, HIGH);  // turn on pull-up for sensor
     
      for(int i=0; i < 900; i++) {
        s.step(1);
        delay(25);
        if(digitalRead(2)) {
           Serial.println("Home!!!");
            p = 0;
           break;
         }
       }
     
       digitalWrite(3, LOW);  // turn off LED
       digitalWrite(2, LOW);  // turn off pull-up.
    }
     
    void allminutes() {
      for(int t=0;t<=60;t++) {
        minute(t);
        delay(500);
        if(t % 10 == 0) {
          wiggle(20);
          delay(500);
        } 
      }
    }
     
    void allhours() {
      for(int t=0;t<=24;t++) {
         hour(t);
         delay(500);
      } 
    }
     
    void bouncehome() {
       minute(0);
       wiggle(100); 
    }
     
    void move(int to,int speed) {
      s.setSpeed(speed);
      if(to != p) {
        int steps = to - p;
        s.step(steps);
        p += steps;
      }
    }
     
    void wiggle(int i) {
      s.setSpeed(200);
      for(; i > 1; i -= 5){
         s.step(i);
         s.step(-i);
         s.step(-i);
         s.step(i);
      }  
    }
     
    void hour(int h) {
    //  move((int)(h * 2.125), 200);  // this shoulnd't be a float...
      move((int)(h * 2), 200);  // oh, 2 seems to work better anyway. yay!
    }
     
    void minute(int m) {
      move(400 - (m * 4), 200);
    }
     
    void getPCtime() {
      // if time available from serial port, sync the DateTime library
      while(Serial.available() >=  TIME_MSG_LEN ){  // time message
        if( Serial.read() == TIME_HEADER ) {        
          time_t pctime = 0;
          for(int i=0; i < TIME_MSG_LEN -1; i++){   
            char c= Serial.read();          
            if( c >= '0' && c <= '9')   
              pctime = (10 * pctime) + (c - '0') ; // convert digits to a number            
          }   
          DateTime.sync(pctime - (TZ * 60 * 60));   // Sync DateTime clock to the time received on the serial port
        }  
      }
    }
     
    void debugOutput() {
      Serial.print('t');
      Serial.println(DateTime.now()); 
     
      Serial.print(DateTime.Hour, DEC);
      Serial.print(':');
      Serial.print(DateTime.Minute, DEC);
      Serial.print(':');
      Serial.println(DateTime.Second, DEC);
     
      Serial.print(DateTime.Day, DEC);
      Serial.print('/');
      Serial.print(DateTime.Month, DEC);
      Serial.print('/');
      Serial.println(DateTime.Year, DEC);
    }
     
    void loop() {
      getPCtime();
      debugOutput();
     
      DateTime.available();
      hour(DateTime.Hour);
      wiggle(20);
      delay(2000);
     
      DateTime.available();
      minute(DateTime.Minute);
      wiggle(20);
      delay(2000);
     
      DateTime.available();
      minute(DateTime.Second);
     
      DateTime.available();
      if(DateTime.Second < 50) {
         move(400 - ((DateTime.Second + 10) * 4), 1);
      } else {
         move(400 - ((60) * 4), 1);
      }
    }

    Steam Clock

    November 10th, 2009

    I picked up an old pressure gauge from my local reclaimed building hardware co-op (RE-store!).  I’ve had it for several months with the idea to replace the guts with a stepper motor to allow microcontroller control of the needle.  In the end it has turned into a clock!

    Steam Clock brass core

    This is the ‘core’ of the meter.  It originally had a pressure tube meter movement thing hanging off it.  I remove that part and drilled out the copper body to more easily handle power wires.

    Stepper motor mount.

    Where the meter movement itself went now needed to go a stepper motor.  This aluminum plate holds the motor.  The plate is made of aluminum salvaged from a CommutaCar charger case.  The standoffs are from the voice coil assembly of an old hard drive.

    Stepper motor clearance!

    This is the stepper motor itself.

    Stepper and 'home' sensor.

    This is the stepper motor mounted and the ‘home’ sensor added.

    Movement!

    This then is the whole working clock.

    Clock components:

    1. Meter movement itself.  (lower left)
    2. Arduino.  (upper right)
    3. Darlington motor driver. (middle)
    4. Home sensor.  (under clock face)
    5. Power supply.  (on the left)
    6. Real time clock.  (not pictured)

    Many of the parts were ‘rescued’ from old hardware.  The stepper motor is from an old HP DLT tape drive (each of these drives have 3 steppers in them!  Plus a bunch of bearings and a brushless motor).  The Home sensor is an IR beam-break (what are those called anyway?) detector.  Both its LED and detector are directly connected to the AVR.  They are turned on for calibration and then turned back off.  The Darlington driver chip was in my junk box.  It just provides more current handling than the AVR can do on its own.  The real time clock and power supply will be new parts.

    When complete the guts will all fit behind the clock face.  The arduino will be replaced with a ‘naked’ ATMEGA168 (probably, or a mega8 if the code will fit).  The power supply will be swapped out for another regulator since the one on the breadboard doesn’t work very well (it has an overly sensitive PTC thingy that likes to shut it down for no reason).  I don’t have the real time clock yet, but it will be a self-contained clock chip with a backup battery.  Probably a DS1307.

    The arduino code uses two libraries: Stepper, to run the motor, and DateTime, which is used to keep the time.  When the RTC is added it will be used to ‘seed’ the DateTime with the real time every once in a while (hourly?).  I’m guessing the clock will keep better time than the arduino, thus the desire to resync every once in a while.

    The next post will include code!

    Lacking in Performoodles.

    April 13th, 2009

    So as some of you know I work at a company that deals with satellite data services on aircraft.  These services are both slow and expensive.  So trying to use them is actually an act of trying to avoid using them…if that makes any sense.  Also, to complicate things, the company I work for is related to, and gets proceeds from, the amount of bandwidth used.  So we both want to use as much bandwidth as possible, but also to use a little as possible.  ugh.

    One of our soon-to-be products is an inflight internet service.  This provides a mostly transparent connection for the passenger’s laptop or the IFE screen in the seat.

    The connection we are using for this service provides 492kbps maximum.  On the surface, that doesn’t seem too bad.  It’s 4 ISDN lines.  Or half a 1MB DSL/Cable modem.  And it’s like 8 56k modems!

    But.

    The latency is killer.  The satellites are in Geosynchronous orbit.  Thats 22,000 miles away.  And 22,000 miles back.  And then, the data lands at one of three ground stations, none of which are in very good locations, so there is a several thousand mile trip over fiber back to my companies data center.  Ugh.

    That all adds up to between 0.9 and 3 (usually about 1.5) seconds of latency for a round trip.  Ugh^2.

    So that means that any time you ask the ground for something, there is at least 2 seconds before you are going to START getting a response.  The ground won’t even know you asked the question for almost a second!

    Of course, it’s actually worse than that.

    What if you ask the question over TCP?  TCP takes 1.5 round trips to even being transferring data.  Ugh.

    Then, of course, TCP is very bad at making efficient use of long latency links (known as ‘long fat pipes’).  TCP generally starts a new connection slowly, so as to not immediately fill it up and risk packet loss.  This is called Slow Start, and is a form of Congestion Avoidance.  It works by waiting for the first several packets to be ACKed by the receiving side before speeding up the transmit rate.  Once the expected ACKs stop coming, the sending side knows what the link capacity is and will slow down a little to fit.  This works very well for short pipes with low latency.  However, since we have such a long latency, and packet loss is actually rather rare, this is an extremely inefficient way to go about things.  If the response data set is small, the connection will in fact never make it out of the Slow Start phase.  This is because by the time the ACKs which would allow the sender to start sending faster get there all the data is already in the pipe.  What could have been a very short 400kbps burst turns into a 1 second long 10kbps dribble.

    Then we have DNS.  Before a TCP connection can even be established, you have to do a DNS lookup to turn ‘www.google.com’ into ’74.125.53.104′.  DNS lookups take about 3 seconds.  Thank god they are cached.  But still.  Ugh.

    So here are some load times for web sites over this satellite link.

    These times were collected using a perl script I wrote for the purpose.  I was unable to find any preexisting tools worth a damn.  The tool emulates a sort of worse-case situation: no cache, full page load from scratch.  However, the script will make use of keep-alives if the server supports them.  And it can make use of a proxy server to avoid the DNS delay.

    Fun page load times over satellite!

    For comparison here is a bunch of web sites loaded by the same script over 786k ADSL.

    Some web page load times over ADSL

    Plumbing

    April 5th, 2009

    Somewhere along the line this last winter the pipe leading to my back yard faucet burst.  I woke up at 2am or so and fumbled around in the dark trying to figure out where the running water noise was coming from and how to turn it off.   Afterwards i went back to bed.

    This morning I woke up again and decided to fix the pipe so that I could put new water in my hot tub.

    This is the pipe, next to the pipe i cut to replace it:

    Bursty!

    Unfortunately, after soldering this new pipe in place, it became apparent that the valve nearby was also damaged.  Upon disassembly the inner workings pretty much fell apart, as the ice had broken them all up.  So after lots more poking around and some splashing and a trip to the pumbing store, I once again had a working faucet!  yay!

    After that little adventure, I commenced the long slow tub draining exercise.

    Draining Hot Tub.

    This part is still ongoing, as it (and the one leading to the street) is a very small hose trying to drain a very large hot tub.

    Trivet Light

    March 30th, 2009

    One of my favorite places to visit often is the Ballard ReStore.  It is a reclaimed building supply place.  A non-profit.  And they also do a good job of passing on some of the odder things found when pulling down old buildings.  They will at times have old meters or photography or lab equipment in addition to the windows and doors and cabinets and other more normal stuff.

    Anyway, one of the sort of interesting things they had when i was walking through a while back was plastic bathroom tile.  These are 4″ square slightly translucent swirled plastic tiles.  I wondered if LEDs would look interesting shining through them.  So I bought 4 of them.  This is another nice thing about this place, the boxes are generally all open.

    IMG_2565.JPG

    So I took two of these tiles and framed them with some random wood i scrounged from my back yard and made a sort of trivet out of them as you can see on the right.

    Then I took some tricolor LED modules I had and an ATTiny85 and some FETs and added some internal lighting.

    This was my first time playing with an ATTiny, and my first time actually ‘producing’–as opposed to breadboarding–an AVR based device.  I used an annoying prototyping method I had seen mentioned on the web.  I will never try that again.  Ick.  Anyway, here is the board

    Trivetlight all soldered up. And here is the back of the board Solder side. showing the insane prototyping method involving enameled magnet wire.

    It works.  I would like to add some batteries and an inductive power pickup to it so the power cord could be hidden under the table.  Also the plastic tiles are somewhat too opaque, so something clearer would be better.

    Sigrun Radio 1500

    March 29th, 2009

    This is Sigrun Radio 1500.  A micropower High Fidelity AM brodcast I sometimes turn on to send music to my tube radio (which you can see at left).  Some day I will build a proper antenna for it and set it up to broadcast around the clock.  But at the moment the signal dies halfway down my driveway, so there isn’t much point.

    Big Pool Lamp

    March 29th, 2009

    IMG_2607.JPG

    So this was at the ReStore today.  It is 12V at 300Watts.  What should I do with it?

    AVR Synthesizer

    March 29th, 2009

    So there are a couple AVR based synthesizers out there already.  But they are all either written in (ew) ASM or want to talk to SID chips (don’t own one) or are otherwise not interesting.

    IMG_2605.JPG So a couple months ago I got one of the AVR Pocket Piano shields from Critter and Guitari.  This is an entertaining little Arduino shield with 25 buttons, three sampled pots, a volume control, an LED, and a microchip 12-bit DAC.  There are a few firmwares around to help the thing make some interesting (or not) sounds.   However they are all quite limited.  And interest in the thing seems to have deteriorated.  I took the (to me) most interesting firmware, a monophonic 1 operator DDS FM synthesizer and promoted it to three voices.  However, only having three pots was cramping my ‘creativity’, so I needed to find something else.

    IMG_2602.JPG IMG_2603.JPG Then a couple weeks ago I saw mention of the newish KORG nanoKONTROLER series. These are very small usb-midi controllers. There are three: a keyboard, a controller, and a drum pad. I went into Guitar Center to look at the keyboard and ended up walking out $120 poorer with both it and the controller. The included software from KORG sucked but was good for one evening’s entertainment. Then getting the linux synths like bristol kept me entertained for a few evenings more.

    But then I was bored again.

    So what to do?

    If A is fun, and B is fun, then A+B must be superfun! So I ended up with this pile of USB cables, some perl, and some more changes to the FM AVR code.  And ended up with this thing:

    IMG_2600.JPG

    Due to the extra controls, I was able to add a second FM operator and an LFO.  So you have three ‘true’ sounds to play with, plus the LFO.

    Like so:

    1. ‘carrier’ frequency.  This is the key you hit and the setting of Slider 1.  Slider one is the pitch of the whole keyboard.
    2. FM Modulator One. This is controlled by Slider and Knob 2 on the controller.  The slider is the amount of modulation, the knob is the frequency relative to the note being played.
    3. FM Modulator Two.  Same as above.
    4. PLUS the LFO goes just into the audible range if you bump it up that high.  It is controlled by Slider and Knob 9.

    Whew.

    To make this simpler I went back to the original monophonic FM code.  At some point I will probably try to add back a second or third voice.  Though given the extra processing required for the second operator and the LFO, i’m not sure there is time available.

    The AVR speaks a very limited dialect of MIDI.  I use a small perl program to shuffle midi data from the ALSA midi inputs (the AVR can’t talk straight to the USB midi devices, of course) to the AVR and also print out its console.

    First Prost!

    March 29th, 2009

    Yes indeed, yet another blog which will never be updated ever again.

    Looking for something?

    Use the form below to search the site:

    Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

    Visit our friends!

    A few highly recommended friends...

    Archives

    All entries, chronologically...