Hi I was wondering if it is possible to control the volume of Volumio via GPIO pins? I ask as I am making a WiFi speaker and would like to have control on the speaker for volume up/down and mute - just to make it easy to adjust volume rather than having to get phone out
Hello
I suggest you to add an ask in this message : interface-with-gpio-and-rs232-spi-full-communication-t2192.html
We are a least 2 guy to ask something like that .
I believe what you want isn’t the same as what Glop asks, or i just didn’t understand what you actually want. Glop wants basic control using a few buttons over GPIO. This isn’t hard to achieve.
Get some buttons connect them on 3.3v and a GPIO in.
Create a python script, import bash/shell commands and send mpc commands
At least thats the simplest way i can think of, you could skip the bash import with mpc and use python-mpd but then you’ll need to install python-mpd.
You could take a loot at this thread for inspiration: detect-when-something-streaming-t2056.html
I think that the volume buttons on GPIO is in the same way that I suggeste to configure via GUI the GPIO actions In or Out. (or more deeply within serial communication).
I think it’s posible t do that with script and other but it will be “endUser” to propose that on the config in GUI…
Buttons shouldn’t be a big thing. A volume knob i think is more difficult, but this variant would be nice!
You could use a rotary encoder to do that. Adafruit sells those they also made a sample script to control windows audio. See adafruit.com/product/377
Hi,
A Volume knob is not that difficult!
Hardware:
You need a rotary encoder and some wires. Dupont cables (male/female) are handy, you can solder one side to the encoder and the other side (female connector) can easily be connected with de GPIO connector.
SOFTWARE:
Gpio
To get access to the GPIO-pins you have to install the RPi.GPIO python module:
Download the package from sourceforge
wget http://sourceforge.net/projects/raspberry-gpio-python/files/raspbian-wheezy/python-rpi.gpio_0.5.8-1_armhf.deb
Install the package
sudo dpkg -i python-rpi.gpio_0.5.8-1_armhf.deb
Rotary class
You can use the rotary-class from Bob Rathbone source: http://www.bobrathbone.com/raspberrypi_rotary.htm
(Bob has also a fantastic tuturial for building a radio project!)
Save the rotary class in: /home/pi
Script
Then you need some code to control the volume (based on the test-script from Bob):
#!/usr/bin/env python
#
# Raspberry Pi Rotary Test Encoder Class
#
# Author : Bob Rathbone
# Site : http://www.bobrathbone.com
#
# This class uses a standard rotary encoder with push switch
#
import subprocess
import sys
import time
from rotary_class import RotaryEncoder
# Define GPIO inputs (BCM)
PIN_A = 23 # Pin 16
PIN_B = 24 # Pin 18
BUTTON = 25 # Pin 22
# This is the event callback routine to handle events
def switch_event(event):
if event == RotaryEncoder.CLOCKWISE:
subprocess.call(['mpc', 'volume', '+2' ])
time.sleep(.2)
elif event == RotaryEncoder.ANTICLOCKWISE:
subprocess.call(['mpc', 'volume', '-2' ])
time.sleep(.2)
elif event == RotaryEncoder.BUTTONDOWN:
subprocess.call(['mpc', 'toggle' ])
#elif event == RotaryEncoder.BUTTONUP:
#print "Button up"
return
# Define the switch
rswitch = RotaryEncoder(PIN_A,PIN_B,BUTTON,switch_event)
while True:
time.sleep(0.5)
Save this script in: /home/pi/VolumeKnob.py
Auto-start the script:
nano /etc/rc.local
Add this line before the exit 0:
python /home/pi/VolumioKnob.py &
Reboot the Pi and you can control the volume with the rotary-encoder and with a button press you can pause/play the music!
Succes!
Harry
Hi!
great !!! that is exactly what I was looking for !!!
But I’ve got a problem with Volumio 1.5, I can’t install python-rpi.gpio. The message is :
i@volumio-bureau:~$ sudo apt-get install python-rpi.gpio
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package python-rpi.gpio
E: Couldn't find any package by regex 'python-rpi.gpio'
Any idea ?
Thanks !
Ok
I did it following this thread : rpi-volumio-gpio-for-python-t1491.html
It works now ! But I change step from 2 to 4 in the VolumeKnob.py file.
Thanks a lot!
too bad…
I thought it was ok but after a reboot mpd does not work anymore. No webUI… I can ssh to my pi. Get the following error :
pi@volumio-bureau:~$ sudo service mpd restart
[ ok ] Stopping Music Player Daemon: mpd.
[....] Starting Music Player Daemon: mpdIllegal instruction
failed!
What to do to avoid a complete re-install ?
info : At boot time I hear the boot sound of Volumio
I bet some packages have been upgraded during the installation. A complete re-install is the fastest way to get you back up and running.
To prevent this from happening you could try and change “jessie” into “wheezy” in the sources file. This should stop apt from getting newer packages that corrupt volumio and the required services. BUT PLEASE NOTE this needs to be tested, if you see that packages need to be upgraded before you can install some thing using apt try to use an older version of the package you want to install. Many upgrade packages break volumio.
Balbuze you could try and see if you can find the illegal instuction in the config files of mpd.
This difficult is the reason to have something in volumio directly in standard for GPIO .
Good luck .
I’m looking for an alternative to python-rpi.gpio, going trough the raspberry pi wiki i found that you should be able to control the GPIO’s using bash scripts. If this works your not required to install python-rpi.gpio and risk corrupting volumio.
I cant test this today, ill see if i can try something tomorrow.
see: elinux.org/RPi_Low-level_peripherals
“Bash shell script, using sysfs, part of the raspbian operating system”
Ooops, I have not publiced my latest instructions!
I had the same problems as Balbuze. But I is possible to install rpi-gpio without killing Volumio!
wget http://sourceforge.net/projects/raspberry-gpio-python/files/raspbian-wheezy/python-rpi.gpio_0.5.8-1_armhf.deb
sudo dpkg -i python-rpi.gpio_0.5.8-1_armhf.deb
…and this works
Succes!
Harry
Hi
I re-did a fresh install. Now it works following Buckler instructions.
Thank you !
Now, next step is having a display lcd or oled .
Buckler, what model do you use ? wich code and what information are displayed ?
I 'd like to add button to go to next/previous song etc…
This a really cheap display about 4 euro, 2x16 characters blue & white (HD44780). A OLED would be nice but so expensive…
The first line is showing Time + Status + Volume
The second line is showing Stationname + Artist + Title (scrolling)
When you play a song the time will show the remaining time and the second line will show you the artist + Title
A nice feature is to use an I2C backpack, you will only have 4 wire between the Pi and the Lcd+BP.
You want a display and buttons, is an Adafruit LCD+keypad kit not an options?
There are a lot of python scripts available wich can be installed with Volumio!
Greetings
Harry
Hi
I ran into the same problem with Volumio and GPIO Python. I then searched and found a solution here in this forum (can not currently find it):
I installed the GPIO Python not with this “sudo apt-get install python-rpi.gpio” but instead did this
sudo su
wget http://sourceforge.net/projects/raspberry-gpio-python/files/raspbian-wheezy/python-rpi.gpio_0.5.8-1_armhf.deb
dpkg -i python-rpi.gpio_0.5.8-1_armhf.deb
After that I was able to access GPIO from Python and still have Volumio running.
I have the following system setup and wrote a script to check for 4 button presses (next song, previous song, first song in playlist, random play toggle). The script also reads a 10k (analog) potentiometer using MCP3008 and sets mpd volume accordingly. Works fine.
System Schematics here
Here is a pic of the back of my gadget running volumio (backpanel with shutdown pushbutton)
Here is the script
#!/usr/bin/python
# coding: utf-8
#------------------------------------------------------
# Client for mpd-Server
# Programm starts 8 Threads
# waits fĂĽr button click on four buttons - sets up three interrupt routines
# button 1 (GPIO23) : jump to next title in playlist
# button 2 (GPIO24) : jump to previuos title in playlist
# button 3 (GPIO8) : jump to first title in playlist
# button 4 (GPIO15) : set mpd player to random mode (toggle)
# Waits also for random seconds to play werbung, suspends currentplaylist
#
# Led1 blinks as long as program runs
# Pressing a buttons blinks Led2 twice for visual feedback
# Successful connection to mpd Server blinks Led2 twice
# keyboard Interrupt is catched for testing purposes in Terminal, signals termination to all threads vi variable exitapp
#
# script also starts thread to read volume potentiometer and sets mpd volume accordingly
# code to read pot via chip MCP3008 is taken from Adafruits learning unit
# Analog Inputs for Raspberry Pi Using the MCP3008 (they call it bit banged).
# This script uses GPIO Pins 4/17/27/22 for CLK/DOUT/CS/CS
#
# Script is started via /etc/rc.local
#
# Pretty simple version found on the Volumio-Forum
# Extended and adapted by Peter K. Boxler, December 2014
#-------------------------------------------------------
import RPi.GPIO as GPIO
import sys, getopt, os
import mpd
import time
import random
from threading import Thread
GPIO.setmode(GPIO.BCM)
buttonPinNext = 8
buttonPinPrev = 24
buttonPinStart = 23
buttonPinRandom = 15
potschalter = 14
led1=25 # green led blinks as long as script runs
led2=7 # red led blinks three times: acks button press
led3=9 # green led on= random play on off= random play off
# GPIO Pins for bit banged AD Converter (from Adafruit example)
SPICLK = 4
SPIMISO = 17
SPIMOSI = 27
SPICS = 22
debug=0
FALSE=0
TRUE=1
exitapp = FALSE
sleep_ping=30
randomstate=0
waitwerbungfactor_dead=100
waitwerbungfactor_blues=15
waitwerbung=0
global TEST_MPD_HOST, TEST_MPD_PORT, TEST_MPD_PASSWORD
TEST_MPD_HOST = "localhost"
TEST_MPD_PORT = "6600"
TEST_MPD_PASSWORD = "volumio" # password for Volumio / MPD
# ***** Function Parse commandline arguments ***********************
# get and parse commandline args
def arguments(argv):
global debug
try:
opts, args=getopt.getopt(argv,"dh")
except getopt.GetoptError:
print ("Parameter Error")
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
print ("App mpd-client -----------------------------------")
print ("usage: mpd-client [-s -h]")
sys.exit(2)
elif opt == '-d': debug = 1
# ***********************************************
#-----------------------------------------------------------
# get next song to be played
def get_nexid(mpd):
global debug
status = mpd.status()
for text in status:
if text=="nextsongid":
nexid=int(status.get(text))
if debug: print "Next SongID: %d" % nexid
return(nexid)
#-----------------------------------------------------------
# lower volume from current value to zero, returns current value
def lower_volume(mpd):
global debug
status = mpd.status()
for text in status:
if text=="volume":
curvol=int(status.get(text))
if debug: print "Current Volume: %d" % curvol
volume=curvol
if debug: print "Decreasing Volume"
while TRUE:
volume=volume-10
if volume<0:
volume=0
mpd.setvol(volume)
if debug: print "Volume ist NULL"
break
mpd.setvol(volume)
time.sleep(1.5)
return(curvol)
#-----------------------------------------------
def connect_mpd():
# Connect with MPD (music player daemon)
#------------------------------------------------
global debug
connected = False
retry_count=3
i=1
while connected == False:
connected = True
try:
client.connect(TEST_MPD_HOST, TEST_MPD_PORT)
except SocketError as e:
connected = False
if connected == False:
if debug: print "Couldn't connect. Retrying"
i=i+1
if i > retry_count:
return(9)
time.sleep(3)
if debug: print("Connected to MPD-Server")
return(0)
#---------------------------------------------------------
# read SPI data from MCP3008 chip, 8 possible adc's (0 thru 7)
def readadc(adcnum, clockpin, mosipin, misopin, cspin):
if ((adcnum > 7) or (adcnum < 0)):
return -1
GPIO.output(cspin, True)
GPIO.output(clockpin, False) # start clock low
GPIO.output(cspin, False) # bring CS low
commandout = adcnum
commandout |= 0x18 # start bit + single-ended bit
commandout <<= 3 # we only need to send 5 bits here
for i in range(5):
if (commandout & 0x80):
GPIO.output(mosipin, True)
else:
GPIO.output(mosipin, False)
commandout <<= 1
GPIO.output(clockpin, True)
GPIO.output(clockpin, False)
adcout = 0
# read in one empty bit, one null bit and 10 ADC bits
for i in range(12):
GPIO.output(clockpin, True)
GPIO.output(clockpin, False)
adcout <<= 1
if (GPIO.input(misopin)):
adcout |= 0x1
GPIO.output(cspin, True)
adcout >>= 1 # first bit is 'null' so drop it
return adcout
#-----------------------------------------------------------
def blink_led1(): # blink led coninuosly when program runs
while not exitapp:
for i in range(3):
GPIO.output(led1, True)
time.sleep(0.2)
GPIO.output(led1, False)
time.sleep(0.8)
GPIO.output(led1, False)
#-----------------------------------------------------------
def blink_led2(anzahl,laenge): # Visual feedback if button pressed and connected
for i in range(anzahl):
GPIO.output(led2, True)
time.sleep(laenge)
GPIO.output(led2, False)
time.sleep(0.1)
#-----------------------------------------------------------
def my_callback_nx(channel):
if debug: print "Pin Falling: %d" % channel
time.sleep(.2) # confirm the movement by waiting 1 sec
if not GPIO.input(buttonPinNext): # and check again the input
if debug: print("ok, pin ist tief!")
ret=client.next()
blink_led2(2,0.1)
if debug: print ret
#-----------------------------------------------------------
def my_callback_pr(channel):
if debug: print "Pin Falling: %d" % channel
time.sleep(.2) # confirm the movement by waiting 1 sec
if not GPIO.input(buttonPinPrev): # and check again the input
if debug: print("ok, pin ist tief!")
client.previous()
blink_led2(2,0.1)
#-----------------------------------------------------------
def my_callback_start(channel):
if debug: print "Pin Falling: %d" % channel
time.sleep(.2) # confirm the movement by waiting 1 sec
if not GPIO.input(buttonPinStart): # and check again the input
if debug: print("ok, pin ist tief!")
client.play(0)
blink_led2(2,0.1)
#-----------------------------------------------------------
def my_callback_rd(channel):
global randomstate
if debug: print "Pin Falling: %d" % channel
time.sleep(.2) # confirm the movement by waiting 1 sec
if not GPIO.input(buttonPinRandom): # and check again the input
if debug: print("ok, pin ist tief!")
if randomstate:
GPIO.output(led3, False)
client.random(0)
randomstate=0
else:
GPIO.output(led3, True)
client.random(1)
randomstate=1
blink_led2(2,0.1)
#-----------------------------------------------------------
def connection_status():
# pings server every 60 seconds and prints "pinging" (if debug is specified).
global sleep_ping, exitapp
while not exitapp: # main thread gives terminate signal here
if debug: print "Connection: pinging the server"
client.ping()
wait=sleep_ping
while wait > 0:
time.sleep(3)
wait=wait-3
if debug: print "Connection: Waiting 3 seconds"
if exitapp: break
client.close() # we need to terminate
if debug: print "-->Thread Connection terminating..."
sys.exit(0)
#-----------------------------------------------------------
def button_nx():
global exitapp
GPIO.add_event_detect(buttonPinNext, GPIO.FALLING, callback=my_callback_nx, bouncetime=300)
#
while not exitapp:
time.sleep(1)
pass # pass ist leer statement
time.sleep(1)
if debug: print "-->Thread NEXT terminating..."
sys.exit(0)
#-----------------------------------------------------------
def button_pr():
global exitapp
GPIO.add_event_detect(buttonPinPrev, GPIO.FALLING, callback=my_callback_pr, bouncetime=300)
#
while not exitapp: # main thread gives terminate signal here
time.sleep(1)
pass # pass ist leer statement
time.sleep(1)
if debug: print "-->Thread PREVIOUS terminating..."
sys.exit(0)
#-----------------------------------------------------------
def button_st():
global exitapp
GPIO.add_event_detect(buttonPinStart, GPIO.FALLING, callback=my_callback_start, bouncetime=300)
#
while not exitapp: # main thread gives terminate signal here
time.sleep(1)
pass # pass ist leer statement
time.sleep(1)
if debug: print "-->Thread START PL terminating..."
sys.exit(0)
#-----------------------------------------------------------
def button_rd():
global exitapp
GPIO.add_event_detect(buttonPinRandom, GPIO.FALLING, callback=my_callback_rd, bouncetime=300)
#
while not exitapp: # main thread gives terminate signal here
time.sleep(1)
pass # pass ist leer statement
time.sleep(1)
if debug: print "-->Thread RANDOM terminating..."
sys.exit(0)
#-----------------------------------------------------------------
# function (thread) to read pot and set volumne
def read_pot():
global exitapp, debug
# 10k trim pot connected to adc #0
potentiometer_adc = 0;
last_read = 0 # this keeps track of the last potentiometer value
tolerance = 10 # to keep from being jittery we'll only change
# volume when the pot has moved more than 5 'counts'
while not exitapp: # loop til main threads signals termination
# we'll assume that the pot didn't move
trim_pot_changed = False
# read the analog pin
trim_pot = readadc(potentiometer_adc, SPICLK, SPIMOSI, SPIMISO, SPICS)
# how much has it changed since the last read?
pot_adjust = abs(trim_pot - last_read)
if ( pot_adjust > tolerance ):
trim_pot_changed = True
if ( trim_pot_changed ):
if debug:
print "Pot changed more than tolerance %d", tolerance
print "Pot before:", trim_pot
print "Pot has changed by:", (trim_pot - last_read)
print "Pot last_read", last_read
set_volume = trim_pot / 10.24 # convert 10bit adc0 (0-1024) trim pot read into 0-100 volume level
set_volume = round(set_volume) # round out decimal value
set_volume = int(set_volume) # cast volume as integer
if debug: print 'Volume new = {volume}%' .format(volume = set_volume)
# set_vol_cmd = 'sudo amixer cset numid=1 -- {volume}% > /dev/null' .format(volume = set_volume)
# os.system(set_vol_cmd) # set volume
client.setvol(set_volume)
# save the potentiometer reading for the next loop
last_read = trim_pot
# hang out and do nothing for a half second
time.sleep(0.5)
# ------------------------------------------------------
# waits randoms seconds and plays werbung
# decreases volume , adds werbung to current playlist, plays werbung, deletes werbung from playlist
# resumes play at next song
def werbung():
global exitapp, waitwerbung
while not exitapp: # main thread gives terminate signal here
wait=random.randint(5, 15)
if debug:
wait=wait*15
else:
wait=wait*waitwerbung
if debug: print "Werbung: Going to wait for %d seconds" % wait
while wait > 0:
time.sleep(3)
wait=wait-3
if debug: print "Werbung: Waiting another %d seconds" % wait
if exitapp: break
# ret=connect_mpd(client)
# if debug: print "Werbung Return from Connect MPD: %d" % ret
if exitapp: break
nxid=get_nexid(client) # nächstes stück der Playlist holen (ID), wird nach Werbung gespielt
ident=client.addid("werbung_1.mp3") # werbung.mp3 zur aktuellen playlist addieren und ID merken
if debug: print "Werbung ID: %s" % ident
cur_vol=lower_volume(client) # Volume vermindern auf Null, aktuellen Wert vorher speichern
client.setvol(cur_vol) # Volume wieder erstellen
if debug: print "Werbung: Volume reset to %d" % cur_vol
client.playid(int(ident)) # Werbung spielen
time.sleep(9) # warten bis gespielt
client.playid(nxid) # vorher gespeichtertes nächstes Stück spielen
client.deleteid(int(ident)) # Werbung mp3 entfernen aus der Playlist
time.sleep(5)
# client.disconnect()
# if debug: print " Disconnected from MPD"
if debug: print "-->Thread Werbung terminating..."
sys.exit(0)
#----------------------------------------------------------
def termplay(): # function not used here
volume=60
for i in range(15):
volume=volume-15
GPIO.output(led2, True)
time.sleep(0.3)
GPIO.output(led2, False)
time.sleep(3)
print "Set Volume to %d" % volume
client.setvol(volume)
time.sleep(3)
#-----------------------------------------------------------
# --------- MAIN --------
arguments(sys.argv[1:]) # get commandline arguments
#GPIO.cleanup(buttonPinNext) # cleanup GPIO Pins
#GPIO.cleanup(buttonPinPrev) # cleanup GPIO Pins
#GPIO.cleanup(buttonPinStart) # cleanup GPIO Pins
GPIO.setwarnings(False)
GPIO.setup(led1, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(led2, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(led3, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(buttonPinNext, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(buttonPinPrev, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(buttonPinStart, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(buttonPinRandom, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(potschalter, GPIO.IN, pull_up_down=GPIO.PUD_UP)
#------------------------------------------------
# set up the SPI interface pins (ADConverter)
GPIO.setup(SPIMOSI, GPIO.OUT)
GPIO.setup(SPIMISO, GPIO.IN)
GPIO.setup(SPICLK, GPIO.OUT)
GPIO.setup(SPICS, GPIO.OUT)
time.sleep(1)
# setup mpd Client Object
client = mpd.MPDClient()
ret=connect_mpd() # connect to MPD server
if ret==9:
if debug: print "Could not connect to MPD"
sys.exit(2)
blink_led2(2,0.5)
# reset random play
client.random(0)
# start play with volume 60%
client.setvol(60)
# clear current playlist
client.clear()
if debug: print "Playlist cleared"
if GPIO.input(potschalter): # Schalter ist off (ganz links gedreht)
# start playing using playlist Blues-1
client.load("Blues-1")
waitwerbung=waitwerbungfactor_blues
if debug: print "Blues-1 loaded"
else:
# start playing using playlist Dead-1
client.load("Dead-1")
waitwerbung=waitwerbungfactor_dead
if debug: print "Dead-1 loaded"
# start with first song in playlist
if debug: print "WaitFactor: %d" % waitwerbung
client.play(0)
if debug: print "MPD-Version: %s" % client.mpd_version
# create and Start Threads
connect_thread = Thread(target = connection_status)
button_nx_thread = Thread(target = button_nx)
button_pr_thread = Thread(target = button_pr)
button_st_thread = Thread(target = button_st)
button_rd_thread = Thread(target = button_rd)
werbung_thread = Thread(target = werbung)
led1_thread = Thread(target = blink_led1)
volume_thread = Thread(target = read_pot)
connect_thread.start() # thread to keep connection to mpd
button_nx_thread.start() # thread to watch for NEXT button
button_pr_thread.start() # thread to watch for PREVIOUS button
button_st_thread.start() # thread to watch for START Playlist button
button_rd_thread.start() # thread to watch for RANDOM PLAY button
werbung_thread.start() # thread to play werbung at random intervalls
led1_thread.start() # thread to blink green led
volume_thread.start() # thread to read pot and set volume
# Main thread goes into loop (wait for ctrl-C)
# ctrl-C bloss fĂĽr Tests im Vorground !!
# posit
try:
while True:
time.sleep(3)
if debug: print "Main thread waiting"
pass # pass ist leer statement
# somebody wants us to stop doing what we are doing...
except KeyboardInterrupt:
# cleanup
blink_led2(5,0.1)
exitapp = TRUE # signal exit to the other threads, they will terminate themselfs
if debug: print "Main: exitapp Signaled"
raise
if debug: print "Main: Terminating, waiting 6 seconds"
GPIO.cleanup(buttonPinNext) # cleanup GPIO Pins
GPIO.cleanup(buttonPinPrev) # cleanup GPIO Pins
GPIO.cleanup(buttonPinStart) # cleanup GPIO Pins
GPIO.output(led3, False)
GPIO.cleanup(led1) # cleanup GPIO Pins
GPIO.cleanup(led2) # cleanup GPIO Pins
GPIO.cleanup(led3) # cleanup GPIO Pins
GPIO.cleanup(SPIMOSI)
GPIO.cleanup(SPIMISO)
GPIO.cleanup(SPICLK)
GPIO.cleanup(SPICS)
time.sleep(6) # wait for other threads
client.disconnect()
sys.exit(0)
#-----------------------------------------------------------
# The End
#-----------------------------------------------------------
The script is normally started in /etc/rc.local but for testing purposes I run it in a terminal window on my Mac. I use ctrl-C to terminate all threads. It accepts -d as commandline parm for debugging to stdout.
I also have a shutdown script that detects yet another button press from the shutdown button. I might combine these two scripts into one.
Hope this helps.
Greetings, Peter
Sorry, I could not figure out how to add a picture to my post. Help welcome.
Thanks, Peter
Peter,
You can add a picture with the button “Upload Attachment”
After the upload you place the picture inline with the button [Place inline]
Succes!
Harry
Thanks Harry
I managed to include inline pics.
Greetings, Peter from Switzerland