I'm looking for some help 'cause I'm getting a bit frustrated on this... :-(
I have a headless Raspberry PI 3 with a PiFi DAC+ audio card, basically an HiFiBerry clone. On the PI I installed mpd and mpc as a client.
On top of those I wrote a python script that invokes some mpc commands to control the underlying mpd daemon (load a playlist, play a stream,...).
Now the issue.
The overall audio setup based on the hifiberry-dacplus overlay works well, the sound is good and I'm fine with it. Mpc & mpd work, I can control all the functionalities of mpd (at least the ones I need) through mpc without a flaw...but, if I try to run my python script suddenly I cannot hear anything anymore, even if no specific errors are traced.
The 'scary' thing is that, after aborting the script execution, I'm no more able to play any sound (I tried with several wav files using aplay), and again no specific errors show up in the log files...looks like someone just 'muted' the volume, but alsamixer shows all playback levels to 100%. I need to reboot the PI to get my sound back.
I checked for clues in the usual places:
/var/log/messages
/var/log/syslog
dmesg
boot.log
/var/log/mpd/mpd.log
I also run aplay -vvv when audio was blocked and compared the output with a session where audio was running fine but I didn't notice any difference...
I know it would be very difficult to diagnose the problem without having access to my system, but do you have any ideas on where else to look to understand if something went wrong?
Just for info, here's my aplay -l output:
**** List of PLAYBACK Hardware Devices ****
card 0: sndrpihifiberry [snd_rpi_hifiberry_dacplus], device 0: HiFiBerry DAC+ HiFi pcm512x-hifi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
Thank you!
Michele
EDIT: seems like there is some incompatibility between the audio board and a 16x2 LCD display I'm using to show the name of the stream I'm playing. The display is a very common one, based on the HD44780 chip.
My code uses the AdaFruit python library available here to drive it and I still have to figure where the problem is: the audio board, as per HiFiberry docs is connected through GPIO 2,3,18,19,20,21 (plus ground & +5V for power), so it shouldn't cause any conflict with the LCD which uses different pins, but I wouldn't bet on it.
Anyway, removing the LCD management part from the python code (but leaving the display physically attached to the RaspBerry pins) apparently solved the problem...
I'll keep this question updated, maybe could be useful for someone else, who knows!
Ok, I got it. As usual, I just went too fast with CTRL-C & CTRL-V without properly reading the code...
I didn't notice I left this statement in my python code
lcd_backlight = 2 #GPIO pin to control lcd backlight
Actually The GPIO 2 (which is one of the two I2C enabled pins on the Raspberry) is not connected to the LCD, but it is used by the audio board for configuration purposes: this way, whenever I tried to initialize the LCD, the audio board was somehow reconfigured, making it "mute". The only way to reset the faulty configuration was to reboot the PI itself.
Just leaving the default 'None' value for the backlight control pin (I do not need it) did the trick.
Related
My ultimate goal is to control a number of peripheral chips on a PCB from a GUI interface on a PC. To do so, my plan was to incorporate a RP2040 (and memory) on the PCB in order to hold all the python scripts and to program/monitor all the peripheral chips. Then, using a PC to interface with the RP2040, send commands over the serial port to execute specific python files on the pico.
I realize that is a bit confusing, so the attached block diagram should help.
Block diagram
Starting on the left of the block diagram, I have a PC running a tkinter GUI. I am currently running the tkinter gui in Thonny. (eventually i would like it to be an executable, but that is beyond the scope of this post) The gui has a number of buttons to choose which python scripts to run. The PC is connected to the PCB through the USB cable. The USB data lines are routed to the RP2040's USB inputs (pins 47,48). The memory on the PCB holds a number of python scrips that correspond to the buttons in the GUI. Ideally, pressing a button on the PC would execute the corresponding py file on the pcb.
What I've got working so far:
My real expertise lies in peripheral chips and PCB design, in this case the front end for a 2-18GHz transceiver, so bare with me if some of my python questions seem basic or misinformed. I've written and tested all the .py files on the pico's memory. To test those scripts I used Thonny to connect to my pico and simply ran (f5) the scripts with the peripherals connected to the right GPIOs. I was also able to get tkinter working and create functioning buttons that can execute commands. Using the pyserial module, I am also able to connected to the pico through the USB and write... strings. Not very useful, but a start.
import serial
ser = serial.Serial('COM3', 38400, timeout=1, parity=serial.PARITY_EVEN, rtscts=1)
s = ser.read(100) # read up to one hundred bytes or as much is in the buffer
print(ser.name) # check which port was really used
ser.write(b'ToggleLED.py') # write a string
ser.close() # close port
Remaining task: The final task I have been failing miserably at the past 2 days has been actually trying to execute the .py files located on the pico's memory through the serial port. My unexperienced/naïve notion was to simply send a string with the files name, obviously not correct. Any thoughts on how to execute those py files using that pyserial module?
BTW, if there is a better solution, please feel free to share! Perhaps the files should be located on the PC and i send 1 command at time?
I can't say anything about your serial problems until you clarify just what is running on the pi (see my comment: I'll update this answer when you do), but re 'is there a better way': possibly.
Since the Pi is running a full operating system, there are a few options. You are basically creating a network connection to the Pi. Whilst this can be done over serial (with the Pi, presumably, acting as a fake USB serial device), it can also be done more conventionally over wifi or ethernet. Lastly, you could host your interface on the Pi and interact with it in a webbrowser, cutting the second computer out of the picture. Exactly which option you decide to take is up to you, and is really off topic here (though it might be on topic elsewhere on SE).
Sending commands to the pi and having it run scripts is Remote Procedure Call. You might want to lookup some of the protocols (like JSON-RPC) generally used to do that, but the basic approach will have code running on the pi:
def do_something():
pass
def do_something_else():
pass
functions = {"something": do_something, "something_else": do_something_else}
while True:
cmd = get_input() # blocks until input comes
if cmd in functions:
reply(f"Running {cmd}")
output = functions[cmd]()
reply(f"{cmd} returned with output {output}")
else:
reply(f"Invalid command {cmd}")
This is schematic: exactly what get_input() on the pi is will depend on how you end up connecting, and what protocol (if any) you end up using. Notice that I have built in confirmation: you want to know if things work or fail.
Whilst you could store these commands in separate scripts and invoke them, if they are just python scripts there is no reason not to call the functions directly from the code running on the pi.
I've seen two different solutions to the question:
With the Pi pico running the REPL (python shell), text strings can simply be sent from a python program running on the host (Windows or Raspberry Pi, etc., connected to the USB com port, with Thonny window closed), and sent to the pico as python commands. This approach is detailed in:
https://blog.rareschool.com/2021/01/controlling-raspberry-pi-pico-using.html
On the pico side, one just need to define a number of functions that will execute from the REPL. E.g.,:
from machine import Pin
# use onboard LED which is controlled by Pin 25
led = Pin(25, Pin.OUT)
# Turn the LED on
def on():
led.value(1)
# Turn the LED off
def off():
led.value(0)
Any string sent to the pico, such as
on()
will be executed accordingly.
In the 2nd approach, the pico will read each line from the USB serial port and parse the line into command and additional parameters, to be compared against a list of predefined commands and executed accordingly. I did that using the Arduino Due, and I'm in the process of porting it to the pico (= no code to show yet :-().
Project Aim: Create a seat that when you sit on it, audio starts. When you leave, the audio stops. Next time someone sits down, the audio begins again. Each time it is a random track, different from the last.
Context: Outside with access to power
How it can work (I think): I’m wondering if it is possible with using a Raspberry Pi and PIR Sensor (plus some other bits and pieces?). Basically, when someone moves into the range of the PIR sensor, this event is detected and sends an input to a GPIO pin on the Pi. With the right script, this can then fire an event – e.g. play a random audio file from micro SD card. Does this sound correct/doable?
Help!: I believe its not too abstract an idea or function, that has probably been done before. But I just can’t seem to find exactly what I’m looking for, where someone has already written a script I can use/modify. So I’d love to know, do you think this idea is doable/achievable? And, where acatly do you recommend I can track down a pre-made script/instruction on making it a reality.
If you know someone who could write such a script, please do put me in contact.
Thanks!
This is actually not that hard to realize. You have to come up with an idea for a sensor that you can build into your chair, I would recommend just a simple one that works like a push button: when someone sits down, you got a connection the RasPi can recognize. After doing that make sure, your RaspberryPi has power, a GPIO connection to the sensor and speakers attached.
The Script is also quite simple and its structure would look like this:
import RPi.GPIO as GPIO
import simpleaudio # just as an example, was the first one I found online
sound = 'path/to/your/soundfile.wav'
def playSound(directory):
play = simpleaudio.WaveObject.from_wave_file(directory)
play.play()
try:
while True:
if GPIO.input(numberofyourgpio):
play_sound(sound)
except KeyboardInterrupt:
pass
Finally you can set this to start after booting the RaspberryPi and you will never have to care about it not being started anymore.
So I'm building this joke program in Python. Basically, what it is and does is it is an app disguised as a game, and when opened, the headphone port is disabled, the audio output is set to computer speakers, volume is set to max, and it says 'gamer alert' many times. The problem I am having is that there is no way to stop it; even if you delete the application while it is running still won't do anything. I need a method of detecting a keyboard shortcut made to stop it. It needs to be compatible with Mac.
Note: if you want to test, you can set it to a lower volume by changing 100 to something around 20 or 30.
I've tried using PyGame, Tkinter, Pynput, Getch, etc. all didn't work. I'm not too sure if it's because I'm not using them right, or if they won't work at all with what I'm trying to do.
import os
while True:
os.system('SwitchAudioSource -s "Built-in Output"')
os.system("osascript -e 'set volume output volume 100'")
os.system("say gamer alert")
I have gotten a few error messages with some of the modules I mentioned above, but otherwise no error messages. The voice might stop after one iteration. Without this kill feature, it works beautifully.
I have a project in my job.
The target is to prepare 14 SD cards for provisioning any Raspberry Pi 3.
So I have to found a solution to do it automatically and follow which SD card is ready to start and which one is complete.
I have the idea to build with a Python3 program and a tkinter interface because I know a little bit Python and not others languages...
The program should work like this :
List every Windows drives where SD card is mounted
Push a button in front of the letter of the SD card drive to start the provisioning.
The provisioning is all steps to make the SD cards bootable with an OS. So I have to pass some DISKPART commands or equivalent in Python I think, if you have any suggestions ?
Show a statut in front of each drive to follow if the drive is pending, working, complete, etc.
I have a huge interogation about this. My program has to refresh every informations. I mean the program should work in real time or not ? What is the best way to proceed ?
To be clear, I don't want someone building to me this program, I just want to have some good idea to implement.
Thank you
You can use this module to execute commands. For example:
import subprocess
completed = subprocess.run(['ls', '-1'])
print('returncode:', completed.returncode)
I can't help with the Python part, but if you have a WinAPI window with message handling (so the WindowProc thing), WM_DEVICECHANGE is the message, here are the actual event categories and RegisterDeviceNotification is how you subscribe to it. Complete (but C) MSDN example is here
While implementing it may require some work, viability itself depends on getting access/not getting access to the message queue (from Python). Based on this and this it seems to be possible, but I have no experience with it.
I have a problem with sending triggers for eeg recording using PsychoPy standalone v1.81.00 on a Win7 64bit OS. I followed the descriptions here and don't get any (more) errors. The triggers, however, don't show on the recording computer (Brainvision Recorder under Win7 32bit).
What I did:
Downloaded and installed the InpOutBinaries_1500 via InpOutBinaries_1500\Win32\InstallDriver.exe
Copied the other files (inpout32.dll, .h and .lib as well as vssver2.scc) to the working directory of my script
Tried sending trigger codes with windll.inpout32.Out32(0x378, triggerCode)
The trigger code doesn't show up in Brainvision Recorder but seems to be set correctly when calling print str(windll.inpout32.Inp32(0x378)).
Thanks for every piece of advice or idea!
I managed to solve the problem. I'm not entirely sure which step(s) actually cut the curve but I recommend the following:
Download and install LPT Test Utility on your presentation computer.
At first, this program installs the inpout32.dll automatically and correctly regardless if you use a 32 or 64 bit OS.
More over, it helps you to monitor and manipulate the pins of your parallel port. If using the standard addresses (LPT1 through LPT3) doesn't work, select LPTX and enter your address manually (see here where to get your parallel port address on a Windows PC). If the triggers don't show on your recording computer using this program, you have an issue that is not related to PsychoPy.
If this fails, (re-)install a parallel port driver. Using Windows 7 this should not be necessary but actually solved one major issue for me. If this still fails, probably the hardware components (parallel port plug / card, cable(s), sync box) are damaged.
If the triggers work with the "LPT Test Utility" program but not using PsychoPy, an individual troubleshooting dependent on your code is necessary. Of course, you need to insert the port address that worked with "LPT Test Utility" in your PsychoPy code.
from psychopy import core
from ctypes import windll
windll.inpout32.Out32(portaddress, triggerCode) #sends the trigger with triggerCode being an integer between 0 and 255
core.wait(0.05) #wait 50ms
windll.inpout32.Out32(portaddress, 0) #deletes the trigger i.e. resets the pins
Best wishes,
Mario