Pirate Audio - ST7789 Image Display Breaks Audio

Hi I’m having a few niggles with the Pirate Audio 3w amp board. I’ve installed all the dependencies (apart from Mopidy) and it’s working fine both playing an mp3 from the desktop and an internet stream using python-vlc through its own speakers. I don’t need/want to use mopidy, just play an internet stream using VLC.

I also downloaded the image.py script from the Pimoroni ST7789 repository as I want to display a 240x240 image then play specific audio. On its own the image display script works well, refreshes quickly and looks great.

The problem is when I try to combine the two things - with a python script that first displays an image then plays the stream. The image displays, with a crackle from the speaker, and though the stream plays with no error there is no sound. If I then go back to the desktop and double-click an mp3, then it plays but there is no sound.

If I reboot the sound is fine again until I run image.py. If I comment out the image.py part of the script (I’ve tried executing it both with Subprocess and by copying all the code into one script, same result) then the stream plays fine and the audio is output.

It’s like the audio is disabled by running image.py, or it’s causing some kind of conflict that’s wiping out the audio until it’s reset after a reboot. I’ve updated all the relevant settings in /boot/config.txt and even replaced cs=ST7789.BG_SPI_CS_FRONT with cs=1 in the image.py code, as per the backlight-pwm example but still no luck.

All help gratefully received! Thanks in advance.

In case you are still working on this…

I had the same issues with the st7789 examples. The ones in this folder


run without problems. Guess the backlight pin is the problem. With pirate-audio it is 13 and in the other example it is 19. My amp stopped working when I played with pwm and I had to reboot several times to get the sound back.

Thanks for responding, that’s useful, will keep trying!

I’ve also been experimenting with the pirate audio board - in my case the one with a built in speaker - and seem to have quite a bit working with it.

I can’t find a way to attach a file to this forum, so here is a (fairly large for a forum post) chunk which gives prerequisites, setup and code to use the buttons to do different things with the screen and speaker.

Perhaps let me know if it all works for you, and if it seems OK I’ll try to get it added to the git repo for the pHat.

#================================PREREQUISITES===============================
# I started with Raspbian Lite - bigger versions of Raspbian should be fine
#
# Ensure that the file at /boot/config.txt cobntains these two lines:
#		dtoverlay=hifiberry-dac
#		gpio=25=op,dh
# and put a hash before this line (as shown) to disable it:
#		#dtparam=audio=on
#
#  You need to install software and libraries as follows:
#		sudo apt-get update
#		sudo apt-get install python-rpi.gpio python-spidev python-pip python-pil python-numpy sox libsox-fmt-mp3
#		sudo pip install st7789
#
#  The code below also assumes that you have 
#	- an mp3 file called 'test.mp3' in the same folder as the program (see lines 140 and 144 of this file)
#	- a font file at /usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf (see lines 70-73)
#  You can of course change thes locations within the code on the lines shown above.
#
#=========================END OF PREREQUISITES===============================

#================================BASIC SETUP=================================
#=======================================================
#Library imports
#=======================================================
# imports for screen
# documentation for PIL is at https://pillow.readthedocs.io/en/stable/reference/index.html
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from ST7789 import ST7789
#import os for beep
import os
#imports for buttons
import signal
import RPi.GPIO as GPIO
#import time so we can make a puase
import time

#=======================================================
# Set up the screen and image buffers
#=======================================================
#Set up screen
SPI_SPEED_MHZ = 80
screen = ST7789(
    rotation=90,  # Needed to display the right way up on Pirate Audio
    port=0,       # SPI port
    cs=1,         # SPI port Chip-select channel
    dc=9,         # BCM pin used for data/command
    backlight=13,
    spi_speed_hz=SPI_SPEED_MHZ * 1000 * 1000
)
# screen size details
width = screen.width
height = screen.height

# Create a few blank images.
# This lets us set up layouts/pictures, then send them easily to the acreen
# We set up an array of images and a corresponding array of draw objects, one for each image
image = [None] * 4
draw = [None] * 4
for i in range(4):
	image[i] = Image.new("RGB", (240, 240), (0, 0, 0))
	draw[i] = ImageDraw.Draw(image[i])

#=======================================================
# Set up a font to use when showing text
#=======================================================
# I've shown how to create two different sizes
# You need a font file in the appropriate directory.
# If using Raspbian lite, you'll need to create the directory and get a font from (eg) https://www.fontsquirrel.com/
font30 = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 30)
font60 = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 60)
	
#=======================================================	
# Create a 'beep' function - a simple noise to make sure sound is working at any stage 
#=======================================================
def beep():
	beepcmd = "play -n synth 0.3 sine A 2>/dev/null"
	os.system(beepcmd)

#=======================================================
# Set up the basics for buttons
#=======================================================
# The buttons on Pirate Audio are connected to pins 5, 6, 16 and 20
BUTTONS = [5, 6, 16, 20]

# These correspond to buttons A, B, X and Y respectively
LABELS = ['A', 'B', 'X', 'Y']

# Set up RPi.GPIO with the "BCM" numbering scheme
GPIO.setmode(GPIO.BCM)

# Buttons connect to ground when pressed, so we should set them up
# with a "PULL UP", which weakly pulls the input signal to 3.3V.
GPIO.setup(BUTTONS, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# NB: Further down, we'll set up the button handler which will tell teh pi what to do on each button pressed

#================================END OF THE BASIC SETUP======================

#=======================================================
# Set up our actual images
#=======================================================
# image 0 should already be a black screen as that's how we set them all up.  It's useful when we end the program
# image 1: get pi logo.  raspberrypi.png should be a 240x240 image in the same directory as the program
image[1] =Image.open("raspberrypi.png")

# image 2: draw a multicoloured series of small boxes over the display.  
# This uses the 'draw' object associated with image3
#draw.rectangle ((x0,y0,x1,y1),(r,g,b)) draws a box from x1,y1 to x2,y2, using r,g,b as colour values
for row in range(10):
        for cell in range(10):
                draw[2].rectangle((cell*24,row*24,cell*24+24,row*24+24), (cell*25, row*25, 0))
				
#image 3 uses drawing text to put a menu item next to each button
# let's have a function to do the repettitive stuff
def show_text(draw, message, x, y, font, ralign):
	size_x, size_y = draw.textsize(message, font)
	text_y = y - size_y
	text_x = x
	if ralign:
		text_x = x - size_x
	draw.text((text_x, text_y), message, font=font, fill=(255, 255, 255))
show_text(draw[3],"play", 0, 90, font30, False)
show_text(draw[3],"logo", 0, 200, font30, False)
show_text(draw[3],"colours", 240, 90, font30, True)
show_text(draw[3],"exit", 240, 200, font30, True)


#=======================================================
# Set up the button handler
#=======================================================
def handle_button(pin):
	label = LABELS[BUTTONS.index(pin)]
	print("Button press detected on pin: {} label: {}".format(pin, label))
	
	if label=='A':
		# button A - play the sound file, suppressing output by sending it to /dev/null
		# You'll need a file called 'test.mp3' in the same directory as the program
		# Show the blank image while the file is playing - this could be a different image, of course
		# NB: Showing the blank screen doesn't actually prevent button presses being made and stacked up
		screen.display(image[0])
		os.system("play test.mp3 2>/dev/null")
		screen.display(image[3])
		
	if label=='B':
		# button B - show the logo image, and pause for a second
		screen.display(image[1])
		time.sleep(1)
		screen.display(image[3])
		
	if label=='X':
		# button X - show the colour image, and pause for a second
		screen.display(image[2])
		time.sleep(1)
		screen.display(image[3])
		
	if label=='Y':
		# button Y - show the blank image, and exit
		screen.display(image[0])
		GPIO.cleanup()
		exit()
	
# Loop through out buttons and attach the "handle_button" function to each
# We're watching the "FALLING" edge (transition from 3.3V to Ground) and
# picking a generous bouncetime of 100ms to smooth out button presses.
for pin in BUTTONS:
    GPIO.add_event_detect(pin, GPIO.FALLING, handle_button, bouncetime=300)
	
# Now that we are all set up, show the menu screen (image 3)
screen.display(image[3])

# Finally, since button handlers don't require a "while True" loop,
# we pause the script to prevent it exiting immediately.
signal.pause()

[end of code]

2 Likes

Thanks David that looks very comprehensive! I’ll give it a go between mince pies over the weekend (probably with a fresh install) and report back, really appreciate the response.

Just realised my file didn’t refer to the need to have a 240x240 image at raspberrypi.png in the same directory as the program. If it’s not there you’ll get an error about the file being missing.

For this purpose, I just downloaded one from a Google image search.

Thanks again that worked really well, I see the menu and the sound, colours and image all behave nicely, much appreciated. I was running it in Thonny so just had to do pip3 for the st7789 install but otherwise the example was perfect for me and I’ve been able to adapt it to play images and vlc streams at will. :)

Hi daldred
Thank you very much for your code. I was able to run it on a raspberry pi 3a+ , running on Raspbian Buster Lite. But volume control doesn’t work. Running

play test.mp3 vol 1

it returns the warning

play WARN alsa: can’t encode 0-bit Unknown or not applicable

Could you help me ?
Thanks

There’s a (quite old) thread here: https://github.com/floere/playa/issues/6 which indicates that adding the option “-t alsa” immediately after the ‘play’ may sort this out.

I’ve not got the display set up on my Pi at the moment, I’m afraid, so can’t test that for you.

Sorry daldred. My diagnosis was wrong. Volume control works correctly (ex.: play test.mp3 vol -12dB reduces sound level), but there is a loud continuous background noise mixed with my mp3 test sound.
Running

play test.mp3 vol 0

plays only a continuous background noise. It is independent of the mp3 file . I tested several files of different quality.
Any idea ?
Thank you again.

I have just seen your message. Thank you. Using

play test.mp3 -t alsa vol -12dB

it removes the warning message.
The background noise persists.
Thank you again.