Skip to content

Software

Peter Markley edited this page May 15, 2021 · 20 revisions

Note: These instructions are for Raspberry Pi OS version Buster.

Contents

Initial Setup

First, you need to install Raspberry Pi OS on the Micro SD card. Then, hook everything up, including a temporary monitor/keyboard/mouse, and as the last step attach the power supply. This will turn on the Raspberry Pi.

Follow the setup prompts in the graphical interface until they're finished. This should include a software update and a reboot.

For headless operation, you should open Raspberry menu > Preferences > Raspberry Pi Configuration and change "Boot" to say "To CLI." Henceforth when you reboot with a monitor connected, you may be prompted to log in using a text interface. After logging in this way, you can always enter the graphical environment by typing startx and pressing Enter.

In the "Interfaces" tab, consider also enabling SSH, for remote login in case maintenance is needed without a monitor.

Sound

Make sure your USB audio interface is connected. Right-click the speaker icon in the menu bar, and under "Autio Outputs" choose your USB device from the list.

For systemd processes, you will also need to edit a system file using vi or nano:

sudo vi /usr/share/alsa/alsa.conf

Change this line:

defaults.pcm.card 0

It should be changed to say:

defaults.pcm.card 1

Install Packages

You will need to install the following using apt-get:

  • php
  • pigpio
  • ntp

Combined into one command:

sudo apt-get install php pigpio ntp

Custom Installations

To get Clockworth running, you will need a handful of utilities from outside the Raspberry Pi OS software repositories.

They have the following dependency structure:

Clockworth
  |
  ├── Sunwait
  |
  └── Git-LFS
        |
        └── Golang

Golang

Download Go version 1.10.

wget https://storage.googleapis.com/golang/go1.10.linux-armv6l.tar.gz

Extract and install.

sudo tar -C /usr/local -xzf go1.10.linux-armv6l.tar.gz
sudo ln -s /usr/local/go/bin/go /usr/bin/go
sudo mkdir /root/gocode

Git-LFS

Dependencies:

  • Golang (needed to download/compile/install)

We need root privileges for this part:

sudo -s

Set this environment variable:

export GOPATH=/root/gocode

Download Git-LFS:

go get github.com/github/git-lfs

Compile:

cd /root/gocode/src/github.com/git-lfs/git-lfs/
make

Install:

cp -p /root/gocode/src/github.com/git-lfs/git-lfs/bin/git-lfs /usr/bin/

Return to the default user privilege level, and run git lfs install:

exit
git lfs install

Sunwait

Let's make a work space in our home directory:

mkdir ~/bin
cd ~/bin/

Download:

git clone https://github.com/petermarkley/sunwait.git

Compile:

cd sunwait/
make

Install:

sudo cp -p sunwait /usr/bin/

Clockworth

Dependencies:

  • Git-LFS (needed to download/install)
  • Sunwait (needed to run properly)

Download

I like to put Clockworth in the pre-established ~/Music directory:

cd ~/Music/
git clone https://github.com/petermarkley/clockworth.git

Note: Because Clockworth uses Git-LFS, downloading as a ZIP file will not work. This will result in pointer files instead of real ones.

Enter new directory:

cd clockworth/

If the download worked properly, you should see larger file sizes in the sounds/drafts/ and art/ directories:

 $ ls -lh art/
total 13M
-rw-rw-r--. 1 pi pi 2.9M Sep  3  2020 clockworth-engraving-4K.jpg
-rw-rw-r--. 1 pi pi 755K Sep  3  2020 clockworth-engraving-HD.jpg
. . .

 $ ls -lh sounds/drafts/
total 91M
-rw-rw-r--. 1 pi pi 2.0M Sep  3  2020 christ_arose-dawn.wav
-rw-rw-r--. 1 pi pi 1.7M Sep  3  2020 christ_arose-dusk.wav
-rw-rw-r--. 1 pi pi 2.7M Sep  3  2020 count_your_blessings.wav
. . .

If the download did not work, you will see very small files instead:

 $ ls -lh art/
total 52K
-rw-rw-r--. 1 pi pi 132 Sep 13  2020 clockworth-engraving-4K.jpg
-rw-rw-r--. 1 pi pi 131 Sep 13  2020 clockworth-engraving-HD.jpg
. . .

 $ ls -lh sounds/drafts/
total 92K
-rw-rw-r--. 1 pi pi 132 Sep 13  2020 christ_arose-dawn.wav
-rw-rw-r--. 1 pi pi 132 Sep 13  2020 christ_arose-dusk.wav
-rw-rw-r--. 1 pi pi 132 Sep 13  2020 count_your_blessings.wav
. . .

Compile Servo Controller

From /home/pi/Music/clockworth, go into the build directory and run make:

cd build/
make

At this point, you should be able to run sudo ./face home print and watch the servo motors orient themselves to their origin point.

Go ahead and put a notch or score mark at the top so that you can attach the hands in the proper positions later.

Test Chime Output

You should also be able to trigger a chime sound directly, to test the speaker output:

aplay /home/pi/Music/clockworth/sounds/drafts/westminster_15.wav

If there is no sound, check your speaker cables/volume and system audio configuration (see Sound section above).

System Services

From /home/pi/Music/clockworth, go into the system directory:

cd system/

Copy this config file to your home directory:

cp -p ./asoundrc ~/.asoundrc

Alternatively, if you want to adjust the EQ of the sound output, install libasound2-plugin-equal and use the other config file:

sudo apt-get install libasound2-plugin-equal
alsamixer #adjust to taste
cp -p ./asoundrc_equal ~/.asoundrc

Install both systemd services:

sudo cp -p ./clockworth-*.service /etc/systemd/system/
sudo systemctl enable clockworth-face.service
sudo systemctl enable clockworth-tick.service

Enabling the service means that it will start automatically on reboot. If you want to start them now, you may need to do that separately:

sudo systemctl start clockworth-face.service
sudo systemctl start clockworth-tick.service

The servo motors should now point to the correct time, and your clock should start ticking. (It may be sending the ticking sound through HDMI. This should change to the USB inferface once you go headless.)

One-Time Calibration

There is some variation in the analogue signal range from one servo motor to the next. If your clock hands wobble back and forth near twelve, you may need to perform a one-time calibration. The clock is trying to reach a position that's out of range for the feedback signal, so it overshoots every time, doubles back, then overshoots again, etc., until enough time passes that the target position comes back in range.

To fix this, simply edit the source code in build/face.c. Find these two declarations:

#define UPPER_LIMIT         98.0 //percentage of a turn
#define LOWER_LIMIT          4.0 //percentage of a turn

You need to adjust these to make the expected signal range smaller. If the hands wobble before twelve, decrease the UPPER_LIMIT by a few percent. If the hands wobble after twelve, increase the LOWER_LIMIT by a few percent.

Then recompile and restart the SystemD service:

make
sudo systemctl restart clockworth-face.service

(Sometimes this service fails to uninitialize, and you have to either reboot or aggressively kill it ...)

systemctl status clockworth-face.service  #note process ID
sudo kill -9 <pid>
sudo rm /var/run/pigpio.pid

sudo systemctl start clockworth-face.service

If the clock hands still wobble, go back and make the signal range more narrow. If they don't wobble, but now they skip over twelve entirely, the range may be too narrow.

If you are performing the calibration at a time that doesn't trigger the issue, you can adjust the system clock manually:

sudo systemctl stop ntp
sudo date -s "11:55"

When you're done, you can re-sync using NTP:

sudo ntpd -q -g
sudo systemctl start ntp

Chimes

The chiming is a separate system, since there's no persistent process that needs to run all the time.

First, while we're still in /home/pi/Music/clockworth/system, copy the configuration file to your home directory:

cp -p ./config.json ~/.clockworth.json

If you want to make changes to the configuration file, you can do so now by editing ~/.clockworth.json. There is an in-progress GUI for this here, but for now you'll need to use a text editor.

At the very least, you should edit this line of the config file with your own GPS coordinates, so that you don't hear sunrise and sunset chimes at inappropriate times of the day:

"location": "48.876667S 123.393333W",

Make sure to use the same coordinate format so it's compatible with Sunwait. From the output of sunwait help:

latitude/longitude coordinates: floating-point degrees, with [NESW] appended.

Now basically, all we need is a cron job that runs every minute from a PHP file in the Clockworth scripts/ directory. We will also point it to the config file you just made.

crontab -e

Enter the following line:

* * * * * /usr/bin/php /home/pi/Music/clockworth/scripts/chime.php -f /home/pi/.clockworth.json -v -l  >>/home/pi/.clockworth.log 2>&1 && /usr/bin/tail -n 1024 /home/pi/.clockworth.log > /home/pi/.clockworth.log~ && mv /home/pi/.clockworth.log~ /home/pi/.clockworth.log

This will create a log file in your home directory. To prevent it from growing indefinitely, the above command will enforce a maximum length by trimming from the beginning of the file.

Note: Make sure that everything is in full paths, instead of relative. The cron job environment is different from the command line environment, so ambiguity can create problems.

Checking Chime Logs

The log file at /home/pi/.clockworth.log should have a single line for every chime event. Here is an example:

2021-05-08 01:45:02 pm: Playing file "/home/pi/Music/clockworth/sounds/drafts/westminster_45.wav" from event "Westminster Quarters → Quarter Hours → Three-Quarter-Hour"

More verbose output can be achieved by leaving the -v flag but omitting the -l flag in the cron job.

Read-Only Root

Once you're done with everything else, and you're 100% sure that it's working as expected (even after rebooting), I highly recommend that you follow this guide to make your Raspberry Pi boot in read-only mode. This will help prevent wear on the Micro SD card, or file system corruption from accidental outages. It can also protect against any accidental changes to the software configuration.

Note: If you have a significantly different version of Raspbian or Raspberry Pi OS, proceed with caution! You may need to find and use a more recent guide that's written for your version of the operating system!

If you do use the guide linked above, as an additional step (not shown in the guide) consider editing your /etc/fstab file and commenting out the line that tells it to mount /boot. Just add a pound sign # at the beginning of the line.

Original:

PARTUUID=334dade7-01  /boot           vfat    defaults          0       2

Edited:

# PARTUUID=334dade7-01  /boot           vfat    defaults          0       2