The Midlife Geek

Ramblings of a middle aged engineer, runner and open source enthusiast

Migrate Pi image to larger Sd card

I needed to migrate Pi image to a larger SD card. Once PyCharm starts syncing to use a remote interpreter, I found 8Gb was running too low to run updates.

Fortunately, from this post, there’s a handy utility on the Pi – SD Card Copier.

Destiny 2 permission error

This PS4 Destiny 2 error:

Your permissions to access online multiplayer may have changed or your profile may have been signed in elsewhere.

Annoying unhelpful Bungie message

Restoring licenses (Settings Account>Management>Restore Licenses) fixed it for me. 

More on threads

Python

In an earlier post, I used Threads but the thread module in Python when I should be using threading. The documentation for threading says it builds upon the thread module (renamed _thread). The docs for _thread say:

This module provides low-level primitives for working with multiple threads (also called light-weight processes or tasks) — multiple threads of control sharing their global data space. For synchronization, simple locks (also called mutexes or binary semaphores) are provided. The threading module provides an easier to use and higher-level threading API built on top of this module.

docs.python.org

That makes sense, so I should be using the threading module. So why is there a leading underscore on thread? The Style Guide (PEP 8) says it’s a weak internal use indication and that for example modules with an underscore are not imported when using an asterisk.

There are two ways to use this module. Define a subclass and override the run method or to use the Thread class’s default run method. I’ll use the second method here.

The Python 2.x code I was using looked like this:

1
2
import thread
thread.start_new_thread(scroll, (text,))

The new code:

1
2
3
4
5
6
7
8
import threading

def scroll(text):
    print(text)

text = 'Example text'
thread = threading.Thread(target=scroll, args=(text,))
thread.start()

So this isn’t that different but it is a lot more readable. The arguments are explicit and there’s no ambiguity.

Fluent Python (Ramalho, 2015) suggests using   concurrent.futures package with Python 3.x. ThreadPoolExecutor and ProcessPoolExecutor implement interfaces to submit threads or processes respectively for execution. I’ll expand on this in a future post as it is useful to submit multiple tasks and collect results – however that’s not what is needed in this example.

Rainbow hat – decorators, arguments and threads

Raspberry Pi

Playing with Rainbow Hat I learned a few things about Python as a result I found out what a decorator is, the difference between args and kwargs and threads. I also learned that a lot of guides don’t understand either.

If you can’t explain it simply, you don’t understand it well enough.

Albert Einstein

Decorators

Rainbow Hat documentation says “use touch handlers either by passing in a function by name, or using the method as a decorator”.

Learning Python (Lutz, 2013) dedicates a chapter to decorators and sums it up rather well:

In short, decorators provide a way to insert automatically run code at the end of function and class definition statements—at the end of a def for function decorators, and at the end of a class for class decorators.

With similar notation to Java’s annotations:

1
@decorator_function def function(arguments): ...

Python is running one function through another and binding the result to the original function name.

1
2
3
4
def function(arguments):
    ...

function = decorator_function(function)

For example, Python has a built in function that returns a static method staticmethod(function). To make example_func static, we put:

1
2
3
@staticmethod
def example_func(arg)
    ...

Which is rebound to:

1
staticmethod(example_func)(arg)

So now I know what a decorator is in Python, I used it for the buttons. What to use them for though? I figure that they should control speed of LED, sequence or colour. That’s going to need a thread running as an event handler.

A short digression on arguments

What on earth is a key-worded argument? Lots of documentation refers to *args and **kwargs but had no idea what it was. Arguments passed to functions are read left to right:

function('Dougie', 42)

But we can also use a key-value pair:

function(name='Dougie', age=42)

Apart from improving readability in the function call, default arguments can be assigned in the function definition:

def function(name='Dougie', age=42)

By convention these are referred to as arg and kwarg. Almost there – that just leaves the *. Python lets you define functions that take any number of arguments, assembling them into a tuple. If you use key-value arguments, it assembles a dictionary.

def function(**kwargs): {...}

Now the clever(er) bit because if you do the same on the function call, Python unpacks the argument into individual arguments (*arg) or key-value pairs (**kwarg).

function(**kwargs)

Back to the main thread

The Rainbow Hat has buttons so I want to use these to control rainbow speed. This seems suited to a thread running an event handler. The syntax for the thread library (hopefully explaining the digression) is:

thread.start_new_thread (function_name, (*args, **kwargs))

Concurrency in Python is probably a post in its own right. The CPython interpreter bytecode isn’t fully thread safe. There are different interpretations of what that means so I’ll use the Open University definition:

A class is considered thread-safe if its instances behave under concurrent method calls as if they were called sequentially.

M362 Developing concurrent distributed systems (THE OU, 2008)

Python source code is compiled to bytecode which is run in a VM as machine code. In order to ensure only one thread executes bytecode at once the current thread has to hold a global lock (Global Interpreter Lock (GIL)).

This means multiple processor cores aren’t being used. In this application it doesn’t matter because the interpreter emulates concurrency by routinely switching threads.


Passwordless SSH access is convenient, especially as everything is on my local network. I only really access the Pi remotely and you can configure it to use RSA keys. I’m on Ubuntu Linux so open a terminal and create an RSA key (if you don’t have one):

ssh-keygen -t rsa

You’ll need to upload it to the Pi:

ssh-copy-id username@ip_address

Now because I can’t be bothered to remember IP addresses, I added a line to /etc/hosts:

ip_address     raspi

That means that I need to add a more specific entry to the ~/.ssh/known_hosts file to allow for the IP address and name:

ssh-keyscan -Ht rsa raspi,ip_address >> ~/.ssh/known_hosts

You’ll be asked for a password to unlock the keyring in Ubuntu when you first login but otherwise that’s you with passwordless ssh! You’ll need a static IP address. I couldn’t be bothered messing about with it personally so left the Pi using Dynamic IP allocation and set my router to always give the same address.

ssh session
Passwordless SSH all working!

PyCharm Professional

PyCharm Professional offers a free student license – which is handy as it supports a remote interpreter over SSH. It also has a Linux version!

Developing for Raspberry Pi is fun but developing on Pi is on the sluggish side. So I just use a text editor, making me less productive. Being able to develop on my laptop then execute on the Pi is great – code completion, VCS, highlighting and debugging all available!

Configuration is easy too. Setup Pi for SSH then add the remote interpreter in PyCharm.

PyCharm Professional

Pimoroni Rainbow Hat

Rainbow Hat (courtesy of Pimoroni)

Pimoroni’s Rainbow Hat offers a nice selection of inputs and outputs using a variety of protocols. This makes it a great way to experiment with Raspberry Pi, especially as Hardware Attached on Top (HAT) avoids the messiness of breadboards and shorting links!

Designed for Android Things, it also has a Python library and a well written getting started guide. I haven’t had a play with Android Things yet so will leave that for another day and am currently a little obsessed with Python anyway.

Installation

Attaching directly to the Pi using the GPIO pins, it’s very straight forward to install (I’m using a Raspberry Pi B+ and Raspbian Stretch). There’s a nice installation guide but it’s just a single script:

1
curl https://get.pimoroni.com/rainbowhat | bash

Can’t really see anyway that Pimoroni could make it easier. If you’re wondering about it’s suitability for younger explorers I’d say you’d be fine.

What and how with Python

The Python library is well documented, although not completely (notably the “star” segmented display). So what have we got to play with?

LED

LED are great so that’s where we start. I found a blog post from a chap called Tim which has a great deal of detail on the AP102 LED used but beware it’s a right rabbit hole (which I spent some time wandering around). These are controlled using the Serial Peripheral Interface (SPI). Documentation suggests the brightness can be adjusted but I couldn’t see it working.

I ended up spending more time messing around with different ways to use the LED that I used it’s own class but most of the methods look something like this:

1
2
3
4
5
6
7
from rainbowhat import rainbow
from random import randint

for each in range(255):
    rainbow.clear()
    rainbow.set_all(randint(0, 6)), r, g, b)
    rainbow.show()

Segmented display

This updates very quickly, refreshing quickly enough to scroll. As mentioned above the library documentation omits display.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import rainbowhat as rh

def scroll(scroll_text):
    while True:
        show = ''
        for letter in scroll_text:
            show = show + letter
            rh.display.clear()
            rh.display.print_str(show)
            rh.display.show()
            time.sleep(0.25)
            time.sleep(2)

scroll('Merry Christmas!')

Temperature and pressure sensor

This is a single sensor that measures both. I haven’t played much with it but it seems about right. The temperature probably needs to be compensated for against the Pi’s temperature as it seems a little higher than I’d expect for room temperature. The functions are accessed using weather.temperature() and weather.pressure().

There’s also an altitude function (which is derived from pressure) weather.altitude(qnh=1020). I notice the parameters are specified as a keyword argument, I need to look at the library and see if I can use QNE as well as QNH.

Capacitive buttons

There’s three capacitive buttons, which are more responsive than I expected. These are accessed using a decorator (more detailed post here) and documentation mentions press and release states but I found there is also a pressed state (as in currently being pressed). I haven’t found if it’s possible to check if two or more a currently pressed and will look at that in another post.

1
2
3
@rh.touch.A.press()
def touch_a(channel):
    # Whatever you want it to do!

I found I wanted an event handler running as a parallel process to monitor the buttons. Concurrency in Python is interesting and I am writing a separate post about it.

Each has a useful corresponding LED so you can show state. These are red, green and blue and are accessed as such, for example to turn on the blue one rainbowhat.light.blue.on().

Piezo buzzer

The buzzer can play midi notes by number or specific frequencies using buzzer.midi_note(number, duration=1.0) and buzzer.note(frequency, duration=1.0). I can’t imagine me using this much as I’m tone deaf so the most important method for me would be buzzer.stop.

Thoughts

I certainly recommend this, especially if you’re getting into Python, Raspberry Pi and working with hardware.

HAT are a lot simpler and tidier than breadboards while still giving visual feedback. There is a good choice inputs and outputs here and the library is consistent and logical. They say that if something is Pythonic, you should be able to work out how it functions and that’s true here.

 

Python Concurrency

What a minefield. If you haven’t seen it, there’s a great talk from David Beazley on YouTube discussing threads, event loops and co-routines. It’s worthwhile just to see someone give a presentation on coding live with Emacs.

Python’s List Comprehension

Python's List Comprehension

I’ve been spending time with Python recently and am beginning to really like some of the language’s features.

List comprehension (listcomp) creates a list by evaluating an expression on each item in a given list, from left to right.

It combines and expression and a loop:

>>> [ord(letter) for letter in 'example']
[101, 120, 97, 109, 112, 108, 101]

Apply a condition:

>>> [ord(letter) for letter in 'example' if ord(letter) < 112]
[101, 97, 109, 108, 101]

It’s useful for combining lists:

>>> [(letter, number) for letter in 'ab' for number in '12']
[('a', '1'), ('a', '2'), ('b', '1'), ('b', '2')]

Pimoroni’s Rainbow Hat introduction has an example to cycle colours on the LED rainbow:

for i in range(101):
    h = i / 100.0
    r, g, b = [int(c * 255) for c in colorsys.hsv_to_rgb(h, 1.0, 1.0)]
    rh.rainbow.set_all(r, g, b)
    rh.rainbow.show()

This is a little hard to follow but we’ll break it down. Hue, Saturation and Value (HSV) represents colour using three values between 0.0 and 1.0 creating a colour “wheel” that is easy to cycle on the LED. Unfortunately the LED combines red, green and blue. The Colorsys library can convert between the two.

The expression is int(c*255). The loop is for c in colorsys.hsv_to_rgb(h, 1.0, 1.0)

The h=i/100 is giving a range of values from 0.0 to 1.0 in 0.01 steps (we could use a list comprehension too [i/100 for i in range(101)]).

So let’s look at a snapshot, where h=1.3:

>>> colorsys.hsv_to_rgb(0.13,1.0,1.0)
(1.0, 0.78, 0.0)

Which the list comprehension converts to:

>>> [int(c*255) for c in colorsys.hsv_to_rgb(0.13, 1.0, 1.0)]
[255, 198, 0]

Giving us the RGB value needed.

Masters degree

With a bachelors completed, a sense of “what now” quickly settles in and a masters degree is a logical next step. After graduation, the Open University (OU) was quick to respond to tweets:

Masters degree

Continue reading

« Older posts

© 2019 The Midlife Geek

Theme by Anders NorénUp ↑