Time for a Hackathon

Summer 2017 Hackathon

Following the success of our first hackathon, Black Pepper held their second hackathon in June this year.

The idea is to take some time out from normal project work to try something different by building something new in a relatively short amount of time.

There were some early suggestions for hacks, and the topic emerged as "Time". In a "wibbly wobbly, timey wimey" way, this is perfectly reasonable.

Hacking a Quartz Clock

I wanted to do a hack that had a hardware component, and I also wanted to try programming an ESP2866 microcontroller using Lua.

The chosen project was to hack on a radio controlled clock, and convert it to use WiFi for time synchronisation.  Our building does a fairly good impression of a Faraday cage, so the radio controlled clocks need occasional trips to the window sill to synchronise.  If we connect to the WiFi network, we can use SNTP to fetch the time.

I was inspired by one particular clock. After the initial reset to the correct time, the second hand would stop moving.  I was fairly confident that some aspect of the control circuitry had failed, but not in a way that would affect my hack. This clock became the donor hardware.

Before the day of the hackathon I investigated the technique to drive the clock hands, and flashed the microcontroller with firmware including the required modules.

The day of the hackathon as time to dismantle, investigate and problem-solve. The tasks I foretold were:

  • Identify the coils for driving the hands
  • Identify sensor used to detect hands at 12 o'clock
  • Use ESP2866 microcontroller (has GPIO pins, ADC, WiFi, SNTP)
  • Connect using discrete components (diodes, resistors) on a breadboard
  • Gain some experience in writing Lua code

No User Serviceable Parts Inside

I started off by disassembling the clock.  The plastic front cover popped out, the hands were levered of the shafts, and the clock module was opened up.

Clock Internals

Opening the module resulted in a cascade of plastic cogs. Later assembly required careful analysis to work out their correct positioning.

I had a small accident with the drive shaft.  I discovered it had fallen on the floor after standing on it, and putting a 30° bend in it.  I spent some time straightening this enough to work.

The exposed internals were examined. The RF coil used for radio reception was quickly discarded.  A sensor (later identified as a photo-diode) was taped to the back of the module, and had a slot lined up with spokes on the drive cog for the second hand.

Moving the Second Hand

Driving the motor is achieved by a short pulse through the driver coil, with alternating polarities.  This is achieved by connecting to a pair of GPIO pins, and setting the output high on alternate pins.  To protect the micro-controller from back EMF from the coil, zenor diodes were used.

Although Lua does not have a class system, you can create a class-like object using metatables. As part of the hack, I explored this capability as I like to keep implementation details hidden.

I created a Motor class, with a step operation.

Motor = {}
Motor.__index = Motor

function Motor:create(tickPin, tockPin)
    gpio.mode(tickPin, gpio.OUTPUT)
    gpio.mode(tockPin, gpio.OUTPUT)
    local motor = {
        tickPin = tickPin,
        tockPin = tockPin,
        tick = false
    }
    setmetatable(motor, Motor)
    return motor
end

function Motor:step()
    self.tick = not self.tick
    local pin = self.tick and self.tickPin or self.tockPin
    gpio.serout(pin, gpio.HIGH, { 25000, 2500 }, 1, nil)
end

The second hand coil was connected to GPIO pins 1 and 2, and I was able to simply drive the second hand around using a repeating timer.

local seconds = Motor:create(1, 2)

tmr.create():alarm(1000, tmr.ALARM_AUTO, function() seconds:step() end)

I was pleasantly surprised by the way the Lua language allowed me to compartmentalise my code into manageable chunks using this approach.

It paid dividends when I later discovered that only one instance of gpio.serout() can be active at a time, and I was able to implement queuing of requests entirely within the Motor class.

Locating the Second Hand

I decided that the sensor I had found had to be some form of optical sensor, which meant that there had to be some form of illumination within the clock module.  Examination of the circuit board identified an LED which was in the right location.  With the sensor connected to the analog input, and a 1.5V battery and resistor on the LED, I could see levels change as the hand was stepped around.

I wrote a piece of code to sweep the second hand around, and print out the value of the analog input on each tick.  The pattern was very clear.  A single sweep around the clock is 60 ticks, and you have two short pulses of 2 ticks, and one long pulse of 5 ticks.

Second Hand Position

Presentation

On the following day, all teams were given a few minutes to describe their hack, what they had learnt, and what they had achieved.

I held up the twisted mass of wires, and demonstrated my ability to move both the minute and second hands, and that I could detect the rotation of the second hand.

Proof Of Concept

I felt I had largely achieved my aims during the hackathon.  I had programmatic control of the hands using Lua code on the microcontroller, and could read the sensor to detect the position of the second hand.

With this, I knew I could reset the second hand to 12 o'clock (spin round until it has just passed the longer pulse), connect to WiFi, use SNTP for the current time, and step it around.  Just a simple matter of coding.

The biggest unknown was how to detect the position of the hour and minute hands, so they could also be reset to 12 o'clock on startup.

Further Development

After the hackathon, I found myself contemplating various mechanisms by which the position of the minute and hour hand could be determined, and peering closely at the clock module.

In the end, I came up with the theory that the same sensor could also be used for the other hands.  The drive cogs were hidden from view, but could plausibly have spokes between to shadow the sensor in the same way as the second hand.

So I wrote some code to just spin the minute and hour hands around.  I saw the output of the sensor did vary, so plotted the number of ticks the output was high/low for.

A similar pattern to that seen for the second hand was observed.  I deduced that the drive shafts had the same 2 thin, 1 thick spoke on it.  A full rotation of the minute hand is 360 steps.  The minute hand would create pulses of 8 or 9 steps from the thin spoke, and 28 or 29 steps from the thick spoke.  The hour hand would create a pulse of 370 steps from the thick spoke, and the thin spoke creates a pulse of 141 or 111 steps (in combination with the minute hand spoke).

Hour And Minute Hands

With this information I was able to reset all hands to 12 o'clock.  I start off by stepping both hands together.  When I have seen a pulse of 5 steps, the second hand is stopped.  When I see I pulse of more than 360 steps the hour hand is approaching the top.  Finally, when I see a pulse of more than 27 steps the minute hand is stopped.

I realise now that I was lucky the minute and hour hands were not obscuring the sensor when trying to locate the second hand.  I wouldn't have known that, and incorrectly concluded I was unable to read the sensor.

I don't actually know that my definition of 12 o'clock is the same as it was from the factory, but I simply re-attached the hands in the ‘correct’ position.

I also took the opportunity to transfer the jumble of wires from the breadboard to a piece of veroboard, and assemble the clock properly.

Veroboard

What's the Time?

The code to connect to a WiFi network and fetch the time using SNTP was simple.  The microcontroller has a RTC library, so once the time has been set, it will maintain the current time.

The main operation is just to wake up 10 times a second, and calculate where the hands should be based on the current time, and where they currently are.  On initial time acquisition, the hands spin round at 10 times speed to the current time, and the second hand tick is smooth during normal operation.

Another piece of code did the UK daylight savings calculation.  If I'd stayed awake this Autumn, I'd have seen the clock spin forward 11 hours when the clocks changed from 2am to 1am.

To Do

At the moment, the clock has hardwired values for the WiFi network, and the SNTP server.  I'd like to add a configuration mode where an Ad-Hoc WiFi network is created, and a simple web page for entering these values is available.  This configuration mode would be launched on first run, or if the button is held on.

I'd like to see if the photo-diode can be read using a digital input, which would simplify the code and the wiring.

I need to add some documentation with circuit diagrams, and a list of the pins used.

The code is available in a public Git repository, gitlab.com/nwholloway/wen-clock.  I called it the "Wen Clock" after Wen the Eternally Surprised, from the "Thief of Time" by Terry Pratchett.

Black Pepper Software Ltd, Warwick House, 32 Clarendon Street, Leamington Spa, Warwickshire. CV32 4PG
© 2017 Black Pepper Software. Registered in England & Wales No. 03763392. VAT No. 747849768.