The Linear Clock Ticks Again

I’ve had a background project ticking over slowly in the background for a number of years.

Last year I designed and had built a number of PCBs to be used as HATs for a Raspberry Pi Zero. They included a RTC and a terminal block to attach the LED strip.

I did say that I would write another post when the boards where delivered and I had assembled the first prototype. Unfortunately I had made a small, but critical mistake when designing the boards, I slightly messed up the package package size for the RTC so it wasn’t possible to get assemble the boards correctly. I didn’t get round to re-doing the PCB layout with the correct sized parts so the whole thing just sat for a while.

In the meantime the Raspberry Pi Foundation went and released a new product, the Raspberry Pi Pico, which is based on the RP2040 chip. As well as the Pico they are also making the RP2040 chip available to other folk to include it directly in their own projects.

Pimoroni have created a number of different boards but their latest is the Plasma 2040 which is specifically designed to drive LED strips.

B.O.M.

Assembly

  • Solder the RTC on to the breakout section of the Plasma 2040, the terminals are labelled so just make sure you match up the pins, I used the headers that came with the RTC and arranged it so the breakout was over the top of the Plasma2040
  • Loosen the screw terminals for the connections marked 5V, DA and -. Insert the Red wire of the adapter in the 5V, Green wire in DA and White wire in –
  • Clip the LED strip to the end of the adapter.
Plasma 2040

Code

When you first attach the Plasma2040 to your computer it will show up as a USB flash drive. This is so you can install the runtime. In this case we’ll be using the Pimoroni Micropython build that comes with support for the board. You can grab a version from the release page on GitHub here. Once downloaded copy it into the root of the drive. When the copy has finished the board will reboot and be ready to run Python code.

You can use the Thonny IDE to both write and push code to the device. You will need at least version 3.3.3 to support the Plasma2040.

The fist version of the code was as follows:

import plasma
from plasma import plasma2040
from pimoroni import RGBLED, Button
import time

NUM_LEDS = 60
LOW = 32
MED = 64
HIGH = 128
BRIGHTNESS = [LOW,MED,HIGH]
BRIGHTNESS_LEVEL = 0

button_brightness = Button(plasma2040.BUTTON_A)

led = RGBLED(plasma2040.LED_R, plasma2040.LED_G, plasma2040.LED_B)
led.set_rgb(0, 0, 0)
led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT)

led_strip.start()

while True:
    RED = [0]*NUM_LEDS
    GREEN = [0]*NUM_LEDS
    BLUE = [0]*NUM_LEDS
    t = time.localtime()

    hour = (t[3] % 12) * 5
    #Hours
    RED[hour] = BRIGHTNESS[BRIGHTNESS_LEVEL]
    RED[hour + 1] = BRIGHTNESS[BRIGHTNESS_LEVEL]
    RED[hour + 2] = BRIGHTNESS[BRIGHTNESS_LEVEL]
    RED[hour + 3] = BRIGHTNESS[BRIGHTNESS_LEVEL]
    RED[hour + 4] = BRIGHTNESS[BRIGHTNESS_LEVEL]
    #Mins
    GREEN[t[4]] = BRIGHTNESS[BRIGHTNESS_LEVEL]
    #Secs
    BLUE[t[5]] = BRIGHTNESS[BRIGHTNESS_LEVEL]
    
    #set the LEDS
    for i in range (NUM_LEDS):
        led_strip.set_rgb(i, RED[i], GREEN[i], BLUE[i])
    
    #change brightness
    if button_brightness.read():
        BRIGHTNESS_LEVEL += 1
        BRIGHTNESS_LEVEL %= 3
    
    time.sleep(1)
 

This works well when triggered from Thonny as it syncs the laptop’s time to the RP2040 each time it connects. But when the clock is powered by a USB power supply or a battery, the clock starts at 00:00:01 Jan 1st 2021 and has no way to be updated to match now.

This is why we need the RTC module, it keeps track of the time while the clock is powered down.

It also has a way to change the brightness, by pressing the A button it will cycle through 3 different brightness levels.

Setting the RTC Time

With a little bit of playing I worked out how to sync the RTC to the current time in the Thonny console

>>> from pimoroni_i2c import PimoroniI2C
>>> from breakout_rtc import BreakoutRTC
>>> import time
>>> PINS_PLASMA = {"sda": 20, "scl": 21}
>>> i2c = PimoroniI2C(**PINS_PLASMA)
>>> rtc = BreakoutRTC(i2c)
>>> rtc.set_unix(time.time())
>>> rtc.set_time(54,18,17,6,18,9,2021)
True
>>> rtc.update_time()
True
>>> print(rtc.string_time())
17:18:54
>>> rtc.set_backup_switchover_mode(3)

The most important line is the last one, which enables the battery backup for the RTC so it remembers the time you just set.

I was going to use the rtc.set_unix() function and pass in time.time() but it appears that the unix timestamp is maintained independently of the “Real” time on the RTC.

The set_time() function takes values in the order

  • seconds (0-60)
  • minutes (0-60)
  • hours (0-23)
  • day of the week (1-7 -> mon-sun)
  • day of month (1-31)
  • monthe (1-12)
  • year (2000-2099)

With the RTC set correctly a small update to the code to read from the RTC rather than from the time object and we are good to go.

import plasma
from plasma import plasma2040
from pimoroni import RGBLED, Button
from pimoroni_i2c import PimoroniI2C
from breakout_rtc import BreakoutRTC
import time

PINS_PLASMA = {"sda": 20, "scl": 21}

i2c = PimoroniI2C(**PINS_PLASMA)
rtc = BreakoutRTC(i2c)

if rtc.is_12_hour():
    rtc.set_24_hour()

if rtc.update_time():
    print(rtc.string_time())
    print(rtc.string_date())

NUM_LEDS = 60
LOW = 32
MED = 64
HIGH = 128
BRIGHTNESS = [LOW,MED,HIGH]
BRIGHTNESS_LEVEL = 0

button_brightness = Button(plasma2040.BUTTON_A)

led = RGBLED(plasma2040.LED_R, plasma2040.LED_G, plasma2040.LED_B)
led.set_rgb(0, 0, 0)
led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT)

led_strip.start()

rtc.enable_periodic_update_interrupt(True)

while True:
    RED = [0]*NUM_LEDS
    GREEN = [0]*NUM_LEDS
    BLUE = [0]*NUM_LEDS
    t = time.localtime()

    if rtc.read_periodic_update_interrupt_flag():
        rtc.clear_periodic_update_interrupt_flag()
         
        rtc.update_time()
        hour = (rtc.get_hours() % 12) * 5
        RED[hour] = BRIGHTNESS[BRIGHTNESS_LEVEL]
        RED[hour + 1] = BRIGHTNESS[BRIGHTNESS_LEVEL]
        RED[hour + 2] = BRIGHTNESS[BRIGHTNESS_LEVEL]
        RED[hour + 3] = BRIGHTNESS[BRIGHTNESS_LEVEL]
        RED[hour + 4] = BRIGHTNESS[BRIGHTNESS_LEVEL]
        GREEN[rtc.get_minutes()] = BRIGHTNESS[BRIGHTNESS_LEVEL]
        BLUE[rtc.get_seconds()] = BRIGHTNESS[BRIGHTNESS_LEVEL]

        for i in range (NUM_LEDS):
            led_strip.set_rgb(i, RED[i], GREEN[i], BLUE[i])
        
        if button_brightness.read():
            BRIGHTNESS_LEVEL += 1
            BRIGHTNESS_LEVEL %= 3
    
    time.sleep(1)
2021 Edition

Next Steps

There are a few things that need doing next. The first is to build a case for the clock, I’m thinking about something made up of layers of thin plywood with a channel for the LED strip and maybe a layer of smoked/mat acrylic to act as a diffuser.

The second part is to work out a way to work with DST, Micropython doesn’t support timezones as the database needed to keep track of all the different timezones takes up a huge amount of space. I could hard code in the dates for my location, but I’ll probably just make use of the B button to toggle an hours difference on/off.

Optionally I might add another 31 LED strip (probably at 30/meter) to be used as a calendar showing the current month with markers for weekends and the current day.

Another option is to use 4 of these to build a 60 LED ring for something a little more conventionally shaped.

And the final extra hack is to daisy chain the Light level sensor (e.g. one of these) on top of the RTC and dynamically adjust the brightness based on ambient light levels.

I’ll also probably keep tinkering with the Raspberry Pi Zero W version as that will allow oAuth to link to things like Google Calendar to show meetings in the clock view and add Holidays to the Calendar view. It will also have access to the full timezone database and NTP for time syncing over the network.

Router swap

With all the working from home over the last 18months and the fact I now work for a 100% remote company I decided it was time to have another look at my home broadband setup.

I currently have a FTTC install supplied by A&A which currently tops out at about 60/15 and while a FTTP setup would be nice I’ll have to wait until OpenReach get their finger out and actually fully enable my exchange (A recent new build development is already full fibre, but the existing properties will have to wait).

The line has been pretty reliable but I decided it was time to add some backup capability if I’m going to be relying on it all the time. I decided to add an LTE/4G link (no 5G out here in the sticks yet either).

I already had a LTE USB stick but the Ubiquiti EdgeRouter X that I was running didn’t have a USB port so I looked at putting the stick in Pi and adding a second low priority default route via the Pi. This worked but meant that I lost IPv6 (finding a UK cell provider that will offer IPv6 on Pay&Go is a problem I’ve looked at before) and others won’t be able to reach my web server or the other services I host at home. I’ll cover the 4G network provision later.

A&A offer a L2TP service which can route the fixed IPv4 and IPv6 ranges over any connection if your main line is down for any reason. This can easily run over a LTE connection, but it does have one slight niggle. If the L2TP tunnel is running at the same time as the FTTC line then it will take priority which means it should only be started when the FTTC line goes down.

The EdgeRouter X only supports L2TP Tunnels when paired with IPSEC so can’t easily be used with this option. I could run something like xl2tp on the Pi with the LTE USB stick but then I would need a way to trigger it on the Pi when the PPPoE link goes down on the EdgeRouter. All of this combined with Ubiquiti’s apparent pulling back from the EdgeRouter line as they focus more on their Dream Machine range I thought I’d see what else was available.

MikroTik

If you poke around the internet in the places where people talk about Ubiquiti kit they also mention MikroTik and RouterOS so I thought I’d have a look and see what was available.

MikroTik hEX s router

The closest match to the EdgeRouter X looked to be a MikroTik hEX S. It has the same 5 Gigabit Ethernet ports, PoE powered and also has a USB port and a SFP port for if I ever want to add fibre support.

I already had a Huawei E3372-200 LTE stick to plug into the side. This supports up to 150Mbps connections and has connectors to add external antenna if needed to get the best signal. I also grabbed a 90° USB adapter, because everybody knows that USB sticks work better when pointed straight up.

Router & Switch

I plugged the hEX S into my desktop ISP setup to work out how configure it and play with some of the settings.

There are 3 ways to configure most RouterBoard/RouterOS devices

  • Winbox – a native application that supports Windows (can be run under Wine on Linux and OSx)
  • WebFig – a web interface
  • Console/SSH – a command line interface

I’ve not tried Winbox, I did most of the setup via the console interface, but I used the WebFig to check. Most of the time WebFig works just fine, but occasionally it would throw javascript errors. I’m hoping that most of this is down to the fact I had to install a 7.1 release candidate build to get LTE stick to work properly. I’ll check back once 7.1 gets a proper release.

Using the console I managed to setup the LAN IP address range, DHCP server and pre-reserved all the static IP addresses to match my old setup.

Getting the port forwarding and hairpin NAT setup was a little bit more challenging than on the EdgeRouter but I have something that looks to behave the same for everything I had setup before.

I set the LTE device to be always on but with a static route to the L2TP endpoint and a script that run when the PPPoE device goes up or down. When the PPPoE goes down it will connect the L2TP client and disconnect it when the PPPoE device comes back up. The easiest way to test is to unplug the ethernet cable between the router and the modem running in bridge mode.

Cellular Contract

The next question is what mobile data plan to use, this is meant to be only used as a fall back, so I don’t really want to be paying for a monthly contract and then not using it, which means I’m looking for a Pay & Go sim card. I also want a plan that has the longest possible lifetime for any credit. Luckily Terrence Eden had recently collated a list of the best deals for this kind of data sim. It looks like the Three 24GB or the matching Vodafone 24GB plan are the best fit.

I opted for the Three as I have reasonable coverage at home, it comes with 24GB pre-loaded and it will last for up to 2 years (unlike a lot of the others that expire every month). It’s list price at time of writing is £44.99, I got mine for $39.96, but it’s been as low as £31.29 on offer recently.

Next

At the moment the router only fails over if the PPPoE connection goes down, it would be nice to try and detect if the PPPoE link stays up, but traffic stops flowing and change over. The challenge here is how to know to switch back since the L2TP tunnel takes priority. I’ll have to think about that one.

King Alfred’s Way

Not being able to travel for the last 18 months has meant that I’ve not done either of the 2 big cycling events I had planned. I was going to go back and have another crack at the Dirty Kanza (now known as Unbound Gravel) and The Rift (200km round a couple of volcanoes in Iceland).

So I’ve been looking for something a little closer to home to have a crack at.

Mid 2020 Cycling UK announced a new route that they had been working on for a while called the King Alfred’s Way, a 350km mainly off road route that starts in Winchester, goes west to Salisbury, North to near Swindon, west along the Ridgeway to Reading and then down back to Winchester via the edge of the Surry Hills and the South Downs Way.

Day 1

Hursley House

I parked my car up at my old IBM Office at about 7:00 and spent the next 30mins getting all the bags setup on the bike, topping up the tyre pressures, generally sorting out filling water bottles and distributing snacks for the day round various pockets.

It was a short (7km) ride to the official start point at the West Gate in Winchester so I could set off close to 8:00.

Winchester West Gate

The route works it’s way through Winchester on mainly quiet residential streets before making a break for the countryside towards Sparsholt where it forks off on to single track trail up through the woods.

It was then a gentle rolling mix of wooded tracks and farm lanes all the way out to Salisbury where the road turns north to roll past Stone Henge.

Stone Henge in the distance

After Stone Henge the route sets off across the Salisbury Plain Training Area, this is where the you have to keep an eye on the flags and be prepared for loud bangs and tanks crossing the track. It was actually pretty quiet this time.

I had expected to find somewhere to stop for lunch along the way but it’s pretty remote and it wasn’t until I drop off the Plain (just after the end of the 3rd GPX file) and made it to All Canning around 14:50 (and the pub was supposed to close at 15:00)

I had planned to camp at a place called Smeathe’s Ridge which is just past Barbary Castle having seen it mentioned as a good spot by a few people riding/walking the Ridgeway. Unfortunately this appears to also be a race horse training gallops which the owner was in the process of mowing when I got there. I did think about asking for permission, but decided to press in a little to see if I could find somewhere else.

About 5km further along and having dropped into the valley I came across an empty field that was well screen from the track, wasn’t overlooked and didn’t look to have any paths running through it. I set up my little tent , and boiled the water for dinner.

View across the valley

Day 2

I woke up stupidly early on the morning of day 2 so I had managed to pack up my tent and was ready to roll again by 6:00. It started with a short push to get up on to the top of the ridge again.

I soon past a perfect camping spot that was just off the trail, behind a bench looking out over the valley. Another cyclists had spent the night and was still very much asleep as I rolled past.

It was foggy and even started to rain a little so I was glad I’d packed my proper rain jacket, both to keep the wet out and to help keep warm.

The track winds it way up over another ridge to the north and then drops down again to crosses the M4 and passes the PGL Summer Camp before climbing back up on to the Ridgeway.

I was short on water as having last been able to top up my bottles was at The Kings Arms in All Canning the afternoon before and uses a bunch for dinner the night before. I found a tap with a dirty looking hose at a little take way caravan attached to a pig farm. Unfortunately as it was mid week and still very early so no change of grabbing a bacon sandwich, but the fitting for the hose came undone easily so I could top up my bottles. About 2km further on there was another tap signposted.

Ridgeway Strade Bianche

The farm lanes were mainly crushed chalk which looked great but could be pretty bumpy and had chunks of flint poking though which was best avoided. As it was dry it was pretty quick rolling, but would be really sticky in the wet.

The Ridgeway took most of the morning, then the route drops down to run along side the Thames at Goring.

The Thames Path took me on to Reading, which was fun as it was the first day of the Reading Festival and the route past one of the site entrances, having to dodge lots Polos and Fiat 500s full of teenagers and then through main shopping centre with the paths full of people carrying disposable tents and crates of cheap cider.

I stopped off at the Mission Burrito in the shopping centre for lunch, before following the River Kennet south out of the city.

The route was mainly cycle paths and trails until it hooks up with the can Basingstoke Canal for a while.

Crossing the canal

After the canal I detoured a little to find the hotel I’d booked in Aldershot deciding that a real bed and a takeaway pizza would hopefully lead to a longer nights sleep.

Day 3

Day 3 started with the only encounter with a bad driver, a close pass on the way out of Aldershot, who then had the gawl to argue about it when called out.

The route rolled through some of the smarter housing south of Farnham before crossing the edge of a golf course and entering another military range. This area is very sandy which was hard going at time and required pushing.

Bike wheel in sand

Unlike the ranges on Salisbury Plane I did actually catch a glimpse of some of our guys in green suits, a small group that looked to be heading off to practice with some smoke grenades.

The range ends up with the climb up to the Devil’s Punch Bowl which again in places is very steep with sections of “babies heads” sized boulders which makes riding without suspension tricky, but the view from the top is pretty good.

Devil's Punch Bowl

After the Devil’s Punch Bowl the route tracks south from Hindhead again sticking mainly to forest trails and I even spotted some deer on the way into Liss.

Deer on the path

I cut the corner a little to get to Petersfield a little sooner and from there up the old road through Queen Elizabeth Country Park. Before the absolutely brutal climb up Buster Hill (it’s bad enough up the other side on Havesting Lane with tarmac). With all the weight on the bike I had push most of it.

From the top it was an easy run along the South Downs Way to the cafe at the Sustainability Centre for some much needed lunch. As I was feeling it by then I choose to make use of the local knowledge and took the direct road route back home. Down Old Winchester Hill and then back up Beacon Hill out of Exton, before cutting across to Owslebury, Fishers Pond and Colden Common before hitting Poles Lane back to Hursley.

Conclusion

It was a really great 3 days and I had a lot of fun, but 3 days is really pushing pretty hard considering the amount of climbing and the type of trail the route takes.

I’ll try and do another post about the kit I took, but one thing I will say is that I’m going to need some new gravel/mtb shoes pretty soon. The Giro Rumbles I’ve been using since I started training for the Dirty Kansa have been pretty good, but a week later the feeling has still not 100% returned to the middle 3 toes on both feet (It’s getting better everyday, but it’s time for some stiffer soles).