PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3819
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Help with gpio-fsm state machine

Tue Mar 23, 2021 6:07 pm

Scott,

I wish there was a Ghost-amp shaped hole in my home, but right now there isn't. The cost (factoring in speakers to do it justice) takes it out of impulse purchase territory, so I'm reluctantly going to say no thank you.

The updated diagram was useful for sorting out RESET vs SERVICE, and the latest version of the overlay (same link) drives the RESET signal and exits the fault state after a 500ms grounding of the SERVICE line. It also reduces the delay between relay activations to 1000ms.

Thinking about the additional muting control, I have a proposal:
1. Allocate another GPIO to drive the MUTE signal.
2. When playback starts, deassert MUTE immediately after K2 (or I could introduce another small delay if it is useful).
3. When playback stops, assert MUTE on entry to the amp_off_wait state.

Resuming playback before the 30 minute timeout just results in the MUTE signal being deasserted. This is a very simple feature to add - just pick a GPIO.

Simple
Posts: 111
Joined: Tue Aug 01, 2017 6:51 am
Location: Charleston, SC, USA
Contact: YouTube

Re: Help with gpio-fsm state machine

Tue Mar 23, 2021 11:50 pm

Thanks Phil
You can just take that code for the button out if you want..
If you leave it in, can you make it a longer hold time for a reset, like at least 10 seconds.
I don't want it to be easily reset as a DC condition can actually be dangerous.
I am getting errors now as follows..

Code: Select all

$ python controlscript.py 
Traceback (most recent call last):
  File "controlscript.py", line 84, in <module>
    fh = open(ampStatePath, 'r')
IOError: [Errno 2] No such file or directory: '/sys/class/gpio-fsm/ghost-amp/state'

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3819
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Help with gpio-fsm state machine

Wed Mar 24, 2021 9:56 am

Sorry about that - I didn't test that update, therefore it was broken. I've fixed that now (same link - https://drive.google.com/file/d/1tYMZem ... sp=sharing), and set the reset delay to 10s.

The update also regularises the state names to make the LED script neater: delay state names are changed to reflect the state they are still in rather than the state they are going to. As a result, all the states in which the amp is on begin with "amp_on", and all of the fault states begin "fault".

The relevant bit of the new script is:

Code: Select all

        # DAC
        if ampState[:6] == 'amp_on':
            color = (0,.1,0) # green
            debugPrint('led green')
        elif ampState[:5] == 'fault':
            color = (.1,0,0) # red
            debugPrint('led red')
        else:
            color = (0,0,.1) # blue
            debugPrint('led blue')
Both the new overlay and script tweak have been tested.

Let me know if you'd like the MUTE support to be added, and if so on which GPIO and with which sense.

Simple
Posts: 111
Joined: Tue Aug 01, 2017 6:51 am
Location: Charleston, SC, USA
Contact: YouTube

Re: Help with gpio-fsm state machine

Wed Mar 24, 2021 1:04 pm

Thanks again Phil

When I trigger the fault, it now resets itself.
I think the relevant part is that GPIO27 needs to be INPUT and pull=UP so that it is triggered with a grounded button LOW.
raspi-gpio get shows the same condition for GPIO27 whether I press the button or not.
All of my buttons and triggers will be triggered with a LOW - fewer wires and safer.
All of the outputs will be triggered with a HIGH - logical sense

Also, for sake of being on the same page with the control script, it is as follows, I have the LED intensities set to 1 rather than the .1 previously..

Code: Select all

import time,os,datetime,subprocess,signal,sys,gpiozero,argparse

version=0.3

def debugPrint(s):
    if debug:
        print(time.strftime('%H:%M:%S',time.localtime())+' '+s)

def signal_handler(sig,frame):
    debugPrint('Ctrl+C pressed')
    led.off()
    led.close()
    time.sleep(0.5)
    sys.exit(0)
    
def pingGoogle():
    (s,o)=command(['ping','-c','1','google.com'])
    return s

def checkNetwork(interface):
    (s,o) = command(['grep', '', '/sys/class/net/'+interface+'/carrier'])
    return(o.rstrip() == '1')

def command(command):
    try:
        output = subprocess.check_output(command, stderr=subprocess.STDOUT).decode()
        success = True 
    except subprocess.CalledProcessError as e:
        output = e.output.decode()
        success = False
    return (success,output)

# arguments
ap = argparse.ArgumentParser()
ap.add_argument('-d','--debug',action='store_true',help='Show debug messages')
args = vars(ap.parse_args())
debug = args['debug']
if debug:
    print('Version:',version)
    print('Arguments:',args)

# constants
redGPIO=6
greenGPIO=12
blueGPIO=13
lanSeconds=5
pingSeconds=5
ampStatePath='/sys/class/gpio-fsm/ghost-amp/state'

# setup
led = gpiozero.RGBLED(red=redGPIO, green=greenGPIO, blue=blueGPIO)

signal.signal(signal.SIGINT,signal_handler)
    
nextPing = datetime.datetime.now()
nextLan = datetime.datetime.now()
lanOk = False
internetOk = False

#No network connection (blink LED)
#Network connected (pulse LED)
#Internet access (on LED)

#Then either blue or green based on gpio22 on or off. 

lastInternetOk = None
lastLanOk = None
lastAmpState = None

while True:
    
    # lan
    if datetime.datetime.now() > nextLan:
        lanOk = checkNetwork('eth0') or checkNetwork('wlan0')
        debugPrint('lanOk:'+str(lanOk))
        nextLan = datetime.datetime.now() + datetime.timedelta(seconds=lanSeconds)

    # ping
    if datetime.datetime.now() > nextPing:
        internetOk = pingGoogle()
        debugPrint('internetOk:'+str(internetOk))
        nextPing = datetime.datetime.now() + datetime.timedelta(seconds=pingSeconds)

    fh = open(ampStatePath, 'r')
    if fh:
        ampState = fh.readline().rstrip()
        fh.close()
    else:
        ampState = 'fault'
    if lastAmpState == None or lastAmpState != ampState or lastInternetOk == None or lastInternetOk != internetOk or lastLanOk == None or lastLanOk != lanOk:

        # DAC
        if ampState[:6] == 'amp_on':
            color = (0,1,0) # green
            debugPrint('led green')
        elif ampState[:5] == 'fault':
            color = (1,0,0) # red
            debugPrint('led red')
        else:
            color = (0,0,1) # blue
            debugPrint('led blue')

        if internetOk:
            debugPrint('led on')
            led.color = color
        elif lanOk:
            # pulse
            debugPrint('pulse')
            led.pulse(on_color=color)
        else:
            # blink
            debugPrint('blink')
            led.blink(on_color=color)

        lastAmpState = ampState
        lastInternetOk = internetOk
        lastLanOk = lanOk

    time.sleep(0.1)
Attachments
gpio_state0324.png
gpio_state0324.png (5.57 KiB) Viewed 788 times

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3819
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Help with gpio-fsm state machine

Wed Mar 24, 2021 2:01 pm

I had seen the problem with the incorrect pull, but put it down to not having the correct external hardware. GPIOs 0-8 pull up by default, and 9-27 pull down. I always advise board designers to work with the default pulls where possible, or to fit stronger external pulls if glitch-free operation is required from power-on. That's less of a requirement in your case because it is software that is reading the GPIO, so we can rely on Device Tree to override the default pull. The overlay does this now.

Simple
Posts: 111
Joined: Tue Aug 01, 2017 6:51 am
Location: Charleston, SC, USA
Contact: YouTube

Re: Help with gpio-fsm state machine

Wed Mar 24, 2021 3:33 pm

Let's please remove all the correlation with the button.
I would like the button to be completely separate from the overlay.
The fault is too important to mess with and needs to be isolated from it.

S

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3819
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Help with gpio-fsm state machine

Wed Mar 24, 2021 10:46 pm

Are you happy that exiting the fault state will require a reboot? Or is deassertion of the FAULT signal sufficient to return to the normal operating state?

Simple
Posts: 111
Joined: Tue Aug 01, 2017 6:51 am
Location: Charleston, SC, USA
Contact: YouTube

Re: Help with gpio-fsm state machine

Wed Mar 24, 2021 11:58 pm

It's OK to go from fault back to normal state without a reboot.
The fault state is a latching relay that will remain in it's condition until it is forced back to an open state, regardless of power state.
The reset function is actually a secondary coil that moves the relay back to an open state.
The idea here is that this should never actually happen, and if it does, it's going to need some repairs.
In amplifier world, these faults can cause fires if not designed right in the detection and protection.
I'm going to think about the output muting for a while before I decide to travel further down any additional paths.
Thanks Phil

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3819
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Help with gpio-fsm state machine

Thu Mar 25, 2021 11:28 am

The overlay (https://drive.google.com/file/d/1tYMZem ... sp=sharing) is now almost back where it started - knowing nothing about the RESET or SERVICE signals - but able to return to amp_off when FAULT clears.

Simple
Posts: 111
Joined: Tue Aug 01, 2017 6:51 am
Location: Charleston, SC, USA
Contact: YouTube

Re: Help with gpio-fsm state machine

Thu Mar 25, 2021 11:56 am

Thanks Phil

Getting a couple errors

$ python controlscript.py
Traceback (most recent call last):
File "controlscript.py", line 84, in <module>
fh = open(ampStatePath, 'r')
IOError: [Errno 2] No such file or directory: '/sys/class/gpio-fsm/ghost-amp/state'

And

$ play 2hz.wav
ALSA lib confmisc.c:767:(parse_card) cannot find card '0'
ALSA lib conf.c:4568:(_snd_config_evaluate) function snd_func_card_driver returned error: No such file or directory
ALSA lib confmisc.c:392:(snd_func_concat) error evaluating strings
ALSA lib conf.c:4568:(_snd_config_evaluate) function snd_func_concat returned error: No such file or directory
ALSA lib confmisc.c:1246:(snd_func_refer) error evaluating name
ALSA lib conf.c:4568:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:5047:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM default
play FAIL sox: Sorry, there is no default audio device configured
pi@MANDY:~/audiosamples $ ls /boot/overlays/ghost-amp.dtbo
/boot/overlays/ghost-amp.dtbo

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3819
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Help with gpio-fsm state machine

Thu Mar 25, 2021 12:24 pm

The version I uploaded is loaded and working here.

What does "md5sum /boot/overlays/ghost-amp.dtbo" report?

And "dmesg -l err"?

And "sudo vcdbg log msg |& grep dt"?

Simple
Posts: 111
Joined: Tue Aug 01, 2017 6:51 am
Location: Charleston, SC, USA
Contact: YouTube

Re: Help with gpio-fsm state machine

Thu Mar 25, 2021 12:43 pm

OK sorry
Must have been an error of mine somewhere in wget, naming or replacing, to install the overlay.
Went through the process again and also cycled the protection circuit and reset.
Seems to be working OK now.
Take a break. I'm going to let it run, test, and see how it goes longer term before doing anything more.

Will find a way to get you one in the future
Thanks again Phil

Simple
Posts: 111
Joined: Tue Aug 01, 2017 6:51 am
Location: Charleston, SC, USA
Contact: YouTube

Re: Help with gpio-fsm state machine

Sun Mar 28, 2021 12:37 am

Going to post some more information that I found for references...
It would be nice to actually not have the 5 second delay and go straight to muting the output.
I am assuming that it's standard part of the driver and not able to be changed but I could be wrong.

Controlling the DigiAMP+ Mute / Un-mute
The DigiAMP+ MUTE state is toggled by GPIO22 on the Raspberry Pi. The latest IQaudio device tree
supports the unmute of the DigiAMP+ through additional parameters (from Raspbian 4.4.14+onwards) …

dtoverlay=iqaudio-dacplus,unmute_amp
"one-shot" unmute when kernel module loads.
dtoverlay=iqaudio-dacplus,auto_mute_amp
Unmute amp when ALSA device opened by a client. Mute, with 5 second delay
when ALSA device closed. (Re-opening the device within the 5 second close window, will cancel mute.)
If you do not want to control Mute state through device tree then you can also script your own solution.
The information below may be useful.
# The amp will startup MUTED
# to unmute the amp.
pi@raspberrypi ~ $ sudo sh -c "echo 22 > /sys/class/gpio/export"
pi@raspberrypi ~ $ sudo sh -c "echo out >/sys/class/gpio/gpio22/direction"
pi@raspberrypi ~ $ sudo sh -c "echo 1 >/sys/class/gpio/gpio22/value"
# to mute the amp once more...
pi@raspberrypi ~ $ sudo sh -c "echo 0 >/sys/class/gpio/gpio22/value"
If you already use WiringPi:
# If using WiringPi - to unmute the amp
gpio mode 3 out
gpio write 3 1
# to mute once more
gpio write 3 0

Simple
Posts: 111
Joined: Tue Aug 01, 2017 6:51 am
Location: Charleston, SC, USA
Contact: YouTube

Re: Help with gpio-fsm state machine

Wed Apr 14, 2021 12:34 pm

Hello again!
Hope all is well on your shore of the Atlantic

Everything is running smoothly so far, latest uptime is over 15 days.
Running both as shairport and also as spotify connect device depending on which is occupying ALSA in the moment.
I went ahead and ordered more boards for moving back to the mini chassis and incorporated the output muting that we talked about.
If you have time in the next few weeks to make that little addition by adding the ability to control GPIO24 in unison with the ALSA state.
This will literally disconnect the output while there is no audio to be played,, kind of like ultra-dolby noise reduction.
The operation will be output-high active.

Thanks again Phil and no rush
S
Screenshot from 2021-04-14 08-19-31.png
Screenshot from 2021-04-14 08-19-31.png (119.81 KiB) Viewed 373 times

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3819
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Help with gpio-fsm state machine

Fri Apr 16, 2021 8:58 am

Hi Scott,

I've added the RELAYSSR control to the overlay - it didn't even need any new states. As ever, the new version is at: https://drive.google.com/file/d/1tYMZem ... sp=sharing

The 5 second mute delay is controlled by a property of the snd-soc-core module. To change this, put the following in /etc/modprobe.d/ghost-amp.conf:

Code: Select all

options snd-soc-core pmdown_time=1000
The "1000" is a delay in milliseconds, the default value being 5000.

Simple
Posts: 111
Joined: Tue Aug 01, 2017 6:51 am
Location: Charleston, SC, USA
Contact: YouTube

Re: Help with gpio-fsm state machine

Sat Apr 17, 2021 12:42 am

Simply marvelous

I assume that there is an ability to use 0ms timeout? May be able to hard code that if all goes well.
Will the changes make it into the next release?

Amazing work
Thx
S

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3819
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Help with gpio-fsm state machine

Sat Apr 17, 2021 7:19 am

The updated overlay will be in all future releases.

I didn't try with a pmdown delay of zero, but I see no reason why it shouldn't work. If for some reason it doesn't, 1ms is very close to immediate.

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3819
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Help with gpio-fsm state machine

Mon Apr 19, 2021 8:33 am

A delay of zero does indeed work. However, with PulseAudio enabled (as is the case on current images) there is an additional 5 second delay between pausing/stopping the stream and ALSA being told to pause/stop. This results in a 10 second delay without overriding the pmdown_time parameter, and a 5 second delay with pmdown_time=0. There may be a PulseAudio setting to reduce its delay, but I haven't found it.

Simple
Posts: 111
Joined: Tue Aug 01, 2017 6:51 am
Location: Charleston, SC, USA
Contact: YouTube

Re: Help with gpio-fsm state machine

Mon Apr 19, 2021 12:03 pm

Ok thanks for the info

Each of the systems I use use alsa directly..
Running the lite version, not the desktop.
Shouldn't be an issue.

S

Simple
Posts: 111
Joined: Tue Aug 01, 2017 6:51 am
Location: Charleston, SC, USA
Contact: YouTube

Re: Help with gpio-fsm state machine

Sat Apr 24, 2021 4:40 pm

May need to clarify something here...

This SSR function needs to operate in an AND function with GPIO23 and ALSA (GPIO22 per the driver code).
GPIO24 can only become HIGH if both GPIO23 is active AND the ALSA state is active.
Otherwise we will lose the startup muting of the output which is a big part of the process.
Not sure if this was made clear.

Thanks Phil
S

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3819
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Help with gpio-fsm state machine

Sun Apr 25, 2021 8:06 pm

The outputs are activated in numeric sequence - 22, then 23, then 24. 24 is deactivated when the signal from the codec goes low, then 30 minutes later 23 is deactivated, then 22. If at any point the signal from the codec goes high again, the deactivated GPIOs get activated again in the same sequence with the same delays - it's like climbing up and down a ladder with three rungs. If you think you are seeing other behaviour, add the fsm_debug parameter ("dtoverlay=ghost-amp,fsm_debug") and reboot, then post the output of "dmesg | grep fsm" when you have seen the fault.

Simple
Posts: 111
Joined: Tue Aug 01, 2017 6:51 am
Location: Charleston, SC, USA
Contact: YouTube

Re: Help with gpio-fsm state machine

Sun Apr 25, 2021 10:18 pm

Ok thanks
I just wanted to clarify the operation. I wasn't sure if it would activate on and off with the dac state without the start condition. The new boards will be here in a few days and I will then be able to test it out.

Cheers on your public march along the river mate!

Thanks again
S

Return to “Device Tree”