Sunday 26 April 2020

Pimoroni Pirate Audio MP3 server.

Pimoroni of Sheffield have recently introduced a range of PHAT form boards for the Raspberry Pi family of single board computers. Their Pirate Audio range offer high quality MP3 playback via a variety of outputs together with the a 240 x 240 full colour display..

I decided on the Pirate Audio Headphone Amp.

The Components


The board is supplied in an resealable anti-static bag.

 I was so excited when I received the package from Pimoroni, I opened it before taking the photograph.
The PHAT form boards are smaller than the standard HAT boards, they are designed to stack on top of any 40 pin Raspberry PI, but they are specifically designed to have the same board dimensions as the Raspberry Pi Zero. So with the Pirate Audio board, I also bought a Raspberry Pi Zero W, as soldering is not one of my skills,  Pimoroni offer them with  pre-soldered  headers.

 So this is the board itself. The screen is not cracked, the protective plastic sheet has partially lifted. Eventually I will remove it once I have finished working on it.
There are four buttons around the screen and a headphone jack on the laft side.
 You can see how the PHAT form boards fit directly on top of the Pi Zero board.
The back of the board showing the Hi/Lo Gain amplifier option switch. Though it is inside the board sandwich when assembled, the switch can be operated using a suitably sized rod.

Assembly

I had a 64GB Sandisk SD in stock (I buy them when they are on sale at my local supermarkets), but Linux in general has issues with the default ExFAT format and Raspberry Pis cannot boot from them. However it is easy to reformat them to FAT32. See this post for details.

I used the recently released Raspberry Pi Imager to install the latest version of Raspbian Buster.

The new SD card was inserted into the Pi Zero and it was connected to a keyboard, mouse, monitor and a USB Ethernet connector via a powered hub. The USB Ethernet connector speeds up the updates
Once the initial set up was complete, it was time to assemble the boards.
The two boards were offered up and then gently pushed together.
I also had a couple of stand offs that I used to support the front of the board sandwich.

Software Installation


The installation script has some issues. Over the Christmas 2019 holidays, the core music server underwent a major upgrade. Unfortunately this seriously broke the software used on the board.
You can follow the story here.

The only real issue to currently be aware of is that the Mopidy Local service is not included in the install script. It was included in the base Mopidy repository, but was split off during the upgrade.

It is easy to install:
sudo apt-get install mopidy-local
After that it is all set up.

Loading MP3s.

Of course a music player is not much use without some music to play.

Martin O'Hanlon has a useful post on Stuff About Code on copying CD music to MP3.
The Python code opens the CD drive, you pop a CD in, close it and off it goes. When it has finished, it pops the drive open again. If you put another CD in and close it, it will process it. This continues until you stop feeding it CDs. Ingenious.

I used his code, but did convert it to Python 3.

I have a Samsung external USB DVD drive. Now it is a bit power hungry. I initially used a powered hub to supply power to the Raspberry Pi, the mouse and keyboard, and the DVD player.

When I tried it, it kept throwing errors. I did wonder if the DVD drive was not compatible. So I tried it on my Raspberry Pi 3 and that happily copied and converted a CD.

So I powered the Raspberry Pi with a separate USB supply and used the USB hub to power the DVD drive, and the keyboard and mouse.

It does make a bit of a rat's nest of cables.

Once I had loaded a few CDs (18), it was time to  give it a try.

I plugged in my headphones and pointed the browser of my tablet at the IP and port number displayed on the Pirate Audio screen. Select the album of choice and...
The sound level is a bit high, so I will have a look at that.

Conclusion

With the exception of the installation of the mopidy-local, the installation was easy.
Remember, if you use a CD/DVD player to ensure you have a suitable power supply.

The Raspberry Pi Zero is a lot less computationally powerful than the Pi 3 or 4, so it does take a while to process the CDs, and the user interface is a bit slow when you run it locally. It is fine on the browser of another machine.

Saturday 18 April 2020

Ada on the Raspberry Pi

Introduction

The computer language  known as Ada was the result of a US Department of Defense competition to develop a computer language to replace the numerous computer languages used in existing defence projects. The competition was won by a team lead by a French team lead by Jean Ichbiah.

Installation

As with installing any new piece of software , you should update and upgrade the current installation
sudo apt update
sudo apt upgrade
sudo apt-get install gnat

As of 18/04/2020 it installed version 6.1.

Hello World

For simplicity, I used the Geany Program Editor to write my first Ada program.

Create a new file called helloworld.adb, I created a folder called Ada in my Documents folder to take the code. For later work, it is best to create a folder for the source code - compiling and building create a number of files.

In the new file enter the following.
-- My first ADA program
with Ada.Text_Io;
use Ada.Text_Io;
procedure HelloWorld is
begin
   Put_Line("Hello World");
end HelloWorld;
The two hyphens start a comment.
The with tells the compiler what package to use. The contents of the package are made visible to this program by the use.
The procedure has a name (HelloWorld) and the code is bounded by the begin - end.
The put_line is a procedure from the package Ada.Text_Io that takes a string parameter and outputs the string followed by a new line character to the standard output.

Compile and Build

Geany handles all the complicated parameters for compilation and building. The options can be found under the Build menu option. Alternatively the function key F8 compiles and F9 Builds.

Execution

Though there is an execute option in the Geany Build menu, the code executes and then disappears.
To see the result of the program start a terminal window and navigate to the folder with the source code.
The executable file has no suffix but has the name of the source file. Prefix the filename with ./ and press return:
pi@somepi:~/Documents/ADA $ ./helloworld
Hello World
pi@somepi:~/Documents/ADA $ 

References

https://www.adaic.org/learn/materials/#introtoada
https://askubuntu.com/questions/421084/how-do-i-install-the-ada-compiler
http://www.getadanow.com/#get_raspberry_pi
http://www.getadanow.com/#step2
https://en.wikipedia.org/wiki/Ada_(programming_language)

Sunday 5 April 2020

Pimoroni BME680 Environment sensor

So, having a display is all well and good, but now you need something to display.

The Pimoroni BME680 breakout board has a Bosch BME680 temperature, pressure, humidity and air quality sensor.

The following code assumes you have the BME680 and the SH1106 OLED display on the default I2C addresses.

import os
import time
import datetime
import sys

from PIL import Image

from PIL import ImageFont
from PIL import ImageDraw

import bme680

from luma.core.interface.serial import i2c
from luma.oled.device import sh1106
from luma.core.render import canvas

TEMPERATURE_UPDATE_INTERVAL = 0.1  # in seconds


# Temperature offset 

TEMP_OFFSET = 0.0

print("Temperature/pressure monitor - OLED")

print("Initialising")

# Instantiate object for SH1106 OLED display

oled = sh1106(i2c(port=1, address=0x3C), rotate=2, height=128, width=128)

# Instantiate object to read  BME680 sensor

sensor = bme680.BME680()

# Set up the sensors

sensor.set_humidity_oversample(bme680.OS_2X)
sensor.set_pressure_oversample(bme680.OS_4X)
sensor.set_temperature_oversample(bme680.OS_8X)
sensor.set_filter(bme680.FILTER_SIZE_3)
sensor.set_temp_offset(TEMP_OFFSET)

# Build the fonts

rr_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'fonts',
                                       'Roboto-Regular.ttf'))
rb_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'fonts',
                                       'Roboto-Black.ttf'))
rr_24 = ImageFont.truetype(rr_path, 24)
rb_20 = ImageFont.truetype(rb_path, 20)
rr_15 = ImageFont.truetype(rr_path, 15)
rr_40 = ImageFont.truetype(rr_path, 40)

# Get sensor data first so that device settings take effect

sensor.get_sensor_data()
# Get the initial date/time and max/min temperature
low_temp = sensor.data.temperature
high_temp = sensor.data.temperature
curr_date = datetime.date.today().day

last_checked = time.time()


# Main loop

while True:
    if sensor.get_sensor_data():
        temp = sensor.data.temperature
        press = sensor.data.pressure
        humidity =sensor.data.humidity
        if datetime.datetime.today().day == curr_date:
            if temp < low_temp:
                low_temp = temp
            elif temp > high_temp:
                high_temp = temp
        else:
            curr_date = datetime.datetime.today().day
            low_temp = temp
            high_temp = temp

        # Write data to canvas

        with canvas(oled) as draw:
            draw.text((65, 55), u"{0:4.0f}".format(press), fill="white", font=rb_20)
            draw.text((1, 55), u"{0:2.1f}%".format(humidity), fill="white", font=rb_20)
            draw.text((1, 1), u"{0:2.0f}°".format(temp), fill="white", font=rr_40)

            draw.text((65, 4), u"max: {0:2.0f}°".format(high_temp), fill="white", font=rr_15)

            draw.text((65, 30), u"min: {0:2.0f}°".format(low_temp), fill="white", font=rr_15)

            if int(time.time()) % 2 == 0:

                draw.text((14, 78), datetime.datetime.now().strftime("%H:%M"),
                          fill="white", font=rr_40)
            else:
                draw.text((14, 78), datetime.datetime.now().strftime("%H %M"),
                          fill="white", font=rr_40)

    time.sleep(TEMPERATURE_UPDATE_INTERVAL)


And this is the result.

There is a potential issue with the temperature. The temperature sensor is directly above the Raspberry Pi Zero, and more importantly close to being above the processor. This does mean that the heat from the processor may well be affecting the temperature being sensed and hence displayed.

Dealing with that is for the next instalment.