Rob Manuel’s British Council Tile / Bus Fabric Sim

Rob’s British Council Tile / Bus Fabric Sim — described here: Amstrad BASIC that approximates the tiling schemes that a local council might have used for a municipal building in the 1970s — is a joy. So few colours!

No, really: this *was* the seat pattern on Western SMT buses circa 1979

Because I care (and don’t if you don’t), here’s the Locomotive BASIC source, lovingly typed into the Caprice32 emulator then extracted as text using iDsk:


10 ' British Council Tile / Bus Fabric Sim
20 ' by Rob Manuel 2018
30 '
40 ' z/x - change char up/down (ascii)
50 ' space - random palette
60 ' c - show ascii val, inks & pause
70 ' v - random character (128+ ascii)
80 ' b - random char and cols
90 ' n - fill with same line & pause
100 'i - input ascii value
110 '
120 ON BREAK GOSUB 260:MODE 1:LOCATE 1,26
130 DEF FNs=INT(RND*255)
140 SYMBOL 255,FNs,FNs,FNs,FNs,FNs,FNs,FNs,FNs
150 DEF FNp=INT(RND*4)
160 DEF FNi=INT(RND*26)
170 GOSUB 470
180 GOSUB 270
190 o$="":i$=INKEY$
200 IF i$<>"" THEN GOSUB 380
210 FOR i=1 TO 40
220 w$=CHR$(14)+CHR$(FNp)+CHR$(15)+CHR$(FNp)
230 w$=w$+CHR$(c):o$=o$+w$:NEXT i
240 store$=o$
250 PRINT o$;:GOTO 190
260 CALL &BC02:PAPER 0:PEN 1:END
270 aa=FNi:bb=FNi:cc=FNi:dd=FNi
280 INK 0,aa:INK 1,bb:INK 2,cc:INK 3,dd
290 BORDER aa
300 GOSUB 320:RETURN
310 IF c>255 THEN c=32:IF c<32 THEN c=255
320 LOCATE 1,1:PAPER 0:PEN 1
330 PRINT "C:"c;
340 PRINT CHR$(c);
350 PRINT " ";
360 PRINT "I:"aa;bb;cc;dd;
370 LOCATE 1,26:RETURN
380 IF i$=" " THEN GOSUB 270:RETURN
390 IF i$="z" THEN c=c-1:GOSUB 310:RETURN
400 IF i$="x" THEN c=c+1:GOSUB 310:RETURN
410 IF i$="c" THEN GOSUB 310:CALL &BB18:RETURN
420 IF i$="i" THEN LOCATE 1,1:INPUT "ASCII?",c:GOSUB 310:RETURN
430 IF i$="v" THEN GOSUB 470:GOSUB 310:RETURN
440 IF i$="b" THEN GOSUB 270:GOSUB 470:GOSUB 310:RETURN
450 IF i$="n" THEN FOR i=1 TO 25:PRINT store$;:NEXT:CALL &BB18:RETURN
460 RETURN
470 c=INT(RND*128)+127:RETURN

And if you really care, here’s an emulator snapshot — BritishCouncilTileSim.zip

Update: I modified the code slightly (essentially, all INT(RND*n) to RND MOD n) so it would compile with Hisoft Turbo Basic. It works! It’s faster!

Snapshot: BritishCouncilTileSimCompiled.zip

Apple IIgs: before and after graphics

Unless you have the heavy analogue Apple CRT that was specially made for it, composite video output on the Apple IIgs is utterly dismal:

Apple IIgs: composite to LCD display

Adding an Apple IIgs → SCART cable through a SCART to HDMI converter is much better:

Apple IIgs: via SCART and HDMI

There’s still a little bit of shimmer to the background, but at least text is legible.

OpenSCAD might not’ve been the best choice here

OpenSCAD might not’ve been the best choice here

OpenSCAD might not’ve been the best choice here

Yup, lots of circles, intersections, differences and offsets went into this attempt at the logo of my favourite museum.

For the determined/demented, here’s the source. It’s probably not that useful for learning OpenSCAD, as it’s written in my typical “carve away all the bits that don’t look like an elephant” style:

// akm logo - why yes this *is* a good tool to use ...

// constants for octagon maths
r1 = 1 - sqrt(2) / 2;           // ~0.292893
r2 = sqrt(r1);                  // ~0.541196
x1 = (sqrt(2) - 1) / 2;         // ~0.207107

sc = 100;                       // size factor
t = 4;                          // line thickness
bigt = 7;                       // strapwork gap thickness
$fn = 256;                      // OpenSCAD circle smoothness

module petal() {
    intersection() {
        translate([ sc * x1, sc * x1])circle(r = sc * r2);
        translate([-sc * x1, sc * x1])circle(r = sc * r2);
    }
}

module hollow_petal() {
    difference() {
        offset(r =  t / 2)petal();
        offset(r = -t / 2)petal();
    }
}

module inner_lobe() {
    difference() {
        for (i = [0:3]) {
            rotate(i * 90 + 45)offset(r = t / 2)petal();
        }
        for (i = [0:3]) {
            rotate(i * 90 + 45)offset(r = -t / 2)petal();
        }
    }
}

module ring() {
    for (i = [0:3]) {
        rotate(i * 90)difference() {
            intersection() {
                inner_lobe();
                union() {
                    offset(r = -bigt / 2)petal();
                    rotate(45)offset(r = t / 2)petal();
                }
            }
            rotate(90)offset(r = bigt / 2)petal();
        }
    }
}

module logo() {
    union() {
        ring();
        for (i = [0:3]) {
            rotate(90 * i)union() {
                intersection() {
                    hollow_petal();
                    rotate(-90)offset(r = -bigt / 2)petal();
                }
                difference() {
                    intersection() {
                        hollow_petal();
                        rotate(45)offset(r = -bigt / 2)petal();
                    }
                    rotate(-90)offset(r = bigt / 2)petal();
                }
                
                difference() {
                    hollow_petal();
                    offset(r = bigt / 2)union() {
                        rotate(-90)petal();
                        rotate(45)petal();
                    }
                }       
            }
        }
    }
}

logo();

Flashprint except without the prints falling over

I use a FlashForge Creator Pro 3D printer for work. It’s okay, but I wouldn’t recommend it: you have to manually level the print bed (ಠ_ಠ), you can’t print via USB, it pretends to be a knock-off MakerBot (same USB ID: naughty naughty) and its slicing software is a mishmash of GPL and other code all bundled up in one proprietary lump. It also doesn’t used g-code, which is a bit poo.

3d print fail
As Vik said: “The Flying Spaghetti Monster has cast forth His noodly appendage and made output in His own image.”

I have been having endless trouble will tall prints losing adhesion, falling over, and leaving a noodly mess everywhere. I’ve fixed it by making some manual changes to the config file, the process as described here: Flashprint advanced print settings by editing the default.cfg configuration file. What I changed was:

[brim]
enable = true                  # valid range {true, false}, default is false # CHANGED
extruderId = 0                  # valid range {0, 1}, default is 0
margin = 10.0                    # valid range [1.0, 10.0], default is 5.0   # CHANGED
layerCnt = 2                    # valid range [1, 5], default is 1           # CHANGED
speed = 60                      # valid range [10, 200], default is 60
excludeInterior = true         # valid range {true, false}, default is false # CHANGED

This makes a colossal double-width, double thickness brim around the prints so that they will not topple. I’m very happy with the results so far.

Rather than mucking about with config files, if you enable “Expert Mode” in Flashprint’s preferences:

Then you can make a brim that stops prints coming off the print bed.

expert brim settings = prints not fall over

And lo, there was much rejoicing …

23½ hour print job done! (They’re LipSync shells, btw)

Eugene’s fishing line header hack for Raspberry Pi Zero

0.38 mm / 5.4 kg test Trilene threaded through Raspberry Pi Zero header holes
0.38 mm / 5.4 kg test Trilene threaded through Raspberry Pi Zero header holes holds male jumper wires snugly without soldering

Eugene ‘thirtytwoteeth’ Andruszczenko (of Game Boy Zero – Handheld Edition fame) posted a neat idea to help your Raspberry Pi Zero take jumper wires without soldering. He threaded fishing line through the 40 hole header, making an interference fit for male header pins. I tried it with 0.38 mm Trilene, which worked rather well.

A few seconds from a 12- hour print job

A few seconds from a 12- hour print job

A few seconds from a 12- hour print job

Instagram filter used: Lo-fi

View in Instagram ⇒

… which of course failed 95% through:

As Vik said: “The Flying Spaghetti Monster has cast forth His noodly appendage and made output in His own image.”

You gotta brim all the time.

Rose plots

source by Dan Anderson: https://www.openprocessing.org/sketch/519299
Enlarged and plotted on a Roland DXY pen plotter: 0.7 mm black pen on design vellum.

Full page:

Even if the 0.7 mm pen is a bit chunky for fine guilloché effects, the plotter output is pretty crisp. Here’s a detail at full resolution:

select this to see the full resolution scan. Original is just under 6 cm wide

Unfortunately, an earlier attempt to print this figure using a fresh-out-the-box 20+-year-old HP SurePlot ¼ mm pen on glossy drafting paper resulted in holes in the paper and an irreparably gummed-up pen. If anyone knows how to unblock these pens, I’m all ears …

birb chirper v2.0

This is one of those toys that you whirl around on a piece of string and it makes a chirping sound like a flock of sparrows. I have no idea what they’re called, so I called it birb_chirper.

Print Settings

Printer: Reach 3D
Rafts: Doesn’t Matter
Supports: Doesn’t Matter
Resolution: 0.3 mm
Infill: 0%

Notes: This is a thin-walled model, so use at least two shells and no infill for smooth walls.

Post-Printing

Take a piece of thin string about 1 metre long (I used micro-cord, very fine paracord), pass it through the hole in the tip, then tie off a jam knot that’s big enough to stop in the hole in the top but still pass back through the slot in the side. Now whirl the thing around fast by the string, and it should start to chirp.

This is intended for the amusement of small children and the annoyance of adults.

How I Designed This

The tip of this thing is an ogee curve. I’ve included my library for creating simple ogee and ogive profiles in OpenSCAD.

// ogive-ogee example
// scruss, 2018
use <ogive_and_ogee.scad>;
ogive(20, 35);
translate([0, -5])text("ogive(20,35)", size=3);
translate([30, 0])ogee(20, 35);
translate([30, -5])text("ogee(20,35)", size=3);

Download: Thingiverse —birb_chirper by scruss. Local copy: birb_chirper.zip

Plotting a card …

I made this two-colour plotted card for the MeFi “holiday card exchange – v.e.” thing. Pen plotter is a Roland DG DXY-1300 (1990s) using Roland 0.3 mm fibre-tip pens. Plot size is 123 × 91 mm, and is driven entirely from Inkscape 0.92.

Building (but not necessarily running) Amiberry on Raspberry Pi 3

I might not have Amiberry — an optimized Amiga emulator for Raspberry Pi — running quite yet, but the build instructions at midwan/amiberry are a bit lacking. If you want to compile it under Raspbian Stretch, you’ll need the following packages:
sudo apt install libsdl2-dev libxml2-dev libxml2-utils libsdl2-ttf-dev libsdl2-image-dev
This will at least allow you to get it to build correctly with:
make -j2 PLATFORM=rpi3-sdl2-dispmanx
More later when/if I get it working.

CP/M 3.1 manuals as PDF

The Unofficial CP/M Web site uses some very old file formats. As almost no-one can easily run Amí 3 to read the manuals these days, here are the CP/M 3.1 manuals from that site converted to PDF:

Raspblocks: Blocks-based Python coding for Raspberry Pi

Raspblocks is a new Blocks-based web programming environment for Raspberry Pi. You don’t even need to write the code a Raspberry Pi, but the Python 3 code it produces will need to be transferred to a Raspberry Pi to run.

For maximum authenticity (and slowness), I fired up  http://www.raspblocks.com/ on a Raspberry Pi Zero over VNC. It took a minute or more to load up the site in Chromium, but creating a simple program was all easy dragging and dropping:

The code it produced was pretty much exactly what you’d write by hand:

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.OUT)

while True:
    GPIO.output(26,True)
    time.sleep(1)
    GPIO.output(26,False)
    time.sleep(1)

And, as you might expect, the code make an LED connected to GPIO 26 turn on and off. Science!

Raspblocks isn’t as polished as its more established rival  EduBlocks, but Raspblocks doesn’t need any software installed. Edublocks installs its own Node.js-based web service, which would be painfully slow on a Raspberry Pi Zero. Raspblocks’ code needs to be run manually from a terminal, but I’d put up with that any day over having yet another Node server distribution installed under /opt.

Synthesizing simple chords with sox

SoX can do almost anything with audio files — including synthesize audio from scratch. Unfortunately, SoX’s syntax is more than a bit hard to follow, and the manual page isn’t the most clear. But there is one example in the manual that gives a glimpse of what SoX can do:

play -n synth pl G2 pl B2 pl D3 pl G3 pl D4 pl G4 \ 
     delay 0 .05 .1 .15 .2 .25 remix - fade 0 4 .1 norm -1

While it plays a nice chord, it’s not obvious how to make audio files from this process. I have a project coming up that needs a few simple guitar chords, and with much trial and error I got SoX to spit out audio files. Here’s what I keyed into the shell:

cat guitar.txt | while read chord foo first third fifth
do
  echo "$chord" :
  sox -n \ 
    -r 16000 -b 16 "chord-${chord}.wav" \
    synth pl "$first" pl "$third" pl "$fifth" \
    delay 0 .05 .1 \ 
    remix - \ 
    fade 0 1 .095 \ 
    norm -1
done

with these lines in the file “guitar.txt”

G   :  G2  B2  D3
C   :  C3  E3  G4
D   :  D3  F#4 A3
F   :  F3  A3  C4
A   :  A3  C#4 E4
E   :  E2  G#3 B3
Em  :  E2  G3  B3

How the SoX command line breaks down:

    • -n —use no input file: SoX is going to generate the audio itself
    • -r 16000 -b 16 “chord-${chord}.wav” — with a sample rate of 16 kHz and 16-bits per sample, write to the output file “chord-….wav”
    • synth pl “$first” pl “$third” pl “$fifth” —synthesize three plucked tones read from the file
    • delay 0 .05 .1 —delay the second tone 0.05 s after the first and likewise the third after the second. This simulates the striking of guitar strings very slightly apart.
    • remix – —mix the tones in an internal pipe to the output
    • fade 0 1 .095 —fade the audio smoothly down to nothing in 1 s
    • norm -1 —normalize the volume to -1 dB.

The chords don’t sound great: they’re played on only three strings, so they sound very sparse. As my application will be playing these through a tiny MEMS speaker, I don’t think anyone will notice.

Update: well, now I know how to do it, why not do all 36 autoharp strings and make the “magic ensues” sound of just about every TV show of my childhood?

Glissando up:

sox -n -r 48000 -b 16 autoharp-up.wav synth pl "F2" pl "G2" pl "C3" pl "D3" pl "E3" pl "F3" pl "F#3" pl "G3" pl "A3" pl "A#3" pl "B3" pl "C4" pl "C#4" pl "D4" pl "D#4" pl "E4" pl "F4" pl "F#4" pl "G4" pl "G#4" pl "A4" pl "A#4" pl "B4" pl "C5" pl "C#5" pl "D5" pl "D#5" pl "E5" pl "F5" pl "F#5" pl "G5" pl "G#5" pl "A5" pl "A#5" pl "B5" pl "C6" delay 0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 1 1.05 1.1 1.15 1.2 1.25 1.3 1.35 1.4 1.45 1.5 1.55 1.6 1.65 1.7 1.75 remix - fade 0 6 .1 norm -1

Glissando down:

sox -n -r 48000 -b 16 autoharp-down.wav synth pl "C6" pl "B5" pl "A#5" pl "A5" pl "G#5" pl "G5" pl "F#5" pl "F5" pl "E5" pl "D#5" pl "D5" pl "C#5" pl "C5" pl "B4" pl "A#4" pl "A4" pl "G#4" pl "G4" pl "F#4" pl "F4" pl "E4" pl "D#4" pl "D4" pl "C#4" pl "C4" pl "B3" pl "A#3" pl "A3" pl "G3" pl "F#3" pl "F3" pl "E3" pl "D3" pl "C3" pl "G2" pl "F2" delay 0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 1 1.05 1.1 1.15 1.2 1.25 1.3 1.35 1.4 1.45 1.5 1.55 1.6 1.65 1.7 1.75 remix - fade 0 6 .1 norm -1

Could maybe use some reverb in there for the ultimate nostalgic effect.

 

MQTT Talk tonight

I’m talking at the Raspberry Pi Toronto Meetup tonight, and if all goes well, the Net-Connected Cowbell will make an appearance:

My slides: MQTT.odp

Links:

3D printed back cover for 6502 badge

Update, 2017-12-03: So of course, as soon as I show this to someone, they ask: “Can it stand up like a display case?” It can now!

STL file and OpenSCAD source for rev 2: VCF-6502-badge.zip
(licence: CC BY-NC-SA 2.5 CA)

Thingiverse: https://www.thingiverse.com/thing:2687960

Rev 1: This worked better than I could have hoped, and so the 6502 40th Anniversary Computer Badge now has a snug-fitting case to prevent shorting, and to keep the batteries in place.

fritzing: Generic 4×4 Keypad part

This needs work, but I made this keypad part for Fritzing:

Part file (zipped): Generic_4x4_Keypad.zip

You’ll see these parts described as variations on “4×4 Matrix 16 Keypad Keyboard Module 16 Button” on ebay. They’re very simple: if you press a button (say S7), the row pins (R1-4; R2 for S7) and the column pins (C1-C4; C3 for S7) are connected. So pins R2 and C3 are connected when S7 is pressed. You can use the Arduino Keypad library to talk to these, but do remember they use up 8 I/O pins.

It’s not internally routed in Fritzing, and you likely won’t be able to use it for any kind of schematic work, but who uses Fritzing for anything other than pretty pictures?

Creating a systemd user service on your Raspberry Pi

Flushed with success from yesterday’s post where I made my first systemd service, I got carried away and wanted to show you how to create a service that runs as a regular user.

A fairly common question on the Raspberry Pi Forums is “How do I run a script every time I reboot?”. The traditional answer (and one I’ve given more than once) is to add a @reboot clause to your crontab. This will indeed run a command when the computer reboots, but it will run pretty early on in the boot sequence when there’s no guarantee of network or time services. So the usual remedy is a bit of a kludge:

@reboot sleep 60 && 

This waits a full minute after rebooting, then executes the command. Network and time services are really likely to be available, but it’s not very elegant. Cron also has some weird gotchas with PATH settings, so while it’s ubiquitous and has worked for decades, it’s not easy to get working. Systemd, however, has a much better way of doing it, and better yet, you can do it all without ever hitting sudo.

I’ll take as a basis for this post the forum query “python and crontab”. The asker wanted to log the time when their Raspberry Pi had rebooted, but they’ve hit the usual problem that the clock didn’t have the right time when their script was triggered, so the log was useless.

(I’m not going to do exactly what the forum poster did, but this is more a demo of a systemd user service than recreating their results.)

First off, here’s the script to log the time to a file (saved as ~/bin/boot_time.py):

#!/usr/bin/python3
from time import strftime
with open("/home/pi/logs/boot_time.txt", "a") as log:
 log.write(strftime("%d-%m-%Y,%H:%M:%S\n"))

I’d have done this as a shell script, but the OP used Python, so why fight it?

FUN FACT: Under most Linux flavours, if you create a bin folder in your home directory, it’s automatically added to your path. So I could just type boot_time.py and the shell would find it.
(You might have to log out and log back in again for the shell to review your path.)

In order to get that to run, I need to do a little housekeeping: make the script executable, and make sure the logs folder exits:

chmod +x ~/bin/boot_time.py
mkdir -p ~/logs

Now we need to do the bits that pertain to systemd. First off, you must make a folder for user services:

mkdir -p ~/.config/systemd/user

NOTE: mkdir -p … is useful here as it makes the directory and any parent directories that don’t exist. It also doesn’t complain if any of them already exist. It’s kind of a “make sure this directory exists” command. Make friends with it.

And here’s the service file, which I saved as ~/.config/systemd/user/boot_time_log.service:

[Unit]
Description=boot time log
DefaultDependencies=no
After=local-fs.target time-sync.target

[Service]
Type=oneshot
ExecStart=/home/pi/bin/boot_time.py

[Install]
WantedBy=default.target

The service file does the following (even if I’m slightly mystified by some of the headings …):

  • Unit
    • Description — a plain text name for the service. This appears in logs when it starts, stops or fails.
    • DefaultDependencies — as this service runs once at boot-up, it doesn’t need the normal systemd functions of restarting and shutting down on reboot. Most service files omit this line.
    • After — here we tell systemd what service targets must be running before this service is started. As we need to write to a file and have the right time, the local-fs.target and time-sync.target seem sensible.
  • Service
    • Type — this is run once, so it’s a oneshot rather than the usual simple service.
    • ExecStart — this is the command to run when the service is required.
  • Install
    • WantedBy — tbh no idea what this does, but if you omit it the service won’t install. Found the answer in this SE, and it works. So I guess what it does is make the service not fail

Finally, you enable the service with:

systemctl --user enable boot_time_log.service

Next time you reboot, the time will be appended to the log file ~/logs/boot_time.txt.

Unlike most (that is, Type=simple) services, it’s perfectly fine if this one spends most of its time inactive:

$ systemctl status --user boot_time_log.service
● boot_time_log.service - boot time log
 Loaded: loaded (/home/pi/.config/systemd/user/boot_time_log.service; enabled;
 Active: inactive (dead) since Sun 2017-10-22 22:17:56 EDT; 1h 5min ago
 Process: 722 ExecStart=/home/pi/bin/boot_time.py (code=exited, status=0/SUCCES
 Main PID: 722 (code=exited, status=0/SUCCESS)

It has executed successfully, so the process doesn’t have to stick around.

Combined Restart / Shutdown Button for Raspberry Pi

A very simple systemd service for Raspberry Pi that provides a software-controlled restart / shutdown button. Code: scruss/shutdown_button

Use

Default behaviour is:

  • your Raspberry Pi will reset if the button is held for more than two seconds but fewer than five seconds;
  • your Raspberry Pi will shut down if the button is held for more than five seconds.

By default, the software assumes the switch is connected to pin BCM 27. Both the pin and the timing can be changed in the Python source file.

Requirements

Hardware

  • A Raspberry Pi (tested on a model 2B, 3B and Zero, and on a model B after minor software modification)
  • A normally open, momentary contact button. I use surplus ATX power buttons (as used on desktop PCs), as they’re cheap and come with a handy set of wires and header connectors. Virtually any button will do the job, though. Just make sure it’s normally open (push to close).

Software

  • A Debian-based operating system that uses systemd (tested on Jessie and Stretch)
  • the python3-gpiozero package to provide GPIO Zero (tested on version 1.4.0)

Installation

Hardware

40-pin GPIO connector (B+, 2B, 3B, Zero)

Connect the button between GPIO 27 and GND. If you use an ATX power button and a Raspberry Pi with a 40-pin GPIO header, connect it across the seventh column from the left:

            -
· · · · · ·|·|· · · · · · · · · · · · · 
· · · · · ·|·|· · · · · · · · · · · · · 
            -

This shorts GPIO 27 (physical pin 13) to ground (physical pin 14) when the button is pressed.

26-pin GPIO connector (models B and A only)

GPIO 27 is not exposed on the original Raspberry Pi header, so GPIO 17 is a reasonable option. If you use an ATX power button and a Raspberry Pi with a 26-pin GPIO header, connect it across the fifth and sixth columns of the second row:

 . . . . ._. . . . . . . .
 . . . .|. .|. . . . . . .
          -

You will also need to change [line 7 of shutdown_button.py](https://github.com/scruss/shutdown_button/blob/master/shutdown_button.py#L7) to read:

use_button=17

Software

The software is installed with the following commands:

sudo apt install python3-gpiozero
sudo mkdir -p /usr/local/bin
chmod +x shutdown_button.py
sudo cp shutdown_button.py /usr/local/bin
sudo cp shutdown_button.service /etc/systemd/system
sudo systemctl enable shutdown_button.service
sudo systemctl start shutdown_button.service

Troubleshooting

Enabling the service should produce output very similar to:

Created symlink /etc/systemd/system/multi-user.target.wants/shutdown_button.service → /etc/systemd/system/shutdown_button.service.

You can check the status of the program at any time with the command:

systemctl status shutdown_button.service

This should produce output similar to:

● shutdown_button.service - GPIO shutdown button
   Loaded: loaded (/etc/systemd/system/shutdown_button.service; enabled; vendor 
   Active: active (running) since Sat 2017-10-21 11:20:56 EDT; 27s ago
 Main PID: 3157 (python3)
   CGroup: /system.slice/shutdown_button.service
           └─3157 /usr/bin/python3 /usr/local/bin/shutdown_button.py

Oct 21 11:20:56 naan systemd[1]: Started GPIO shutdown button.

If you’re seeing anything other than Active: active (running), it’s not working. Does the Python script have the right permissions? Is it in the right place? If you modified the script, did you check it for syntax errors?

The output from dmesg will show you any error messages generated by the service.

Modifications

If you use a HAT/pHAT/Bonnet/etc. with your Raspberry Pi, check pinout.xyz to see if it uses BCM 27. If you do need to change the pin, best to pick one that doesn’t have a useful system service like serial I/O or SPI. If you’re using an ATX button with a two pin connector, make sure you choose a pin physically adjacent to a ground pin.

If you modify the timing, please ensure that you keep the shutdown button press duration longer than the reboot one. Otherwise you’ll only be able to shut down.

Notes

You should not need to reboot to enable the service. One machine of mine — a Raspberry Pi Zero running Raspbian Stretch — did need a reboot before the button worked.

The reboot code is based on the Shutdown button example from the GPIO Zero documentation.

This is not the only combined shutdown/reset button project to use GPIO Zero. gilyes/pi-shutdown also does so, but pre-dates the implementation of the various hold time functions in GPIO Zero.

GPIO 27 was used, as it’s broken out onto a physical button on the Adafruit PiTFT+ display I own.

This is my first systemd service, and I’m still at the “amazed it works at all” stage. The service file may not contain the ideal configuration.

Connector Pinouts

From GPIO Zero’s pinout command

40 pin

   3V3  (1) (2)  5V    
 GPIO2  (3) (4)  5V    
 GPIO3  (5) (6)  GND   
 GPIO4  (7) (8)  GPIO14
   GND  (9) (10) GPIO15
GPIO17 (11) (12) GPIO18
GPIO27 (13) (14) GND   
GPIO22 (15) (16) GPIO23
   3V3 (17) (18) GPIO24
GPIO10 (19) (20) GND   
 GPIO9 (21) (22) GPIO25
GPIO11 (23) (24) GPIO8 
   GND (25) (26) GPIO7 
 GPIO0 (27) (28) GPIO1 
 GPIO5 (29) (30) GND   
 GPIO6 (31) (32) GPIO12
GPIO13 (33) (34) GND   
GPIO19 (35) (36) GPIO16
GPIO26 (37) (38) GPIO20
   GND (39) (40) GPIO21

26 pin

   3V3  (1) (2)  5V    
 GPIO0  (3) (4)  5V    
 GPIO1  (5) (6)  GND   
 GPIO4  (7) (8)  GPIO14
   GND  (9) (10) GPIO15
GPIO17 (11) (12) GPIO18
GPIO21 (13) (14) GND   
GPIO22 (15) (16) GPIO23
   3V3 (17) (18) GPIO24
GPIO10 (19) (20) GND   
 GPIO9 (21) (22) GPIO25
GPIO11 (23) (24) GPIO8 
   GND (25) (26) GPIO7