Introduction: 'Weasley' Location Clock With 4 Hands
So, with a Raspberry Pi that had been kicking around for a while, I wanted to find a nice project that would allow me to make best use of it. I came across this great Instructable Build Your Own Weasley Location Clock by ppeters0502 and thought that it would be good to try.
The clock basically consists of a Raspberry Pi which controls servos in order to turn the hands of the clock. As in the house of the Weasley family in the Harry Potter books/films, each family member has their own hand. Each hand points to the current location of that family member. The clock achieves this by receiving messages from the mobile phones of the family whenever they enter or leave a pre-defined radius.
The main differences to the previous Instructable were that I needed to have 4 hands, not 2 (otherwise my daughters would have complained) and I decided to build the frame too, not get an old clock to reuse. This was because I was concerned that space would be a problem in an existing clock case, with the need to fit in 4 servos etc.
It took a lot longer than I anticipated, though mostly where I came across fiddly problems which stumped me, and which didn't seem to be covered by the original post. Nothing against the original Instructable, which was generally great, but some years had passed and versions of things changed... etc. Also, being in the UK meant that some of the Imperial/Metric elements caused more challenges than I expected.
Also, whilst I am OK at the coding, the physical making of the clock definitely stretched me, and required some additional tools, which also slowed me down somewhat.
At the end I'll include a section on "Things I would do differently/better if I were doing it again..."
One of the things that struck me was that the expensive components were to do with the hands of the clock. 4 hands is definitely way more expensive than 2. I decided to put in some costings so that you have some idea. This is the first time time I have added it all up, and disregarding the tools, I think I spent about £200. Plus some stuff I didn't use (and haven't included below) plus the Pi, plus the power supply both of which I had already.
- Raspberry Pi - can't remember how much it originally cost but it was a Model 2B. I think that if you don't already have one, then even a Pi Zero would probably do. I had added a wifi dongle and SD card with Raspbian. And I had an old Android phone charger lying around.
- Adafruit Servohat for the Pi - £16
- Power supply for the Servohat - This I really struggled to find as all websites just pointed to the adafruit site which then, obviously recommends a US power supply. Then I realised that I had an old variable voltage supply with interchangeable tips so I used that. But the US one is $8 so that's the ballpark.
- Case for the Pi, so that I could then attach it to the clock frame. £5
Servo's and gears
Here I'm quoting the price for all 4, so divide if you want fewer hands (Adding it up it is ~£40 PER HAND = £160 :-o
- 4 x Servos - I used the ones recommended by ppeters0502 - found on ebay for ~ £15 each = £60 - I searched for the following text "GWS-Digital-Servo-Sail-Winch-S125-1T-2BB-360-degree" but sometimes they were unavailable
- 4 x brass tubes which fitted exactly inside each other - ~ £3 each. I got 1 each of 1/4", 7/32", 3/16", 5/32" = £11
- 4 x clamps which clamp onto the brass tubes to allow you to attach gears. ~ £7 each = £28. I got them from ActiveRobots who do regular orders from Servocity in the US, allowing you to avoid the international shipping. They can also get anything else you can find on Servocity's main US site. This was very handy for the next 2 items
- 4 x acetyl 0.770" pattern gears for mounting on the clamping hubs. ~ £6 each = £24
- 4 x acetyl spline-mounted acetyl gears for mounting on the servos. ~ £6.50 each = £26
- 1 x pack of hex nuts to attached gears to clamping nuts = £2.60
- 1 x 7/64" hex key (allen key) because anything coming from the US is imperial, so the hundreds of allen keys I already have are useless = £1
For the Physical build
Here I mostly used offcuts of stuff I had lying about
- 2 x squares of plywood for the 'face' and 'back' plate
- I then cut 4x10cm cylinders off an old banister rail I had, in order to connect the back to the face
- Some blocks to mount the servos at the correct offset - just softwood offcuts that I cut to size.
- Assorted screws. from very small (to attach Pi case to frame) to medium (to attach frame together)
- 0.75mm sheet of mild steel about 50cm x 20cm (to cut the hands out of). This was the only thing I bought ~£9 from Wickes
Some things I had and some I borrowed or bought
- Soldering Iron + electrical solder - for attaching the connectors to the Adafruit Hat & Pi.
- Jigsaw - for cutting out the rough shape of the hands
- Drill. just a normal cordless 18V drill
- Drill bits - Bear in mind that you WILL need imperial drill bits to make holes which match the brass tubes. I managed to borrow some.
- hacksaw - for cutting the brass tubes. Don't do what I did and spend £3 on the tube cutter, it works by pressure and means the interior of the tubes gets a bit smaller. so the next-size-down tube does not then fit through
- Bench grinder - I didn't have one of these but a friend did and it made shaping the hands MUCH easier. Until then I was just using files. I wouldn't buy one just for this project, but for the metal hands it was great.
- I bought some assorted diamond point files (very small). useful for the hands and tubes around £15
- rough and smooth sandpaper
- some small clamps hold things in place when drilling.
- a vice for the same reason.
Step 1: Setting Up Your Phones to Send Their Location to Your Pi (Part I MQTT Broker)
This bit is described very well by ppeters0502 in his excellent Weasley Clock Instructable. Oddly, though maybe reflecting differing skillsets, he started with the build and then moved to the software, I did it the other way round. So, I started with the phone... hang on, no I didn't, I started with the MQTT broker, which is Step 6 in his Instructable. I will omit all the bits that he does very well and just throw in some bits that I might add. I went the CloudMQTT route that he mentioned.
as I was writing this, I checked the link to the plans and found that there is no longer a free plan! They withdrew it, for what seems like reasonable grounds. i.e. that people would set up a free instance and then never use it. I didn't notice because current instances can continue. So I won't change. But it does make the instructions a bit redundant. There seem to be 3 options.
- Pay the $5 per month for Cloud MQTT (but that sounds pricey for the clock on an ongoing basis).
- Go the Mosquitto on Pi route as described in the first Instructable. I can't comment on that, but could be a good option.
- Just google "free MQTT cloud broker" and it looks like there are some others.
So, on the assumption that you have a working MQTT broker, if it is anything like the CloudMQTT one then there will be a Server, User, Password and Port displayed. You will need all of these for setting up your phones to send the broker your locations/movements.
Cloud MQTT decided not to even let existing free instances continue, which is perfectly reasonable as they need to make money, but it does mean that the clock stopped working. SO.... I know need to do something else. I looked on the web and found HiveMQ which seems free, and set up an instance there. It's a bit different to CloudMQ and my phones and Node Red initially refused to connect to it. Phones did nothing and Node Red hung on a connecting mode. I eventually found a thread here which suggested doing an upgrade of Node Red. Also I found something stating that you MUST enable TLS. you can see in these 3 screenshots me trying to connect one of the purple Node Red 'MQTT in' nodes to a testTopic on the HiveMQ broker. From the first image I clicked the pencil icon to edit HiveMQ Broker. Then on the second image I have replaced most of the address with ???? but enabled the TLS option. But then editing the TLS option is the third image and shows that there is nothing needed there. This seems to have connected. As does my phone. So now I just need to match the topic to my original topic.
Step 2: Setting Up Your Phones to Send Their Location to Your Pi (Part II Owntracks)
This is also covered very well in the original Instructable, in Steps 7 (Android), 8 (iOS) & 9 (setting up Regions).
I only had iOS devices so didn't try step 7.
What would I add to those instructions?
- In the set-up there are also the fields TrackerID and DeviceID. These you should have as being able to identify you within your family. E.g. I had them as R and RPhone respectively. This means that you can pass through to the clock which Servo and therefore which hand to turn.
- Regions are the name for the locations which you want to track.
- Each region is defined by a Name, a Latitude, a Longitude and a Radius.
- Because I wanted to have a number of locations as one section on my Clock, I used a naming convention, which turned out to be very useful. Other methods are possible but this worked for me.
- For example, For the FAMILY section of the clock I wanted to have my parents and siblings and my wife's parents and siblings. Therefore I had locations like "Family Tom", "Family Dick", Family Harry" & "Family ParentsR". This meant that the next stage could know what to pass to the Clock.
- Bear in mind that people can have different locations. But as long as they are consistent with the naming convention then that's fine. E.g. my work would be different from my wife's work region and called differently. but as long as they both start "Work" then all is fine.
- You want the mode set to 'Significant' on the Maps screen. This means that you (mostly) only get messages when you enter or leave regions. This seems to be the updated version of the note marked IMPORTANT: at the end of Step 8 in the original Instructable.
- As mentioned in the original Instructable, using Google Maps is a great way of finding out the Lat/Long of somewhere. I found it more efficient to do this in bulk, finding out all the Lat/Longs of my location, then I pasted them into Notes (on my Mac) and with the cloud sync-ing, it meant that they magically appeared on my iPhone in Notes and I could copy/paste them into Owntracks. It also meant that I could send the file to my family's phones and we all had consistent locations.
- Locations which are close together can cause problems. My brother lives 2 streets away, and initially my phone kept thinking that I was simultaneously in the region of his house as well as at home. Eventually I had to put additional logic into Node Red to catch and ignore this happening.
Step 3: Setting Up the Raspberry Pi
So here I am assuming that you have a base Pi set up and on wifi. I was running Raspbian but it shouldn't matter. Use instructions at raspberrypi.org to get it all set up.
Note that a Pi has ports for display to a monitor and keyboard/mouse etc. BUT obviously once you have it in the clock, you don't want any of that. So the answer, suggested by someone on the Raspberry pi website, I think, was to set up a VNC connection. This allows you to connect from another device to the Pi and control it as well. I do it from my Mac but have also done it from an iPad. I'd suggest using something with a keyboard for ease of use.
I just found that they seem to have made it easier since I connected... see here
Essentially you connect and get a window which is the standard Pi interface.
So, you have a window to your Pi from your laptop or computer.
Now you need to connect the Servos.
First you need to do some fairly basic soldering to get the adafruit hat onto the Pi. It's a little fiddly, but despite not having soldered for 30-odd years, it was fine. As ever, I found a useful YouTube video to walk me through it, which was a great help.
Whilst the hat can run 16 servos, I only needed 4 and so I only bothered soldering the first set of 4 pins.
Then the servos just push onto the pins. I did one first to check that I could actually get the servo to move.
This was where I hit my first major roadblock. I had a very basic python script to move the servos and literally nothing happened. I spent about a week trying new scripts etc, and then smoke started appearing on the hat. Switching everything off, I checked the schematic. It was a component which protects against reverse polarity. Because I had a multi-tip, multi-voltage power source, I had missed the fact that you could have the DC output going both ways by reversing the tip. I had got it wrong (50:50 chance) and just burned out my first adafruit hat
So a slight delay as I bought a new one, re-soldered and corrected the tip. MUCH better.
Next I needed to work out how to move the servos to the correct point on the clock. That will come in Step 5, but what I did do, having not built the actual clock, was to lightly screw the servos to a random bit of wood, and stick some masking tape with an arrow on them, as in the picture. This gave a very visual feedback to what I was coding.
Step 4: Installing Node Red (Getting the Messages From MQTT Server to Your Python Script)
- Have receiving nodes for the MQTT messages - these are light purple and I had 1 per family member
- Map that to the servo that you wish to move (numbered 0, 1, 2, 3)
- Determine whether you are entering or leaving a radius on OwnTracks
- Work out which location that servo needs to be pointing to
- There were some exceptions to the basic rules which I needed to build in.
- Set the angle correctly
I had Node-RED doing the first 4, and kept the Python relatively simple.
You can see the basic flow here, and all flows can be exported into the format here, which means that you can import this basic flow into your Node-RED and then adapt. Note that I have stripped out all the connections from the purple nodes so that you can't access my MQTT instance. I also stripped out all the test-nodes as they contain actual data... you may need to change this file type to be flows.json in order to import into your Node-RED but Instructables didn't let me upload that.
The green nodes are debugging nodes which then display output in the debug window on the right of the screen (may need expanding - find the arrow halfway up on the right)
The first bit to do is the "Live - for debugging only" bit. That checks that you can receive the MQTT messages and see what is in them. json is just a more structured version of the messages which allows you to get the data out more easily. In this flow, when live, I then connect the purple nodes top left to the json node to the right of them.
Once you know how the messages are going to look in live, it gets very boring to have to walk out of your house and down the road and back, just to trigger an event. Once you have done that, you can copy the message into a TEST trigger, and then just click it to simulate the event. You can also change the data, to pretend to be for different locations (make sure they correspond exactly to the location names in Owntracks).
You can see in the flow that the test cases all go into a separate node and then that goes into the json node. This is purely to tidy up the screen.
I can't emphasise enough how useful these nodes were, and still are.
So I then hit the next roadblock. This one took a LOT of googling in forums etc. My flow would work perfectly, but it wouldn't trigger my python script. I could not work this out, but I will spare you the swearing etc. Just to say that, as highlighted in the second screenshot, you must specify python3, as apparently Node-RED assumes python2, unless you specify.
2 additional complications - only if needed
I then had a number of challenges where the logic didn't quite work. First was that Owntracks went a bit weird and, as my brother lives 2 streets away, it often said that I was in 2 places at once, or kept switching between. The only way I could get round it was to add in a condition to stop false positives. If it claimed I was at his house, then I routed through and checked the actual Longitude/Latitude in the message and aborted it if it said I was actually at home.
The other problem was that, when walking my dog I couldn't really get a good radius. I usually walk in the same area, so here, I said "if I enter this area, I am definitely walking the dog, and will be until I get home." this meant that it wouldn't switch to the pub that I pass on the way home, or various other local places which could trigger whilst dog-walking. In order to do this I needed to set up some persistent Context variables (look them up on Node-RED. See screenshot. These variables persist until Node-RED is restarted and so I can say If on a dog walk, set the Context Variable to "Dog". Then ignore ANYTHING else unless I 'Enter' Home.
The last screenshot is the one of my actual final flow, with all the exceptions, just for your interest.
Step 5: Actually Moving Servos With Python on the Pi
- Import a few libraries
- move the variables coming from Node-RED to variables in the script
- maps the angles determined by the calibration script to the locations on the clock.
- check that the location is found in the list, and if not then move to "Peril"
- write out what was done to a log-file
- move the required servo to the required angle
- Stop one servo from 'buzzing' *
3 things to note.
The log-file is super useful for debugging. It means that you can look at the Node-RED debug of a message, and then see what happened in the script. the output looks like this. The first 3 are me taking the dog for a walk, and then Child 1 leaving the house and arriving at school. Note to check the time on the Pi. It may default to UTC and not allow for summer/winter time changes. E.g. the times below are 1 hour out.
2020-12-07_05:36:03 Who = 0, loc = Travelling, detail = Home, Angle = 10, index = 8
2020-12-07_05:36:04 Who = 0, loc = Dog, detail = Astons, Angle = 86.5, index = 10
2020-12-07_06:07:49 Who = 0, loc = Home, detail = entering, Angle = 75, index = 0
2020-12-07_06:23:53 Who = 2, loc = Travelling, detail = Home, Angle = 19, index = 8
2020-12-07_06:30:48 Who = 2, loc = School, detail = N, Angle = 60.5, index = 2
One of the Servos (0) kept buzzing after the end of the script. As you can imagine, this is super-annoying to have in our kitchen. I found a thread somewhere which mentioned setting the servo angle to 'none' which somehow sets it to be idle. That worked brilliantly and can be seen in the script at the end.
Bear in mind how low a hand takes to sweep round the clock. You can see in the script that there is a time.sleep(4) line just before we set the servo to stop buzzing. That's because you have to allow the hand to get to its destination before you set it to idle. Otherwise it just stops. This is also important when calibrating it, because you are doing multiple moves within the script. I would set it running to move to all 12 locations in turn, so that I could recheck them all. but you need a little time in between.
Step 6: Finalising the Software - Phones to Servos
Once you have the test bench and the scripts set up, then you can run it 'live' for a bit and see how it works in real time. This is where I found the exceptions which I needed to add into my Node-RED flow.
You can easily disconnect and connect family members in the Node-RED flow if you want to concentrate on one. For example, if two are causing problems but you want to fix one at a time. Otherwise, bear in mind that you will continue to receive messages from any connected phones.
I mentioned the problem with Dog-walking and my brother's house being quite close. I had 2 other challenges.
First, locations within other locations. My wife was doing a course at a college in London. We wanted that to register as 'School', but it is also in 'London'. So we needed to re-use the context to say that if you were leaving that 'School' then move to 'London' not 'Travelling'.
Second, race conditions. As mentioned, my brother's house is 2 streets away, and also near our favourite pub/restaurant. This means that sometimes 2 signals are received at the same time, or very close together. This can set up a 'race condition' where you get different outcomes depending on which gets through the logic quickest, leading to unpredictable outcomes. In order to counter this I made all 'entering' messages have a 1s delay in the logic, which seemed to fix the problem. There may be better, more elegant, ways to solve this, but it seemed to work.
Step 7: Building the Physical Clock - Part I - the Servos & Axle
- I got 2 large (~30cm) squares of plywood that I had lying around (about 9mm thick).
- Then I cut an old bannister rail into 4x10cm sections and screwed the front and backplates together.
- Having marked the centre hole, I drilled it to be the same size as the largest brass tube.
- Then I painted it with normal white gloss paint.
- After some experimentation I realised that I could probably not get 4 servos round the same axle if they were all attached to the back (or front) plate. So I needed to have either 3 + 1 or 2 + 2, on each plate. I ended up with 3 on the back and 1 on the front.
- I worked out the offsets required on a piece of paper and then cut the brass tubes to match. Note that the thickest tube is the shortest, and the thinnest must go all the way to the back plate. (I actually embedded the smallest one in a hole that I partially drilled in the back plate, but not all the way through so that the axle didn't move backwards).
- For the tubes, I bought a tube cutter, but that uses pressure to cut them and it means you can't get the smaller tube inside. So I used a hacksaw and then had to do a fair amount of filing to get them to work. Te diamond point-files were invaluable here.
- Then I matched the diagram to the actual offsets for the clamps and cogs *.
- Once I had the offsets, I knew how 'high' to make the blocks to mount the servos. I broke a couple of blocks by sawing them too thin and also drilling the hole to let the wire out.
- Then came the fiddly part of where to put the blocks so that they would exactly meet the cogs on the axle. I screwed in one block and then could rotate the servo to meet the axle and then screw in the second block the other end of the servo. I also found that I needed to cut a bit out of some blocks to avoid snagging other cogs. It took quite a while.
- Once I had all that done, I got my raspberry pi case, drilled two holes in it, and screwed it to the front plate. Then I could add the Pi in, close up the front and back plates (having connected the servos to the pi (remembering which servo was for which family member) and turn to the hands...
* Here I found the biggest problem, which I have yet to completely solve. The brass tubes were, 1/4", 7/32", 3/16", 5/32". But the clamps were metric (except one which was 1/4"). Converting the tubes to metric they were 6.35mm, 5.56mm, 4.76mm 3.97mm. The remaining clamps were 4mm, 5mm and 6mm bore. The smallest 2 and the largest are fine. but clearly the 0.44mm is too much travel for the clamp so I had to pad it out with paper. I have tried this a number of times and it works OK for a while and then loosens again. So the 2nd largest hand fails to work properly. It was fine for about 6 months though, so time spent doing this well was time well invested. But if I was doing it again I might have gone 1 size up or down, with a gap to try and get a better clamp to tube fit. e.g. go for 9/32", 1/4",(gap), 3/16", 5/32"
Step 8: The Clock Hands
I decided on sheet steel as I wanted something rigid but less likely to snap while I was making it. Also being thin meant that 4 hands was less of an issue.
- First I sketched out a shape.
- Then I transferred it to the steel on top of some masking tape.
- Then I very inexpertly cut them out with my jigsaw. They were, and are, all different, but I don't mind that.
- Then a friend suggested I borrow his bench grinder to shape them, and this was great. highly recommended. Otherwise the filing takes ages.
- There was still some filing to do and then sanding to ensure no sharp edges and also a nice finish.
- I had to drill holes to match the respective brass tubes (use off-cut tubes to check, not the mounted ones on the clock).
- I found that the holes needed a little filing to get them on the tubes, but once on they were tight and needed no glue. The exception was the front hand which I wanted to have a 'cover'. So I cut out a (mostly) round piece of steel, after having drilled the hole and got it to the right size, and superglued it to the front. you can see it in the last picture. Occasionally the front hand would need a dab of glue to secure it but after a couple of false starts the hands work really well.
- I had rejected the idea of photos (because children would complain of our of date photos quickly) so I settled for painting on initials with acrylic paint.
Step 9: Complete!
It all works really nicely. The hands are sometimes a little off, depending where they came from, but actually it doesn't matter because each location is a section not just a line.
Sometimes, weirdly, my phone refuses to acknowledge that I am at home. I am clearly within the Owntracks radius when shown on the map, and even when the accuracy is good... I have no idea why. doesn't seem to afflict the rest of my family. but the set-up is the same. This means that Owntracks never sends a message and I get stuck in 'Travelling'. But it usually sorts itself out eventually.
It's been super-useful to have in our kitchen, mostly to know when the girls are heading home from school, or their friends' houses, and so when to have food/tea ready for them.
Again, a big hat-tip of thanks to @ppeters0502 for the great instructions to follow. Hopefully these can add something around making a clock with 4 hands..
Step 10: Things I Learned, and Would Do Better/differently If I Had to Do It Again.
- Physical builds need trial and error. There is no way to predict the problems of space, you just need to dive in and try.
- For code, googling problems is essential
- Start basic and build up. The servos on the test bench wood meant that I could get most of it working without the physical build
- I might have got the hands laser cut at a CNC machine. But I didn't know where the local one was, and I like how the the mild steel worked out (it was cheap and the bench grinder made it much easier)
- a stepper motor might be possible if you use the gearing to get a 360 turn. but you may then have to have the servos too close to the central axle
- There are 2 types of servo (Futaba & HiTech). Make sure that you have checked this as they have different numbers of teeth on the spline. And I bought the wrong ones initially...
- Don't connect up the hat with the wrong polarity ;-)
- Google and Stack Overflow are your friends when stuck. But you need to use good search terms...
- The test bench is actually a way that you can get a simpler, cheaper version much more easily. Most of the complication with the build comes from having to have the hands rotate around the same axle. If you compromise on that, then it is all much easier. And I think that 4 may be the limit of the single axle unless the shaft gets much longer. You could, I suppose have 3 on the front plate and three on the back plate if the shaft were longer...
Step 11: Possible Future Extensions...?
The ideas I had about next steps are as follows.
- I'd like to re-purpose an old iPad as the clock face. i.e. make a digital clock. Possibly browser-based or an app. As a physical clock is essentially stateless (i.e. it doesn't know where it currently is, except by virtue of the hands being in a physical position) I would need to have a persistent store of data. Node Red can write out to the local file system, so I would probably do that.
- If I did that then I'd like to be able to see it from outside the home. But then we really need to sort out the security. Because access within the same wifi network is one thing, access from the internet is another. I currently have no idea about how best to do this this, but I suspect an MQTT subscription going the other way could work (pi publishes the current status and external devices subscribe to it)...?
- I'd quite like one hand for 'Abroad' . but that could be complex from an OwnTracks point of view. Maybe could just use long/lat combined with some huge radii?