Thank you for your donation!


Cloudsmith graciously provides open-source package management and distribution for our project.


Problem: I2C volume control of max9744
#1
I have a Pi Zero 2W with a USB DAC sending an analogue audio signal to a Max9744 amplifier which then amplifiers the audio signal to power some 20W speakers; the max9744 is connected to the Pi via I2C and can provide digital volume control.

I have found from trial and error that my best sound quality comes when the Pi is outputting 100% volume and then I adjust volume through I2C to adjust the amplifier.

Below is my python code (thanks AI for writing it!) that lets me adjust volume by: "python SetAmpVolume.py vol" where "vol" is the volume.

Is there some means for me to have moode use this command to execute volume changes and keep mpc volume 100?
I tried editing vol.sh but it didn't work (thanks again for AI helping me find that file and trying this) - is there some master call to setting volume somewhere? Is this shenanigans possible?

On the plus side, I'm loving the built in rotary encoder feature for volume - worked first time! Alas it changes mpc volume and not via i2c to a max9744 Sad
 

Code:
import smbus
import sys

# Initialize I2C bus
bus = smbus.SMBus(1)
MAX9744_ADDR = 0x4B  # I2C address of MAX9744

def set_volume(volume):
   """Set volume level on MAX9744 (0-63)"""
   if volume < 0:
       volume = 0
   elif volume > 63:
       volume = 63
   try:
       bus.write_byte(MAX9744_ADDR, volume)
       return True
   except:
       print("Error communicating with MAX9744")
       return False

# Check if volume was provided as command line argument
if len(sys.argv) > 1:
   try:
       volume = int(sys.argv[1])
       if 0 <= volume <= 63:
           if set_volume(volume):
               print(f"Volume set to {volume}")
           else:
               print("Failed to set volume")
       else:
           print("Volume must be between 0 and 63")
   except ValueError:
       print("Please provide a valid number between 0 and 63")
else:
   # Get volume input from user if no command line argument
   while True:
       try:
           volume = input("Enter volume level (0-63) or 'x' to exit: ")
           if volume.lower() == 'x':
               sys.exit()
           volume = int(volume)
           if 0 <= volume <= 63:
               if set_volume(volume):
                   print(f"Volume set to {volume}")
                   break
               else:
                   print("Failed to set volume")
           else:
               print("Volume must be between 0 and 63")
       except ValueError:
           print("Please enter a valid number")
Reply
#2
So, I don't really know what I'm doing, but I seem to have kludged something together that works Smile. I literally guessed the php syntax based on the nearby rows lol
Maybe someone can let me know if there's an error or something with this? Will it bite me later?

Also, what on earth does vol.sh do?? Same with rotvol.sh as I tried changing those and nothing happened!

It seems mpc volume is now pegged at 100, and changing the volume on the web interface now sets my max9744 amp gain to the "volume" shown on the Moode webpage.

I started by running this
Code:
grep -rnw '/var/' -e 'setvol'

from here to find playback.php having a "setvol" command (AI gave me the idea to try this) 
I then added the sysCmd('python3... as shown below, and changed the sendMpdCmd to set volume to 100 every time. The "SetAmpVolume.py" was written by AI and is posted below
Code:
if ($_SESSION['mpdmixer'] == 'hardware') {
                       sysCmd('amixer -M -c ' . $_SESSION['cardnum'] . ' sset "' . $_SESSION['amixname'] . '" ' . $_POST['volknob'] . '%' );
               } else {
                       sysCmd('python3 /home/pi/SetAmpVolume.py ' . $_POST['volknob']);
                       sendMpdCmd($sock, 'setvol 100');
                       //sendMpdCmd($sock, 'setvol ' . $_POST['volknob']);
                       $resp = readMpdResp($sock);
               }

Code:
import smbus
import sys

# Initialize I2C bus
bus = smbus.SMBus(1)
MAX9744_ADDR = 0x4B  # I2C address of MAX9744

def set_volume(volume):
   """Set volume level on MAX9744 (0-63)"""
   if volume < 0:
       volume = 0
   elif volume > 63:
       volume = 63
   try:
       bus.write_byte(MAX9744_ADDR, volume)
       return True
   except:
       print("Error communicating with MAX9744")
       return False

# Check if volume was provided as command line argument
if len(sys.argv) > 1:
   try:
       volume = int(sys.argv[1])
       if 0 <= volume <= 63:
           if set_volume(volume):
               print(f"Volume set to {volume}")
           else:
               print("Failed to set volume")
       else:
           print("Volume must be between 0 and 63")
   except ValueError:
       print("Please provide a valid number between 0 and 63")
else:
   # Get volume input from user if no command line argument
   while True:
       try:
           volume = input("Enter volume level (0-63) or 'x' to exit: ")
           if volume.lower() == 'x':
               sys.exit()
           volume = int(volume)
           if 0 <= volume <= 63:
               if set_volume(volume):
                   print(f"Volume set to {volume}")
                   break
               else:
                   print("Failed to set volume")
           else:
               print("Volume must be between 0 and 63")
       except ValueError:
           print("Please enter a valid number")
Reply
#3
I discovered the hard way that rotenc.py (when using built in rotary encoder option) has it's own separate call for volume - I made the changes below:

mpd_cli.connect()
#mpd_cli.setvol(new_volume)
os.system("python3 /home/pi/SetAmpVolume.py " +str(new_volume))
mpd_cli.setvol(100)
mpd_cli.disconnect()
Reply


Forum Jump: