Playing Sounds on command

I have been trying to get the Borg to play a sound on a button press.
Playing the mp3 from the terminal works fine, but when I put it in the code, Borg seems to hang on boot. That is, none of the joystick commands work.
I am doing everything over SSH so can't see what is going wrong.
I've also looked at the MeArm script in the hope I could figure it out, but no luck.
These are the lines I have added to metalJoy.py
My lines are commented out.

# Settings for the joystick
axisUpDown = 1                          # Joystick axis to read for up / down position
axisUpDownInverted = False              # Set this to True if up and down appear to be swapped
axisLeftRight = 2                       # Joystick axis to read for left / right position
axisLeftRightInverted = False           # Set this to True if left and right appear to be swapped
buttonResetEpo = 3                      # Joystick button number to perform an EPO reset (Start)
buttonSlow = 8                          # Joystick button number for driving slowly whilst held (L2)
slowFactor = 0.5                        # Speed to slow to when the drive slowly button is held, e.g. 0.5 would be half speed
buttonFastTurn = 9                      # Joystick button number for turning fast (R2)
interval = 0.00                         # Time between updates in seconds, smaller responds faster but uses more processor time
buttonShutdown = 0                      # Joystick button number to get the Raspberry Pi to shutdown (Select)
#buttonSiren = 12                        # Joystick button number to get the Raspberry Pi to play siren.mp3 (Triangle)
                # Check for button presses
                if joystick.get_button(buttonResetEpo):
                    PBR.ResetEpo()
                if joystick.get_button(buttonSlow):
                    driveLeft *= slowFactor
                    driveRight *= slowFactor
#                if joystick.get_button(buttonSiren):
#                   omxplayer -o local ~/metalborg/siren.mp3
                if joystick.get_button(buttonShutdown):
                    # Start the Raspberry Pi shutdown sequence
                    print 'Shutting down...'
                    PBR.MotorsOff()
                    PBR.SetCommsFailsafe(False)
                    PBR.SetLed(True)
                    os.system('sudo halt')
                    break
Attachments: 
piborg's picture

The reason the script is no longer working is that Python does not directly understand terminal commands.
Because of this it thinks the command is an error, causing the script to fail to run.

You can run terminal commands using the os library like this:
os.system('terminal command')

In other words I think this should work as intended:

                # Check for button presses
                if joystick.get_button(buttonResetEpo):
                    PBR.ResetEpo()
                if joystick.get_button(buttonSlow):
                    driveLeft *= slowFactor
                    driveRight *= slowFactor
                if joystick.get_button(buttonSiren):
                    os.system('omxplayer -o local ~/metalborg/siren.mp3')
                if joystick.get_button(buttonShutdown):
                    # Start the Raspberry Pi shutdown sequence
                    print 'Shutting down...'
                    PBR.MotorsOff()
                    PBR.SetCommsFailsafe(False)
                    PBR.SetLed(True)
                    os.system('sudo halt')
                    break

Ah! Of course, I hadn't considered that they are essentially different entities, I have been Googling the wrong things. Doh!
I am planning to put some WS2812 LEDs (AKA neo pixels) on him too. But since the only way to get the RPi to manage the timing requirements (as far as I know) is to use DMA using the rpi_ws281x library, this seems not to work alongside the Borg scripts. But then it's probably due to my lack of coding skills.
I'm thinking of using an Arduino (Trinket or Gemma) and triger the animations from the metalJoy.py code, thereby taking the processing off the RPi.
Does this sound like a good way of doing it

piborg's picture

That does sound like a good way of doing it.

The Arduino is well suited to problems with timing constraints, where the Raspberry Pi is well suited to problems requiring processing horsepower.
As a pair they can do a lot of complex tasks in a clean fashion if the workload is separated appropriately.

There is a good guide here if you wish to use serial to communicate between them:
http://www.doctormonk.com/2012/04/raspberry-pi-and-arduino.html

The sound works great thank you.
The only thing I would like to change is that when sound is playing, nothing else works. When the sound has finished, everything works as normal.

Now I'm trying to switch a few GPIOs from high to low and back, under controls from the PS3.
This is so that the Arduino Uno will change the LED (WS2812B) animations on command.
I have an Arduino sketch that responds to switch inputs (High/Low) but now want to control those from the Rpi. I have studied the link from Dr Monk, but that seems to be over USB, I was trying to avoid big plugs sticking out the side of Borg.

Unless there is a better way to 'talk' to the Nano over serial to do what I am hoping for?

I'm guessing that a level shifter will be required so I've ordered a couple of these http://makersify.com/products/adafruit-txb0104-bi-directional-level-shifter
I've also got a UBEC to power the Uno and LEDs
http://makersify.com/products/ubec-dc-dc-step-down-buck-converter-5v-3a-...

piborg's picture

Instead of using the USB connector you should be able to use the serial pins on both devices.

This part of an instructable talks about wiring these pins:
http://www.instructables.com/id/The-Raspberry-Pi-Arduino-Connection/step...

The serial port pins on the Raspberry Pi will try to run as a terminal connection by default.
This guide should help you turn that off, leaving them to be used as a standard serial port from Python:
http://www.hobbytronics.co.uk/raspberry-pi-serial-port

For the sound we can use a different function to prevent the script from waiting for completion.
Add this to the library imports:
import subprocess
Change the command call to:
subprocess.Popen(['omxplayer', '-o', 'local', '~/metalborg/siren.mp3'])
It looks a little messier but it runs the command in a separate thread, allowing the script to continue.

Thanks a bundle, got a question on connections though, don't want to burn any boards.
The instructibles link says to use pins 1 and 6, but the PicoBorg Reverse is using those. Obviously I can use an alternative ground so pin 6 is not a problem, but pin 1 (3.3v) is hooked up to the PBR. Is it ok to link the Arduino to the corresponding Pin 1 of the daisy-chain header on the PBR? Is that header a pass through or will I need to enter any code to enable that pin?

The sound code did not work, Borg lost comms with the PBR when I activated the button to play the sound, but no sound was played. It's not a serious issue though, the sound was just a 'nice to have' idea. I have reverted to your original code for now.

piborg's picture

The daisy-chain header is indeed a pass-through, all of the pins can be used like the original 1-6 pins without any software involvement.

From what you said before I presume you are still intending to power the Arduino separately.
If this is the case you do not really need to connect the 3.3v line, they were using that to power the Arduino separately.

Personally I would put both the Tx and Rx lines through the level shifter to be safe, I suspect they may be 5v on the Arduino side.

As for the audio code I probably made a mistake (going from memory).
The script losses communications like that if it hits an error and cannot recover from it, such as a function name it cannot find.

Thanks, very informative as always.

Yes, I plan to power the Arduino from the 12v battery pack via a UBEC, which arrived yesterday, so won't need to use the 3.3v from the PBR.

I will await the level shifter before I start connecting them together, the Arduino is 5v, so not worth risking it.

I find it astounding that you can do so much from memory, so the odd error is bound to creep in, it will give me a challenge while I wait for the level shifter to arrive.

piborg's picture

I guess the memory thing is a good indication I spend far too much time using Python in general :)

I tried the new sound command in Python this morning and it appears okay, but it did give me some thoughts:

  1. Did you type Popen with the upper-cased P: subprocess.Popen?
  2. It might be worth trying with the fully named path instead of ~:
    subprocess.Popen(['omxplayer', '-o', 'local', '/home/pi/metalborg/siren.mp3'])
  3. If all else fails you can try running the script directly in the SSH session instead of crontab and see what error message you get
Subscribe to Comments for "Playing Sounds on command"