Thursday, 24 May 2018

Setting up a Raspberry Pi Zero W to run pywws

I recently bought my first Raspberry Pi Zero W, a tiny little computer just 3 inches long and 1½ inches wide (in its case). I intend eventually to get it working with pywws (some weather station software I wrote a while ago) and I'll be adding to this blog post as I go along, to keep it all in one place.

Getting started


As I'll be using the Pi in "headless" mode (no monitor or keyboard in normal operation) I decided to start as I mean to go on. This also means I don't yet need adapters for the mini HDMI and OTG USB ports on the Pi Zero.

I downloaded and copied the current version of Raspbian, called "stretch", and copied it to a 16 GB micro SD card. An 8 GB card would have been sufficient but the larger card only cost a few pence extra. Note that this is the full version of Raspbian (i.e. not "lite") and is not the NOOBS version.

Booting the Pi directly into headless mode turned out to be surprisingly easy. The instructions in this forum post were all I needed, and worked perfectly despite the negative comments on the post. I inserted the micro SD card, in an adapter, into my openSUSE Linux PC and used the "open with file manager" prompt to mount both partitions. The df command showed them to be mounted as /run/media/jim/boot and /run/media/jim/rootfs.

Having changed directory to the /run/media/jim/boot partition all I had to do was create an empty file called ssh (with the command sudo touch ssh) then use a text editor (run via sudo) to create a file wpa_supplicant.conf with the following contents:
country=GB
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="my_wifi_ssid"
    scan_ssid=1
    psk="my_wifi_password"
    key_mgmt=WPA-PSK
}

After safely unmounting the SD card partitions I removed it from the PC, put it in the Pi, and turned the power on. About a minute later the hostname raspberrypi showed up in the DHCP server's list of hosts and I was able to ssh into it (the initial password is raspberry):
jim@brains:~$ ssh pi@raspberrypi
The authenticity of host 'raspberrypi (192.168.1.176)' can't be established.
ECDSA key fingerprint is SHA256:bw10eHPZ3debE04S+5a8xEYSDHT9AmZk8MJWxfNTapQ.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'raspberrypi,192.168.1.176' (ECDSA) to the list of known hosts.
pi@raspberrypi's password: 
Linux raspberrypi 4.14.34+ #1110 Mon Apr 16 14:51:42 BST 2018 armv6l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Apr 18 01:25:27 2018

SSH is enabled and the default password for the 'pi' user has not been changed.
This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.

pi@raspberrypi:~ $ passwd
Changing password for pi.
(current) UNIX password: 
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
pi@raspberrypi:~ $

Creating a user


I could continue to use the default pi user name, but I find it more convenient to have the same user name on all my computers. As I'll be using NFS to share storage with some of those computers it's also useful if the user has the same UID number:
pi@raspberrypi:~ $ sudo adduser --uid 1026 jim
Adding user `jim' ...
Adding new group `jim' (1026) ...
Adding new user `jim' (1026) with group `jim' ...
Creating home directory `/home/jim' ...
Copying files from `/etc/skel' ...
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
Changing the user information for jim
Enter the new value, or press ENTER for the default
        Full Name []: Jim Easterbrook
        Room Number []: 
        Work Phone []: 
        Home Phone []: 
        Other []: 
Is the information correct? [Y/n] y
pi@raspberrypi:~ $ sudo visudo -f /etc/sudoers.d/010_pi-nopasswd
pi@raspberrypi:~ $
The final visudo command is to add the new user to the list of users permitted to do things as root.

Logging in without a password


It may sound strange but this is a way to improve security when using ssh. Passwords can perhaps be guessed, but a 2048 bit RSA key is harder to crack. I already have a key, so I just needed to copy the public key to my new account on the Pi:
jim@brains:~$ ssh-copy-id -i ~/.ssh/id_rsa.pub raspberrypi
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/jim/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
jim@raspberrypi's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'raspberrypi'"
and check to make sure that only the key(s) you wanted were added.

jim@brains:~$ ssh raspberrypi
Linux raspberrypi 4.14.34+ #1110 Mon Apr 16 14:51:42 BST 2018 armv6l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri May 25 07:13:41 2018 from 192.168.1.162
jim@raspberrypi:~ $
No password was needed to login to the Pi, as expected.

The next step is to disable ssh with passwords entirely. Edit the sshd_config file and restart the ssh daemon:
jim@raspberrypi: $ sudo vi /etc/ssh/sshd_config 
jim@raspberrypi: $ sudo service ssh restart
There is just one line to edit, to disable password logins uncomment the PasswordAuthentication line and set it to no:
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
#PermitEmptyPasswords no
Test by attempting to login as another user:
jim@brains:~$ ssh pi@raspberrypi
Permission denied (publickey).
jim@brains:~$

Completing initial setup


I used sudo raspi-config to set the host name (under network options), set the locale (en_GB.UTF-8) and timezone (Europe/London) under localisation options, and set it to boot to console rather than desktop (under boot options).

To minimise SD card "wear" I moved some directories to RAM by adding the following to /etc/fstab and then rebooting:
tmpfs  /tmp      tmpfs  defaults,noatime,nosuid,size=100m  0 0
tmpfs  /var/log  tmpfs  defaults,noatime,nosuid,mode=0755,size=100m  0 0
tmpfs  /run      tmpfs  defaults,noatime,nosuid,mode=0755,size=2m  0 0
(At first the Pi failed to boot, so I moved the SD card to my main PC, mounted rootfs and deleted everything in the directories that have been moved to tmpfs.)

I also disabled swap (with sudo apt-get remove dphys-swapfile) and turned off file system journaling.

I added a few of my favourite command aliases by creating a file /etc/profile.d/aliases.sh containing the following:
alias df='df -h'
alias la='ls -ao'
alias ll='ls -l'

To save a small amount of power consumption I turned off video output by adding the following to /etc/rc.local, before the exit 0 line:
# turn off video output signal
/usr/bin/tvservice -off

File sharing with NFS


It's very convenient to be able to copy files from one machine to another with NFS. The autofs service can be used to mount NFS shares when needed. I started by exporting the Pi's /home file system so it can be mounted on other machines. This requires installing the NFS server package:
jim@gordon:~ $ sudo apt-get -o Acquire::ForceIPv4=true update
jim@gordon:~ $ sudo apt-get -o Acquire::ForceIPv4=true install nfs-kernel-server
The -o Acquire::ForceIPv4=true option stops apt-get using IPv6, as I don't yet have an IPv6 internet connection.

I then added the following line to /etc/exports:
/home   192.168.1.0/24(rw,root_squash,sync,no_subtree_check)
This should allow any machine on my local network to read and write files in /home on the Pi, once the NFS server is restarted:
sudo service nfs-kernel-server restart

To mount other machines on the Pi requires autofs to be installed:
jim@gordon:~ $ sudo apt-get -o Acquire::ForceIPv4=true install autofs
I then edited /etc/auto.master and added the following line:
/auto   /etc/auto.tracy.island  --timeout=30
The file /etc/auto.tracy.island lists the NFS shares I want access to:
brains  -bg,intr                brains:/home
zero-x  -fstype=nfs4,bg,intr    zero-x:/volume1
brains is my main PC and zero-x is my Synology NAS box. (Fans of 1960s children's television should know what inspired my local network naming scheme.)

After restarting autofs I can access files on other machines:
jim@gordon:~ $ sudo service autofs restart
jim@gordon:~ $ ll /auto/brains/
total 32
drwxr-xr-x  7 1024 users  4096 May 19 09:42 admin
drwxr-xr-x 94 jim  users  4096 May 25 11:18 jim
drwx------  2 root root  16384 Aug 21  2011 lost+found
drwxr-xr-x 13 2001 users  4096 May 22  2016 sarah
drwxr-xr-x 19 pi   users  4096 Sep  9  2017 test
jim@gordon:~ $ ll /auto/zero-x
total 208
drwxrwxrwx 113 root root   4096 Mar  6 18:15 audio
drwxrwxrwx   6 root root   4096 May 18 15:12 brains
drwxrwxrwx   5 root root   4096 May 10 12:19 DVD
drwxrwxrwx   6 root root   4096 May 10 14:22 firefly
drwxrwxrwx   6 root root   4096 May  9 08:59 kyrano
drwxrwxrwx  29 root root   4096 May 15 14:07 photos
drwxrwxrwx   7 root root 131072 May 17 12:59 pvr
drwxrwxrwx   5 root root  12288 May 12 08:41 toppy
drwxrwxrwx  11 root root   4096 May 20 09:45 video
jim@gordon:~ $

Scheduling backup


Experience has taught me the value of backing up computers. The Raspberry Pi is no exception, and as I have a NAS that's always on backing up couldn't be easier. I created a "scripts" directory and added two files. /home/jim/scripts/backup_to_zero-x.sh does the actual backup:
#!/bin/sh

log=/var/log/log-backup

dest="jim@zero-x::gordon"
export RSYNC_PASSWORD=xxxxxx

rsync -av \
        /etc $dest >$log 2>&1
rsync -av \
        --exclude=".cache" \
        --exclude="cache" \
        /home $dest >>$log 2>&1

# mail the log file
if [ -s $log ]; then
  /home/jim/scripts/email-log.py $log "backup log"
  fi
/home/jim/scripts/email-log.py emails the backup log to an email server running on the NAS:
#!/usr/bin/env python

from email.utils import formatdate
import platform
from smtplib import SMTP
import sys

def main():
    file = sys.argv[1]
    subject = sys.argv[2]
    with open(file, 'r') as f:
        contents = f.read()
    if not contents:
        return
    sender = platform.node() + '@tracy.island'
    date = formatdate()
    msg = '''Subject: {subject}
From: {sender}
Date: {date}

{file} contents follows
===START===
'''.format(date=date, file=file, sender=sender, subject=subject)
    msg += contents
    msg += '''
====END====
'''
    smtp = SMTP(host='zero-x', port=25, timeout=20)
    smtp.sendmail(sender, 'jim@zero-x.tracy.island', msg)

if __name__ == '__main__':
    main()
I set up a root user "cron" job to run the backup script daily at around 4 am.

Installation of pywws


You'll probably want to install pywws from PyPI, but I use the development version from GitHub:
jim@gordon:~ $ mkdir weather
jim@gordon:~ $ cd weather/
jim@gordon:~/weather $ git clone https://github.com/jim-easterbrook/pywws.git
Cloning into 'pywws'...
remote: Counting objects: 9190, done.
remote: Compressing objects: 100% (24/24), done.
remote: Total 9190 (delta 10), reused 15 (delta 4), pack-reused 9162
Receiving objects: 100% (9190/9190), 4.55 MiB | 724.00 KiB/s, done.
Resolving deltas: 100% (5557/5557), done.
jim@gordon:~/weather $ cd pywws
jim@gordon:~/weather/pywws $ python3 setup.py build
...
jim@gordon:~/weather/pywws $ sudo python3 setup.py install
...
jim@gordon:~/weather/pywws $
The install process was hanging whilst fetching dependencies from https://pypi.python.org/ until I disabled IPv6 entirely by adding net.ipv6.conf.all.disable_ipv6 = 1 to /etc/sysctl.conf and rebooting.

The next step is to install the required Python USB library:
jim@gordon:~/weather/pywws $ sudo apt-get install python3-libusb1
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  python3-libusb1
0 upgraded, 1 newly installed, 0 to remove and 38 not upgraded.
Need to get 35.1 kB of archives.
After this operation, 189 kB of additional disk space will be used.
Get:1 http://raspbian.mirror.uk.sargasso.net/raspbian stretch/main armhf python3-libusb1 all 1.6.3-1 [35.1 kB]
Fetched 35.1 kB in 0s (67.1 kB/s)    
Selecting previously unselected package python3-libusb1.
(Reading database ... 124808 files and directories currently installed.)
Preparing to unpack .../python3-libusb1_1.6.3-1_all.deb ...
Unpacking python3-libusb1 (1.6.3-1) ...
Setting up python3-libusb1 (1.6.3-1) ...
jim@gordon:~/weather/pywws $
Finally I can test that the core pywws software is installed correctly:
jim@gordon:~/weather/pywws $ pywws-version -v
18.5.0
build: 1541
commit: d505b50
Python: 3.5.3 (default, Jan 19 2017, 14:11:04) 
[GCC 6.3.0 20170124]
USB:    pywws.device_libusb1
examples:
   /usr/local/lib/python3.5/dist-packages/pywws-18.5.0-py3.5.egg/pywws/examples
docs:
   http://jim-easterbrook.github.com/pywws/
jim@gordon:~/weather/pywws $ pywws-testweatherstation 
12:29:22:pywws.logger:pywws version 18.5.0, build 1541 (d505b50)
Traceback (most recent call last):
  File "/usr/local/bin/pywws-testweatherstation", line 11, in 
    load_entry_point('pywws==18.5.0', 'console_scripts', 'pywws-testweatherstation')()
  File "/usr/local/lib/python3.5/dist-packages/pywws-18.5.0-py3.5.egg/pywws/testweatherstation.py", line 117, in main
    ws = pywws.weatherstation.WeatherStation()
  File "/usr/local/lib/python3.5/dist-packages/pywws-18.5.0-py3.5.egg/pywws/weatherstation.py", line 462, in __init__
    self.cusb = CUSBDrive()
  File "/usr/local/lib/python3.5/dist-packages/pywws-18.5.0-py3.5.egg/pywws/weatherstation.py", line 316, in __init__
    self.dev = USBDevice(0x1941, 0x8021)
  File "/usr/local/lib/python3.5/dist-packages/pywws-18.5.0-py3.5.egg/pywws/device_libusb1.py", line 78, in __init__
    raise IOError("Weather station device not found")
OSError: Weather station device not found
jim@gordon:~/weather/pywws $

Connecting the weather station


Given the limitations of the "OTG" USB port on the Pi Zero I was pleasantly surprised that when I connected my test weather station console (an old one whose outside sensors have failed) via a standard USB A to micro USB lead (as used to connect a phone to a computer) it powered up normally. It also works with pywws:
jim@gordon:~/weather/pywws $ sudo pywws-testweatherstation 
12:32:56:pywws.logger:pywws version 18.5.0, build 1541 (d505b50)
0000 55 aa ff ff ff ff ff ff ff ff ff ff ff ff ff ff 03 20 01 41 11 00 00 00 81 7f 00 01 00 00 00 01 
0020 94 27 87 27 00 00 00 00 00 00 00 07 01 01 16 55 41 23 c8 00 00 00 46 2d 2c 01 64 80 c8 00 00 00 
0040 64 00 64 80 a0 28 80 25 a0 28 80 25 03 36 00 05 6b 00 00 0a 00 f4 01 12 00 00 00 00 00 00 00 00 
0060 00 00 5a 0a 63 0a 41 01 56 00 dc 01 08 81 dc 01 c5 81 68 01 75 81 95 28 d3 25 24 29 5a 25 fd 02 
0080 04 03 f4 ff fd ff 85 ff 91 ff 6c 09 00 14 10 19 06 29 12 02 01 19 32 11 09 09 05 18 12 03 28 13 
00a0 00 13 07 19 18 28 07 01 01 12 00 13 09 24 13 02 13 09 24 13 33 13 09 24 13 02 12 07 28 12 50 13 
00c0 09 24 13 02 13 10 14 16 18 12 02 07 19 00 16 03 28 04 45 13 01 04 10 28 15 01 30 05 22 12 03 10 
00e0 22 02 07 01 02 00 02 12 07 28 11 59 13 03 06 06 43 12 04 13 00 04 12 04 13 00 04 12 07 31 03 34 
jim@gordon:~/weather/pywws $
I used sudo as the USB device is "owned" by root by default.

The USB ownership is best dealt with by adding a "udev" rule. Create a file /etc/udev/rules.d/39-weather-station.rules containing the following:
ACTION!="add|change", GOTO="weatherstation_end"
SUBSYSTEM=="usb", ATTRS{idVendor}=="1941", ATTRS{idProduct}=="8021", OWNER="jim"
LABEL="weatherstation_end"
(Replace jim with your user name.)

Restart the udev system (sudo service udev restart) and unplug then replug the weather station. You should now have access to the weather station without using sudo:
jim@gordon:~/weather/pywws $ ll /dev/bus/usb/001/
total 0
crw-rw-r-- 1 root root 189, 0 May 25 12:20 001
crw-rw-r-- 1 jim  root 189, 2 May 25 13:03 003
jim@gordon:~/weather/pywws $ pywws-testweatherstation 
13:04:14:pywws.logger:pywws version 18.5.0, build 1541 (d505b50)
0000 55 aa ff ff ff ff ff ff ff ff ff ff ff ff ff ff 03 20 01 41 11 00 00 00 81 7f 00 01 00 00 00 01 
0020 94 27 88 27 00 00 00 00 00 00 00 07 01 01 12 31 41 23 c8 00 00 00 46 2d 2c 01 64 80 c8 00 00 00 
0040 64 00 64 80 a0 28 80 25 a0 28 80 25 03 36 00 05 6b 00 00 0a 00 f4 01 12 00 00 00 00 00 00 00 00 
0060 00 00 5a 0a 63 0a 41 01 56 00 dc 01 08 81 dc 01 c5 81 68 01 75 81 95 28 d3 25 24 29 5a 25 fd 02 
0080 04 03 f4 ff fd ff 85 ff 91 ff 6c 09 00 14 10 19 06 29 12 02 01 19 32 11 09 09 05 18 12 03 28 13 
00a0 00 13 07 19 18 28 07 01 01 12 00 13 09 24 13 02 13 09 24 13 33 13 09 24 13 02 12 07 28 12 50 13 
00c0 09 24 13 02 13 10 14 16 18 12 02 07 19 00 16 03 28 04 45 13 01 04 10 28 15 01 30 05 22 12 03 10 
00e0 22 02 07 01 02 00 02 12 07 28 11 59 13 03 06 06 43 12 04 13 00 04 12 04 13 00 04 12 07 31 03 34 
jim@gordon:~/weather/pywws $
As soon as I tried "live" logging, with the command pywws-testweatherstation -l -vv, I got USB timeout errors as reported by other pywws users on the pywws mail list.

A bit of experimenting with longer timeouts and measuring times to read data from the station showed the problem only occurs after pywws has paused USB activity for 5 seconds or more. I had a hunch the the Pi might be switching USB modes during this apparent inactivity, so I added the line dtoverlay=dwc2,dr_mode=host to /boot/config.txt to fix the USB port in "host" mode. This appears to have cured the timeout problem.

Final steps


To finish off I installed all the pywws dependencies I need, then copied the pywws data directory from the Pi 2 I was using. That machine has a disc drive so I haven't had to worry about SD card wear. I made a few changes to weather.ini to minimise writes to the card:
[config]
frequent writes = False

[paths]
local_files = /tmp/pywws/results
work = /tmp/pywws
I'm also using /tmp/pywws for the logfile. This avoids writing to the SD card, but does mean that the log is cleared every time the Pi is rebooted. I don't expect to have to do this too often.

The Raspberry Pi Zero is so small I'm tempted to stick it on the back of the weather station console, with a short USB lead (with right angle plugs?) to make a neat installation. However I suspect the wi-fi may interfere with the station's reception of data from the outside sensors.

Oxbridge entrance - a modest proposal

There has been some talk recently about apparent bias in the way Oxford and Cambridge universities select undergraduate students, disproportionately favouring (white) students from fee-paying schools. The universities respond, with some justification, that they accept anyone who gets top grades at A level and performs well at interview, and it's not their fault if state schools are failing to educate pupils to the required standard. (This is a gross oversimplification of the argument, but you get the idea.)

When I went to Cambridge (in the late 1970s) about half the undergraduates were, like me, from state schools. The good news is that this has improved to around 62%. The bad news is that this is still not enough. To be at the forefront of academic research the leading universities need to attract the best minds from whatever background. It is unlikely that they're to be found in such high proportions in fee-paying schools, which only educate about 6.5% of Britain's children.

The big question is how to remedy this imbalance. Almost any proposed change to the admission system still allows fee-paying schools to gain an advantage. Their higher number of teachers per pupil means they can provide intensive coaching that helps students get better A level results than they would in a state school. The supreme self-confidence they instil in many pupils is a great advantage at interview. The extra-curricular activities, from music to sport to mountain climbing, look good on the UCAS form and are in decline in many cash-strapped state schools. I think it's time for something more radical.

There are roughly 4 million people aged 15-19 in the UK at present, so there are about 800,000 reaching university age every year. Oxford University has around 3,200 undergraduate places each year, so one might expect one in 250 people to go to Oxford, or say 1 in 300 to allow a margin for foreign students. A 1000 pupil secondary school has around 150 students in each year, so might expect someone to get into Oxford every two years or so.

I propose that Oxford and/or Cambridge should allocate undergraduate places to schools based purely on the number of pupils aged 11-16 years at that school. For most schools the allocation would be a number less than one. The school would "bank" each year's allocation until they have more than 0.5 places at one university in the bank, and have a pupil who the school believes would benefit from going to that university. The bank account would then be debited one place, taking the balance below zero.

It would be up to the school to choose which pupil(s) to send, using any criteria they think appropriate. I'm sure most would take this responsibility seriously, but if St. Cakes (motto Quis paget entrat) decides to send the boy whose parents make the largest donation to the headmaster's drinks cabinet that's their business. I'm sure they'd welcome the ensuing publicity.

The side effects of this policy might be interesting. Would parents move to be near a "failing" school that has lots of places in the bank but no pupils capable of benefiting from a university education? The influx of children from homes with high expectations might do a lot to revive such "failing" schools. Would Eton form a multi-academy trust with lots of inner-city schools to boost its pupil numbers and so be allocated enough places for its fee-paying pupils? Probably, so the allocation rules will have to define a "school" as occupying buildings in close proximity.

Footnote: the state school I went to had 180 pupils in each year. I was the only one of my year group to go to Cambridge, and another of my year got in to Oxford. This was better than average for a state school and reflects the privileged upbringing of many of its pupils. I was lucky enough to be raised in a home full of books, where it was expected that I and my three siblings would go to university, with parents who willingly paid our maintenance costs, and who moved house to be in the catchment area of a good school. I benefited hugely from all these advantages, and it's wrong that people without such advantages are denied the benefits.

Saturday, 3 February 2018

Samyang 500mm 1:6.3 DX mirror lens

Long focal length lenses for SLR cameras are mostly one of two types - refractors (true lenses) or "mirror" lenses (actually Cassegrain telescopes). Large aperture long lenses are big, heavy, and expensive, but they can perform really well. Mirror lenses are much smaller, lighter, and usually a lot cheaper. However they are fixed aperture, usually manual focus, and have notable optical limitations.

500mm f/6.3 mirror lens

Three years ago I bought a Samyang 500mm f/6.3 mirror lens. (What appears to be the same lens is sold under several other brand names. Mine is clearly labelled "made in Korea" though.) It was sold as "ex demo" but I can't see any sign it wasn't brand new. It comes with a screw-on lens hood not shown in the above photo. The lens has a T-thread (M42x0.75) mount, so I've used a T-thread to M42x1 adapter and an M42x1 to EOS adapter (which I already had) to attach it to my Canon 100D. The EOS adapter has a "focus chip" - this tells the camera it's got a Canon 50mm f/1.8 lens attached and allows the focus confirm system to work on well lit subjects. f/6.3 is about the smallest aperture the EOS 100D's focus system can cope with.

Stedi Stock camera shoulder brace

In another blog post I described how I've mounted the camera plus lens on a shoulder brace. I've recently been having some fun using this set up to photograph some birds in my garden. All the following pictures are taken through a double glazed window, which is sub optimal, so better pictures should be possible.

Fieldfare in my garden

This first picture is of a fieldfare (Turdus pilaris). This unprocessed picture is a bit dull, and if you zoom in (click on the picture to see it on Flickr, then click on it again to zoom in) you can see it's really not very sharp.

Fieldfare in my garden

I'm no expert in processing photographs but I thought I'd have a go using GIMP, an open source programme available on many operating systems. All I've done here is to boost the contrast a little, adjust the brightness, and use an "unsharp mask" filter to make it a bit less soft. I think it's a significant improvement.

On this more recent picture (a green woodpecker (Picus viridis)) I actually managed to get the bird in focus. I've done similar processing and am pleased with the glint in the eye and the detail in the feathers.

Woodpecker in my garden

This picture also shows one of the optical defects of mirror lenses, the doughnut shapes formed around out of focus highlights. The ethereal ring shape in front of the bird's shoulder is caused by a berry on a plant stem in the foreground. Some people find this sort of aberration very annoying. I don't think I mind it too much.

The most severe problem with this particular lens design is the difficulty in focusing. Its focal distance goes from 2m to infinity (and beyond) in a quarter turn of the lens body. If they'd only made this nearer a full turn it would be much easier to use. Some people have remedied this by attaching long levers or gearing systems. I've yet to try anything like this.

Tuesday, 30 January 2018

Sussex pond pudding

Last weekend I made a Sussex pond pudding and, as I occasionally do, I posted a picture of it on Facebook. The ensuing discussion included both a request for my recipe and a link to a recent Guardian article "the perfect... Sussex pond pudding".

Here's my recipe, fleshed out with a few pictures. I've taken it from a slim booklet of traditional Sussex recipes I bought a few years ago in a branch of "Sussex Stationers", a now defunct budget bookshop chain.

1/ Make suet pastry from 8 oz self raising flour, 4 oz suet, 2 oz breadcrumbs, pinch of salt, and enough water to make a soft dough. I use a food processor as I don't have the knack of making pastry by hand. The Guardian's recipe omits breadcrumbs, so won't have the brown flecks (from the crust) you can see in my picture.

Sussex pond pudding

2/ Roll out the pastry and line a buttered 2 pint pudding bowl. To make a better fit to the steep sided bowl I cut out three triangles so the remainder is like a radiation warning symbol shape. I then join these cut edges (after dampening with water) inside the bowl. Trim around the top edge then combine all the pastry offcuts and roll out to make a circular lid.

Sussex pond pudding

3/ Wash an unwaxed lemon and cut up 4 oz of butter and allow to soften. Stab the lemon many times with a skewer, then wrap in the butter, then roll in 4 oz of dark brown sugar. Place in the lined bowl with any left over sugar. The Guardian's version slashes the lemon with a knife and simply surrounds it with cubed butter and sugar which looks a lot easier.

Sussex pond pudding Sussex pond pudding

4/ Attach the lid and trim the edges, then cover with a circle of parchment and an aluminium foil lid with room for expansion. It domes right up as it cooks.

Sussex pond pudding Sussex pond pudding

5/ Steam for 3 to 4 hours (or a bit more), turn out on to a plate and eat.

Sussex pond pudding