Alastair Barber

Harry Potter Weasley Clock

2020 Update - Much of the code and recommendations in this post will be well out of date! But I’ve kept it up as inspiration.

Harry Potter Weasley Clock

For Christmas, I decided to attempt to make magic as real as I could using the wonder that is electronics, programming and determination. I set out to make a ‘Weasley’ clock. For those who don’t know, this is a magical device that lives in the Weasley household, however instead of displaying the time, it displays the whereabouts of each family member by pointing a named hand at a defined location such as ‘school, travelling, magic-ville etc’. My version has only one hand and that points to six different locations and consists of a Raspberry Pi, USB Mobile Broadband Modem, Arduino, ‘Servo’ Motor, Some Microswitches and more Pritt Stick than I’d like.

There were many quite drastic changes throughout the build process and as a pretty fixed deadline (christmas) so please accept that the solution I came up with may not be as elegant as possible - and I wouldn’t recommend anyone copy the code/circuits presented here verbatim for anything, but rather use it as a guide and a way of saving yourself the trouble of learning some things the hard way…

Requirements

The device has to work as if by magic. Therefore, apart from power, there could be no external connections to other devices (no Ethernet) and also without any configuration whatsover (no WiFi). It also had to be portable and not require much maintenance. Naturally, I couldn’t actually figure out how to make it really magical - so in order to know where I am - the clock looks up my location over the internet (that I update with a phone app or web interface) and positions the hand accordingly. Discounting WiFi and ethernet meant that GPRS or Mobile broadband was the way to go.

Design

It is possible to purchase GPRS modems that are compatible directly with an Arduino or PIC interface that would’ve done the job well, however the cost for such devices was always around £40 for a device to be sent from Hong Kong / China, taking time I simply didn’t have. The solution was clear - a Raspberry Pi (which I already had) and a second hand USB mobile broadband stick which I picked up on Tottenham Court Road for £8. This coupled with a pre-pay data plan should hopefully have the connection problem solved. The next stage was figuring out the hardware, and in particular some way of moving a hand to a precise location around an entire 360 degree rotation, and finally bringing it all together (hardware and software) into something that resembled a clock.

Step 1 - An Internet Connected LED

Basic Layout of the System The RPi GPIO Librarires provide a good way of accessing the GPIO poins on the Raspberry Pi 2020: Use gpiozero instead and use the code on their website There are other ways such as wiringpi for those familiar with Ardunio and C++.

wvdial

Although the Raspberry Pi has the drivers already for a huge number of USB mobile broadband modems - the E160 included, Linux actually needs to know what to do with it! That is, what to dial, what information to send, and how to establish a connection. A great utility for doing nearly all of this is wvdial. This, when used with the pppd, will establish a working GPRS connection as a network interface. When the Pi first came out - getting this working was a bit of a nightmare, however now things have vastly improved. I’ll post some information about how I got it all connected shortly - but there are some excellent tutorials on this a quick Google search away!

The above script will do nothing other than light up the LED as connected in the configuration shown in the image above. If we’d like to control it remotely, there are two options, either someone of something pushes a command to the RPi, or the RPi pulls this comand from somwhere.

Push Commands

This would certainly be the most efficient way to control the LED. All we’d need to do would be to set up a server on the RPi and have it wait for something to connect and tell it what to do. Unfortunately, that last bit was the hard part with the current set-up. Whilst the USB modem reported an IP address to the Raspberry Pi, it turns out that it may not be the only thing with that address. Some research confirms that phone networks do tend to use NAT (similar to that on a home modem - except you can’t configure it!) to share out one address between multiple devices. Another way could be to have the RPi make a connection to a server somewhere and that server keep the socket open, but I didn’t want to set up a dedicated VPS somewhere in order to do this (my webhost would, understandably, not support this).

I also originally planned on having the Pi listen out for SSH connections and setting up a dynamic dns daemon on it so I could connect to it remotely. Unfortunately the situation with NAT rules this out too, which is a pain.

Pull Commands

This is the method I ended up using for all of the communications with the clock. The idea is that every minute, the RPi polls a web server for a file, and depending on the contents of said file, the light is turned off or on. This is simple as it only requires a few lines of Python code, however has the downside of requiring additional traffic which will mean more expense from the point of view of network traffic and data usage.

Step 2 - Making Stuff Move

First go at stepper motor control

Initially, I decided that a stepper motor would be the best choice for the project. I needed something that could rotate through a full 360 degrees in a constant direction (clockwise) and that I could control the speed and position of the spindle. Stepper motors are controlled by sending pulses of varying duration to the motor in order to control the angle of rotation. Check out the wikipedia page for more info about how they work.

The essential part of controling a stepper is the timing of the signal. Knowing this, I was unsure about whether or not the RPi would be suitable for this task as given that it’s running the whole linux operating system it isn’t really a real-time system, so timings might not be too accurate. Either way, I tried attaching the stepper motor’s driver board to the GPIO pins on the RPi and pulsing them in the same way the example Arduino sketch supplied with the motor did. Everything seemed to work perfectly, so I sat back and had myself an enjoyable Club Mate at the London Hackspace, where I did pretty much all of the work on the project after moving to the capital.

I was starting then to work out how to get the pointer to move to the correct part of the clock - however I wanted to be sure that the motor wasn’t drifting, so I set it off to do 100 rotations, came back, and, ah. Turns out it was drifting, and by quite a lot (about 20-30 degrees). So no good. I assumed this must be the timing problem, so tried again using just an Arduino, but no luck! I was using a very cheap stepper motor, but with no dedicated driver circuit to handle accel/decelleration, missed steps and the like. One of the ICs alone would’ve cost more than the motor, and good quality NEMA motors themselves also cost about £15, and are too large for what I wanted. I also didn’t like how the whole system was ‘open-loop’, with no feadback on the position of the motor shaft. Basically, what I needed was a servo. A 360 degree servo? Why yes, it turns out such things exist! Except it wasn’t quite what I was expecting.

I ordered a ‘Full Rotation Servo’ without properly reading the datasheet or understanding what it does. It’s not actually a servo in the traditional sense as far as I can tell, the only thing that you can control is the speed of rotation. I spent a while thinking about how to resolve this issue and decided that the best way forward would be to somehow add feedback to the motor. I had thought about using some kind of rotary encoder but these can be very expensive and would’ve required a fair bit of mechanics. I happened to have a few micro-switches with rollers on the arms and using one of the ‘heads’ supplied with the servo I put together this hack:

Servo-Microswitch-Combined!

On the left is a ULN2003 control IC. This consists of several ‘Darlington Pairs’ and allow the Arduino to switch a higher current than it would be able to do so on its own. In the centre, an Arduino Duemillnova and at the right the stepper motor with a microswitch epoxy-ed on to the side. Every time one of the arms from the wheel passes over roller on the arm of the microswitch - it pulls an input on the arduino low. The Arduino counts these pulses and can hopefully work out how far the shaft has turned. I had to be careful to ‘debounce’ the signal coming in from the switch. ‘Bouncing’ happens when the mechanical contacts on a switch almost literally bounce off of one another, creating a noisy signal - shown on the right of the image below, instead of a nice clean one like that on the left:

Noisy-signal!

If the Arduino simply counts all of the pulses it receives, it’ll count all of the short ones in between the switch being pressed by the arm and then it springing back up! Despite having come across this countless times before it caught me out again and it took me a few minutes of wondering what was going on and worrying that I’d irreversably glued a broken switch to the side of the motor to figure out what’d happened. I’ll post the Arduino Sketch I used to solve this on the code page [TODO - Link]. I’ve since discovered the ‘bounce’ library that may solve this problem better than my quick and dirty code, so I’d recommend checking that out.

(By the way - I know that all this is possible with a Raspberry Pi on it’s own, but as I was really pressed for time I found it quicker and easier to prototype the software and electronics with the Arduino I already had)

Whilst this solution was all very well for rotating the arm around 60 ( = 360 / 6) degrees, it’s no good for being able to work out where the hand is. This could be solved by always remembering the last place it was moved to and then counting 60 degree rotations from then to move it to a new place, but, like the stepper motor, one click out and it’s never going to be back in the right place (by itself), and that’s assuming the counting method always works. I decided that the quickest, cheapest and simplest way to solve this was simply to glue another microswitch on the side of the first one and then extend one of the arms out so it only hit it once per revolution. Then, whenever a pulse is received from the second microswitch the Arduino knows it’s got round to the start - a fixed point of reference. The first iteration whilst I was testing it extended this arm with several bits of old credit card glued onto the arm. Needless to say, this was totally useless for anything more than testing (it fell off after 10 mins) - but it was great ok for prototyping. Here’s a video of it in action:

The final version of this mechanism does away with the naff bit of plastic and has a nice aluminium disk mounted flush on the hub of the wheel and a M6 bolt head in line with the second microswitch. Stupidly I didn’t get a photo of it - I could’ve sworn I had! Sorry :(

As you can see - there’s a Raspberry Pi with a prototyping plate hat I’ve used to break out the GPIO pins on the Pi. Seeing as I had developed all the code for driving the motor for the Arudino, the Raspberry Pi needs a way to send the data it retrieves from the internet to the Arduino. There are many ways of doing this and I chose probably the most ridiculous and quick and dirty one that’s probably never been seen before. A couple of things I didn’t want to do:

Given that the only data I was going to be sending would be a number between 1 and 6 and probably at the ver most every half an hour - I made my own protocol. It’s illustrated well in the video with the LEDs on the PiPlate - one line rises high and then an amount of pulses made on the other line. The Arduino counts these pulses and then starts the motor - waiting until the second microswitch is hit (12 o’clock) and then stops after counting this many pulses on the first switch input. This does mean that the hand always passes through 12 o’clock whenever it moves (so going from 1 to 11 means rotating almost 2 full rotations) - but I thought this an acceptable cost to almost guarantee that the hand will always be in the intended place.

In case you didn’t catch the video, here’s that last bit illustrated: Arduino - Raspberry Pi Communication

This works because the Arduino is capable of registering 3.3v signals as ‘logic high’ despite being run at 5v, although we can’t send signals back to the Pi. This is something I’d like to fix when it’s time to ‘upgrade’ the clock as it’d be very useful to know if the hand gets stuck or something. (I believe the Atmega328 will happily work at 3.3v - so might be simpler just to give it its own power supply).

Step 3 Code

This will be incredibly out of date!

It’s not elegant work but it gets the job done!

Raspberry Pi As I mentioned earlier - all the programming on the Raspberry Pi is done in Python. Sure - it has quite a serious overhead of being interpretted, especially on an embedded platform like the Pi, but in this situation it’s hardly a dealbreaker!

#! /usr/bin/python

import urllib2,time
import RPi.GPIO as GPIO

#Setup the GPIO pins on the RasPI
#Make 23 and 24 outputs

GPIO.setmode(GPIO.BOARD)
GPIO.setup(23,GPIO.OUT)
GPIO.setup(24,GPIO.OUT)

#Get the time, and make a URL. We use this so as to be sure that the result isn't
#cached somewhere.
timenow = str(time.clock())
urlstring = "http://www.a-barber.com/path/to/php-script.php/?rand="+timenow

#Request the URL - and see what the server says...
response = urllib2.urlopen(urlstring)
command = response.read()

#The server is responsible for determining if the clock has already
#gone to the position. If there's a position that hasn't been picked up
#already by the pi - then the response will be a number followed by 'N'

if 'N' in command:
	#Parse the number (1st char in string) to an integer.
	number = int(command[:,1])
	
	#0 is a valid position (0 steps along from when the 'full rotation' 
	#microswitch is hit) - so send the signal to the Arduino high outside
	# of the loop.
	
	GPIO.output(23, GPIO.HIGH)
	
	for i in range(number):
		#Output a short pulse (off -> on -> off) on the second
		#gpio pin...
		
		GPIO.output(24, GPIO.HIGH)
		
		sleep(0.5) #The timing is not important so this doesn't need to be too 
					# accurate. 
		
		GPIO.output(24, GPIO.LOW)
		
		sleep(0.5)
	#End of the loop 0 or more pulses have been sent...
	
	GPIO.output(23, GPIO.LOW)

#There was no 'N' in command if this has been reached without pulsing. End of the
#script!

Arduino

#include <servo.h>

Servo myservo;

int servo_power = 0;
int servo_pwm   = 1;

int sixth_rotation_in = 7;
int full_rotation_in  = 8;

int data_flag_in = 2;
int data_sig_in = 3;



int servo_speed = 86;
void setup()
{
  pinMode(servo_power,OUTPUT);
  pinMode(sixth_rotation_in,INPUT);
  pinMode(full_rotation_in, INPUT);
  
  pinMode(data_flag_in, INPUT);
  pinMode(data_sig_in, INPUT);
  
  digitalWrite(sixth_rotation_in,HIGH);
  digitalWrite(full_rotation_in,HIGH);
  
  myservo.attach(servo_pwm);
  myservo.write(86);
  

}
void loop()
{
 int stepstotake = getData();

 digitalWrite(servo_power,HIGH);  

  goToStart();
  countSteps(stepstotake);
  digitalWrite(servo_power,LOW);
  
}

void goToStart()
{
  while(1)
  {

    //Rotate the servo until we hit the full rotation
    if(digitalRead(full_rotation_in) == LOW)
    {
      //We've reached the point at the start of the rotation.
      //Now, we need to go one more click on the sixth_rotation before we start counting.
      //It could be that the sixth is pressed and we need to get off it, or we haven't quite reached it
      //and we need to get past it.
      //Serial.write("Full rotation low. \n");
      if(digitalRead(sixth_rotation_in) == HIGH) //We're not yet on it...
      {
        Serial.write("Sixth rotation high. \n");
        while(digitalRead(sixth_rotation_in) == HIGH) //Do nothing while we let it roll on
        {
          delay(50); //Debounce a bit
        }
      }
      if(digitalRead(sixth_rotation_in) == LOW) //Wer'e on it...
      {
            Serial.write("Sixth rotation low. \n");
        while(digitalRead(sixth_rotation_in) == LOW) //Do nothing while we roll off it
        {
          delay(50); //Likewise
        }
      }

       if(digitalRead(sixth_rotation_in) == LOW)
      { 
         Serial.write("Sixth rotation is still low...\n");
      }
      else
      {
         Serial.write("Sixth rotation is high... \n");
      }
 
        //That's all folks!
        return;
    }
  // Not even reached the full rotation yet. Keep on going!
  }
}

int getData()
{
 // Serial.write("Waiting for data...\n");
  while(digitalRead(data_flag_in) == LOW)
  {
    delay(10);
  }
  int dataCounter = 0;
  //Serial.write("Data flag... \n");
  while(digitalRead(data_flag_in) == HIGH)
  {
      while(digitalRead(data_sig_in) == LOW)
      {
        delay(10); 
        if(digitalRead(data_flag_in) == LOW) return dataCounter;
      }
      dataCounter++;
      //Serial.write("Signal... \n");
      while(digitalRead(data_sig_in) == HIGH)
      {
        delay(10);
        if(digitalRead(data_flag_in) == LOW) return dataCounter;
      }
  }
  //Serial.write("Data flag removed...");
  return dataCounter;
}


void countSteps(int steps)
{
  int counter = 0;
  myservo.write(servo_speed);
  while(counter < steps)
  {
      //While it's high do nothing 
       while(digitalRead(sixth_rotation_in) == HIGH)
       {
         delay(50);
       }
       //It went low! Wait for it to go high again...      
       //Now wait for it to go low again 
       counter++;
      
       while(digitalRead(sixth_rotation_in) == LOW)
        {
          delay(50);
        }
        // Now it's back high - that's one pulse! 
        
   }
   return;
}

Step 4: Putting it all together - circuits and glue

So, all the parts are made as a prototype. At this point I had about two days before I was skipping town to spend christmas with my family (as was my girlfriend) - so I needed to get this finished fast. Please forgive the lack of photos of the builds!

Putting together a circuit

I didn’t want to have to use up the Arduino shield to make this and decided to make the power supply, motor control circuit and Arduino circuit all on one piece of veroboard. This is another bit I don’t have a photo of :( - so here’s the circuit diagram: Circuit Diagram

That’s all there is to it really! Surrounding the voltage regulator is a chunky heatsink. This is mainly because the RasPi and GPRS dongle combined happily much through about 800 mA of power. Given that there’s a 2v drop across the regulator that (2 * 0.800) = 1.6w of power that’s being dissapated across it. On its own it will get incredibly hot, so a heatsink does a good job of bringing it down to a good temperature.

The last thing I took a picture of before finishing it and wrapping it all up was the many iterations of the clock face. Originally I was going to laser cut the dial out of MDF and print the design onto paper but there was just no time! It was back to good ol’ handwriting and drawing that saved the day!

Drawing the clock face

The body itself was an old chinese clock from a car-boot sale in Vauxhall. It was pretty beaten up and needed new feet. I removed the original mechanism (and sold it on eBay). I discovered that spray-paint is wonderful and made a nice heavy board backing for the face that hides some of the workings. In this photo you can just about see the circuit board that I made for the Arduino and motor driver.

Insides of the clock

And so that’s it! She got it on Christmas day and was working - checking in every minute with my webserver until the begining of February when it got moved next to a wall. Unfortunately the mobile broadband stick doesn’t seem to be able to pick up and maintain a solid connection there - and it’s location at the bottom right of the clock under the pi and pi-plate probably doesn’t help. Even worse, the Pi doesn’t know to try to reconnect if no connection is detected. I wrote a simple script to try and fix this but it’s not really helped much. Fortunately however, the mobile broadband stick contains a connection for an external antenna. I’m about to order one and install it when I’m next visiting, although maybe having a GSM antenna stuck out the back of it might take away from the magic - it’d be good to have it reliably working again!

The next step is to figure out a way of always getting it to update correctly, instead of trying to use the terrible webapp I made on my iPhone. Perhaps attaching a modem and arduino to my bag or car?!

Anyway - if you’ve got this far reading, thank you very much!

Again, massive thanks must go to the London Hackspace and its wonderful community for the inspiration and encouragement to go for it, and think of new ways to solve problems and setbacks.