• Disclaimer: This Vendor's Forum is a paid-for commercial area. Unlike the rest of diyAudio, the Vendor has complete control of what may or may not be posted in this forum. If you wish to discuss technical matters outside the bounds of what is permitted by the Vendor, please use the non-commercial areas of diyAudio to do so.

Support for Botic Linux driver

Hi,
I’m considering ‘closing’ BBB/Hermes/Cronus and DAC in the one aluminum case.
I would like to mount and use 3 LED’s on the front panel of the case (as user interface😉)and connect them to dedicated BBB/Hermes LEDs header.

It would be great if the LED’s could behave for example as follows:

  • 1st LED: Indicate the power; behave just like on-board BBB blue LED; switched on/off in the same time as blue BBB LED,
  • 2nd LED: Indicte playing music with HI clock (eg 24.xx or 49.xx or 98.xx MHz). When playing blinking (heartbeat), When pausing LED solid. Without playing/pausing LED switched off,
  • 3rd LED: Indicte playing music with LO clock (eg 22.xx or 45.xx or 90.xx MHz). When playing blinking (heartbeat), When pausing LED solid. Without playing/pausing LED switched off
Is it possible to write a piece of code to drive these external LEDs?
If so maybe someone experienced/talented could give an example.
I'm sure it would be helpful for many users.
Regards,
B

Maybe I can help even though I am learning as I go... Here is a python script to get you started. Certainly somebody who is good in Python can improve this!

Power LED: I just use LED1 wired to the front panel. It is almost the same as the on-board BBB power LED, and I have a separate power indicator run by the actual power supply that drives the BBB. The trickier ones are 2nd and 3rd.

2nd and 3rd LED: I am using python code that displays source frequency information as text, but we can instead transmit the logic to GPIO outputs. I can't actually test the following python script because one of my Hermes LEDs isn't working correctly, but I am confident that the detection portion of this works. This does not look for the mute function in the es9018, but if you have i2c volume control from BBB then it is simple to detect the mute condition. I personally feel that a flashing LED would be an annoying distraction. How about both LEDs together = Buffalo mute? That part can be added later.

To run this on the BBB you will need to install the Adafruit GPIO library as described here.

I will try to use the code box - it has been stupidly breaking syntax lately by 'spell checking'.
Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import Adafruit_BBIO.GPIO as GPIO
import time
import subprocess
import smbus # needed if you later want to add i2c functions
# GPIO setup needed to address pins
GPIO.setup("P9_12", GPIO.OUT)
GPIO.output("P9_12", GPIO.LOW)
GPIO.setup("P9_13", GPIO.OUT)
GPIO.output("P9_13", GPIO.LOW)
# define a loop function to check hw_params every half second
def displayloop():
    while True:
        with open('/proc/asound/Botic/pcm0p/sub0/hw_params') as f:
        lines = f.readlines()
        try:
            rawrate = lines[4]
            rate =(int(rawrate[6:12])/1000)
        except IndexError:
            rawrate = 0
            # display (which of the two rate multiples is being used)
        if rate == 0:
            GPIO.output("P9_12", GPIO.LOW)
            GPIO.output("P9_13", GPIO.LOW)
        elif rate == 44 or rate == 88 or rate == 176:
            GPIO.output("P9_12", GPIO.HIGH)
            GPIO.output("P9_13", GPIO.LOW)
        elif rate == 48 or rate == 96 or rate == 192:
            GPIO.output("P9_12", GPIO.LOW)
            GPIO.output("P9_13", GPIO.HIGH)
        else:  time.sleep (.5)
displayloop()
I use similar code for transmitting system status to an iOS display. If you want, you can increase the sleep time of the loop (currently half a second, which saves a tiny bit of CPU at the expense of responsiveness).

To try this little script, install the GPIO library, put the script in a convenient location (I use /usr/script - 'mkdir /usr/script', then 'nano /usr/script/'some_script_name'.py' (no single quotes) and copy the above into it & save.) To run the script, cd to /usr/script and execute 'python 'some_script_name'.py' (again no quotes). Once you get it working as you like, perhaps start it from /etc/rc.local - open that file and add "python 'some_script_name'.py as the next-to-last line, and reboot.

Have fun! 😱
 
Last edited:
Thanks,
I will try🙂.
Acually I have got one RGB LED (equivalent of 3 LEDS: Red, Green, Blue) embedded in the adapted on/off push button:

s-l500.jpg


I am going to use it to switch on/off and show current status of playback of DAC +BBB placed in one aluminum enclosure.
 
Great! So you will want to add the additional LED output to the mix... From the above bash script it is pin "P9_11" (or GPIO 30 if using bash). It will be fun to see how distinct are the colors produced by each of the 3 pairs. [I have some RGB christmas lights that are failing, and I can see that their distinct colors are made by adding pulse width modulation to the mix. I doubt you want BBB doing that.]

Actually, Miero can tell us whether Botic will always take care of the pin setup - maybe those setup lines are unneeded when running Botic. But for now, add lines containing "P9_11" to the pin setup block as well as to each logic state. Then you can deconstruct/combine the 'elif rate == XX:' statements as you wish, followed by a GPI😵utput of high or low for each of the three pins (11,12, and 13). Just respect the indentation that you see. I didn't include the highest possible rates (352 & 384) - you certainly can. Remember that these LEDs can also report information from the DAC (like mute) via i2c from the es9018, if you are using one with volume control via BBB...

Have fun and show us how it works!

Best,

Frank
 
Last edited:
I was thinking about this some more. Perhaps this conversation should be moved over to: http://www.diyaudio.com/forums/twisted-pear/281776-control-bbb-based-audio-appliances.html

for now...

I might personally like using display logic something like this:

44 = blue
88 or 176 = blue plus green
48 = green
96 or 192 = green plus red

This makes the button brighter when playing "HD" material, and distinguishes between frequency families. Blue/light blue vs green/yellowish

Mute could be white, and you would detect that from the DAC by adding two bits:

1) In the GPIO setup lines add: 'bus = smbus.SMBus(1)'
2) Change 'if rate == 0:' to 'if bus.read_byte_data(0x48, 0x0a) == 207:' (remove single quotes). Then below it, indented, the three GPIO lines such as: 'GPI😵utput("P9_XX", GPIO.HIGH)' (remove single quotes - if this doesn't work I can help, as it is working for me in slightly different syntax. I assign the read to a variable.)

[If you have a very custom 9018 setup we might have to adjust the '207' to something else.]

It would be great to reverse the output of the EN LED (controlled by Botic) so that when it comes ON the button is red, meaning time to reset BBB. We don't have access to control that function at the moment. I would prefer this option for my system as well.

Anyway, have fun with this! It should be simple to get it running and I welcome your questions over on the other thread.
 
Last edited:
That is tempting! 😀

Another use for PWM would be to adjust relative LED brightness for those of us with one-color LEDs. Each color has a different efficiency, and they all change depending on the number that are lit.

If feature requests are being entertained, could we flip-flop EN LED output? 🙄

Cheers! :cheers:
 
Great! So you will want to add the additional LED output to the mix... From the above bash script it is pin "P9_11" (or GPIO 30 if using bash). It will be fun to see how distinct are the colors produced by each of the 3 pairs. [I have some RGB christmas lights that are failing, and I can see that their distinct colors are made by adding pulse width modulation to the mix. I doubt you want BBB doing that.]

My RGB LED in the on/off switch button is 4Pin LED with common cathode. Different colours arise as a mix of three basic colors.

I don't use i2c volume so I have to find out other way to detect 'Mute'/Pause. Maybe detection (persistence or lack of) DATA signal (D2 on Hermes board) could solve the detection of Pause?

This weekend I am going to try to test your script.
Regards, bern
 
Last edited:
Maybe detection (persistence or lack of) DATA signal (D2 on Hermes board) could solve the detection of MUTE?

We must be careful not to break the isolation between Cronus and BBB. The file /proc/asound/Botic/pcm0p/sub0/hw_params is reasonably responsive, but doesn't indicate 'mute' per se. When no sample rate is evident it indicates 'nothing playing', which is equivalent to 'no data on D2'. Even if you don't use BBB for volume, you may still be able to read the mute register via the isolated i2c connection on Hermes. I suggest you get your hands dirty with some of the code for LEDs, and then address the question of mute vs. "nothing playing" later. You may change your mind on what information is worth knowing. Good luck!
 
Greetings Bern,

Didn't want you wasting time... Because my suggestions up to now are somewhat in fragments, I put the code together for a RGB LED and tested it as best I could (with 2 of 3 working LEDs on my Hermes). This should do what I suggested above if led1 -> red; led2 -> blue; led3 -> green. Using MPD it works as we discussed. With Squeezelite the 'no play' response isn't reliable - Squeezelite seems to keep the file /proc/asound/Botic/pcm0p/sub0/hw_params from updating during a pause, and I'm not sure why. But if you use MPD then this will be a strong start. The colors red and violet remain available and you can see that python logic is very straightforward if you want to add them. 😉

Enjoy,

Frank

Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import Adafruit_BBIO.GPIO as GPIO
import time
import smbus # needed if you later want to add i2c functions
# GPIO setup needed to address pins
GPIO.setup("P9_11", GPIO.OUT)
GPIO.output("P9_11", GPIO.LOW)
GPIO.setup("P9_12", GPIO.OUT)
GPIO.output("P9_12", GPIO.LOW)
GPIO.setup("P9_13", GPIO.OUT)
GPIO.output("P9_13", GPIO.LOW)
rate = 0
rawrate = 0
# define a loop function to check hw_params every half second
def displayloop():
    while True:
        with open('/proc/asound/Botic/pcm0p/sub0/hw_params') as f:
            lines = f.readlines()
        try:
            rawrate = lines[4]
            rate =(int(rawrate[6:12])/1000)
        except IndexError:
            rate = 0
# display the sample rates being used - LED1=red, LED2=blue, LED3=green
# white=no play; blue=44; green=48; light blue=88/176; yellow(ish)=96/192
        if rate == 0:
            GPIO.output("P9_11", GPIO.HIGH)
            GPIO.output("P9_12", GPIO.HIGH)
            GPIO.output("P9_13", GPIO.HIGH)
        elif rate == 44:
            GPIO.output("P9_11", GPIO.LOW)
            GPIO.output("P9_12", GPIO.HIGH)
            GPIO.output("P9_13", GPIO.LOW)
        elif rate == 48:
            GPIO.output("P9_11", GPIO.LOW)
            GPIO.output("P9_12", GPIO.LOW)
            GPIO.output("P9_13", GPIO.HIGH)
        elif rate == 88 or rate == 176:
            GPIO.output("P9_11", GPIO.LOW)
            GPIO.output("P9_12", GPIO.HIGH)
            GPIO.output("P9_13", GPIO.HIGH)
        elif rate == 96 or rate == 192:
            GPIO.output("P9_11", GPIO.HIGH)
            GPIO.output("P9_12", GPIO.LOW)
            GPIO.output("P9_13", GPIO.HIGH)
        else:  time.sleep (.5)
displayloop()
 
Apologies: On my browser the code box produced a systematic error in the GPIO setup.

I don't know what you read but the lines beginning "GPIO.setup" should be:
GPIO.setup-leftparen-doublequote-P9_XX-doublequote-comma-space-GPIO.OUT-rightparen

I will set up a GIT account for all further code suggestions. 😡 😡
 
Greetings Bern,

Didn't want you wasting time... Because my suggestions up to now are somewhat in fragments, I put the code together for a RGB LED and tested it as best I could (with 2 of 3 working LEDs on my Hermes). This should do what I suggested above if led1 -> red; led2 -> blue; led3 -> green. Using MPD it works as we discussed. With Squeezelite the 'no play' response isn't reliable - Squeezelite seems to keep the file /proc/asound/Botic/pcm0p/sub0/hw_params from updating during a pause, and I'm not sure why. But if you use MPD then this will be a strong start. The colors red and violet remain available and you can see that python logic is very straightforward if you want to add them. 😉

Enjoy,

Frank
Thanks Frank,

I installed Adafruit BeagleBone IO Python library and checked initially your script.
it works fine to show low and high closks.
I use squeezelite and I suppose it will not be easy to implement pause indication.
One thing wonders/concerns me. I see in the process list that the phyton script takes about 49% CPU. I use squeezelite with SOX upsampling which takes another 50% CPU usage. So CPU encounter 100% usage in total.
Do you have 49% CPU usage with python script also?
Regards,
bern
 
Glad to hear of your preliminary success, Bern. Yes, I see an error in the code. time.sleep(time in seconds) should not be in a logic condition, it should always be executed regardless of the rate. Remove 'else' from that line and pull the indentation out in line with the other elif statements.

Cheers!
 
Miero, I notice that squeezelite (even if not the correct PID) prevents correct updates of '/proc/asound/Botic/pcm0p/sub0/status' in addition to '/proc/asound/Botic/pcm0p/sub0/hw_params'. If you can suggest a way to push an update to either of these files, I will try to fix Bern's script.
 
Glad to hear of your preliminary success, Bern. Yes, I see an error in the code. time.sleep(time in seconds) should not be in a logic condition, it should always be executed regardless of the rate. Remove 'else' from that line and pull the indentation out in line with the other elif statements.

Cheers!
After correction python's process CPU usage is nearly 0%. This is awesome!
 
Last edited:
Miero, I notice that squeezelite (even if not the correct PID) prevents correct updates of '/proc/asound/Botic/pcm0p/sub0/status' in addition to '/proc/asound/Botic/pcm0p/sub0/hw_params'. If you can suggest a way to push an update to either of these files, I will try to fix Bern's script.
Frank,
I think Squeezelite's parameter '-C' can help

From manual:-C <timeout> Close output device when idle after timeout seconds, default is to keep it open while player is 'on'

I set -C 1 and it works just fine
 
Last edited:
Frank,
I think Squeezelite's parameter '-C' can help

From manual:-C <timeout> Close output device when idle after timeout seconds, default is to keep it open while player is 'on'

I set -C 1 and it works just fine

This fixes the 'stickiness' of the sample rate display in my iPad controller. 😉

For others, there are options in squeezelite 1.8 that are not listed in the Ubuntu man page (that is otherwise very useful). View the additional options by executing "squeezelite -?" from the command line.
 
Problem starting Squeezelite

After a few false starts (Squeezelite not connecting to NAS or showing on controller...................oops NAS firewall closed!)
I have followed Kinku's excellent how-to in post 923 to the letter, Squeezelite seems to runs fine (no sound yet as output not connected to dac as yet) but I still have one small problem, it won't start at boot.
I have made the startup.sh script and it is executable. if I input :-
root@botic:~# /etc/init.d/startup.sh
squeezelite starts ok, so the script works
however:- root@botic:~# insserv startup.sh
doesn't seem to make the script run at boot.
I am a compete novice with Linux and any help would be much appreciated.
Steve.
 
Last edited: