I have a simple python code that takes MIDI signal from a musical keyboard via USB connected to a PC which then sends command to an Arduino board to write to its digital out. This works perfectly fine and is without issues. I tried migrating the same code to Raspberry Pi with some modification specific to the Pi. My code is as follows:
import pygame
import mido
import rtmidi
import time
import RPi.GPIO as GPIO
pygame.init()
BLACK = [0,0,0]
WHITE = [255, 222, 111]
note_list = []
note_list_off = []
outport=mido.open_output()
inport=mido.open_input()
GPIO.setmode(GPIO.BCM)
done = False
GPIO.setup(4,GPIO.OUT)
print("START!")
while done == False:
for msg in inport.iter_pending():
try:
n = msg.note
except:
continue
if msg.velocity>0 and msg.velocity != 64:
print(msg.velocity)
GPIO.output(4,True)
time.sleep(1)
GPIO.output(4,False)
else:
msg=mido.Message('note_off',note=n)
outport.send(msg)
pygame.quit ()
Adding RPi.GPIO is the only difference with the code running on Windows. If I moved the code
GPIO.output(4,True)
time.sleep(1)
GPIO.output(4,False)
just above the line
print("START!")
Raspberry Pi writes to the correct port which I tested by connecting to an LED. The problem here is that the line after
for msg in inport.iter_pending():
never gets executed. I have checked to see if the Pi detects the keyboard and these are the outputs:
lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 005: ID 07cf:6803 Casio Computer Co., Ltd CTK-3500 (MIDI keyboard)
amidi -l
Dir Device Name
IO hw:3,0,0 CASIO USB-MIDI MIDI 1
aconnect -i
client 0: 'System' [type=kernel]
0 'Timer '
1 'Announce '
client 14: 'Midi Through' [type=kernel]
0 'Midi Through Port-0'
client 28: 'CASIO USB-MIDI' [type=kernel,card=3]
0 'CASIO USB-MIDI MIDI 1'
The Pi can read the MIDI from the keyboard just fine because this is the output for aseqdump -p 28 while playing keys from the keyboard
Waiting for data. Press Ctrl+C to end.
Source Event Ch Data
28:0 Note on 0, note 64, velocity 9
28:0 Note on 0, note 60, velocity 27
28:0 Note on 0, note 57, velocity 1
28:0 Note off 0, note 57, velocity 64
28:0 Note on 0, note 60, velocity 30
28:0 Note on 0, note 57, velocity 23
28:0 Note on 0, note 55, velocity 31
28:0 Note off 0, note 55, velocity 64
28:0 Note off 0, note 60, velocity 64
28:0 Note off 0, note 57, velocity 64
28:0 Note on 0, note 55, velocity 29
28:0 Note off 0, note 55, velocity 64
28:0 Note on 0, note 57, velocity 35
My Python version is 3.11. Any help is much appreciated.
When you open a port in Mido, you should specify which port you want it to open, by name. If you don't specify a port, it will open the system-specific default port, which can be overridden by environment variables
So, the fix for your project would be to specify the CASIO USB-MIDI as the input port
inport = mido.open_input("CASIO USB-MIDI MIDI 1")
Alternatively, you could leave the parameter empty in mido.open_input()
and instead configure the CASIO as the system default port by setting the environment variable:
export MIDO_DEFAULT_INPUT='CASIO USB-MIDI MIDI 1'
This might be preferable if you might use the same script with other devices later.