Need help with an Rpi Pico

Hello,

I am not a good programmer at all but I manage to make my accordion keyboard work as far as notes go.

I needed 5 potentiometers to control different parameters so I installed an ADS1115.

It is working perfectly with the test script provided with the lib BUT as soon as I add it to my main code it’s not working at all and give me thius error :

OSError: [Errno 110] ETIMEDOUT

can anyone help me solve this problem?

the lib is here :

the ads1115 function is dacmescouilles(), it works where it is now but I can’t put it in the “while” loop

here is my micropython script :

# Pi Pico MIDI Matrix Decode
#
# @diyelectromusic
# https://diyelectromusic.wordpress.com/2021/02/03/pi-pico-midi-matrix-decode/
#
#      MIT License
#      
#      Copyright (c) 2020 diyelectromusic (Kevin)
#      
#      Permission is hereby granted, free of charge, to any person obtaining a copy of
#      this software and associated documentation files (the "Software"), to deal in
#      the Software without restriction, including without limitation the rights to
#      use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
#      the Software, and to permit persons to whom the Software is furnished to do so,
#      subject to the following conditions:
#      
#      The above copyright notice and this permission notice shall be included in all
#      copies or substantial portions of the Software.
#      
#      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
#      FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
#      COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHERIN
#      AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
#      WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
from machine import Pin, I2C
from machine import ADC
import utime
import midi
from time import sleep
from ads1x15 import ADS1115

#configuration du ADS1115

i2c=I2C(0, sda=Pin(4), scl=Pin(5))
adc = ADS1115(i2c, address=72, gain=1)

def dacmescouilles():

    value = adc.read(0, 1)
    print(value)

dacmescouilles()

#juste la led de la pico
led = Pin(25, Pin.OUT)

#boutons octaves
bout_bass1 = Pin(2, Pin.IN,Pin.PULL_UP) #basses 
bout_bass2 = Pin(3, Pin.IN,Pin.PULL_UP) #basses
bout_acc1 = Pin(4, Pin.IN,Pin.PULL_UP) #accords
bout_acc2 = Pin(5, Pin.IN,Pin.PULL_UP) #accords



#potards
adc_pin_bend = Pin(28, mode=Pin.IN)
bend = ADC(adc_pin_bend)

#uart = UART(0,31250)

#librairie midi

my_midi = midi.Midi(0,Pin(0),Pin(1))
velocity = 127
note=48
debounce_gate=5





# tentons de faire un tableau de commande

grille_basses_noms=[
    ["fa","do","sol","re","la","mi",
     "si","fad","dod","lab","mib","sib",
     "Afa","Ado","Asol","Are","Ala","Ami",
     "Asi","Afad","Adod","Alab","Amib","Asib"
     ]
]

grille_basses_notes=[
    [                       #### NOTES ###########
     -7,    # FA            #    41   # r=8  c= 13   
     0,     # DO            #    48   #      c= 15     
     7,     # SOL           #    55   #      c= 11      
     2,     # RE            #    50   #      c= 14      
     -3,    # LA            #    45   #      c= 10     
     -8,    # MI            #    40   #      c= 12     
     -1,    # SI            #    47   # r=9  c= 13     
     -6,    # FA# / SOLb    #    42   #      c= 15     
     1,     # DO# / REb     #    49   #      c= 11     
     -4,     # SOL# / LAb    #    44   #      c= 14     
     3,     # RE# / MIb     #    51   #      c= 10     
     -2,    # LA# / SIb     #    46   #      c= 12
                            #### ACCORDS #########
     5+12,     # fa            #    53   # r=6  c= 13     
     12+12,    # do            #    60   #      c= 15     
     7+12,     # sol           #    67   #      c= 11     
     14+12,    # re            #    62   #      c= 14    
     9+12,     # la            #    57   #      c= 10     
     4+12+12,  # mi            #    52   #      c= 12     
     11+12,    # si            #    59   # r=7  c= 13     
     6+12,     # fa# / solb    #    54   #      c= 15     
     13+12,    # do# / reb     #    61   #      c= 11     
     8+12,     # sol# / lab    #    56   #      c= 14     
     15+12,    # re# / mib     #    63   #      c= 10     
     10+12     # la# / sib     #    58   #      c= 12     
     ]
]





# Details of how to make a keyboard matrix
# http://blog.komar.be/how-to-make-a-keyboard-the-matrix/

firstnote = 48 # C3
rows = []
cols = []
playnote = []
lastnote = []
canal_1 = 1  
canal_2 = 1  

#ads1115 test



#pitch sur dac du pico pin 28

def midiPitchBend():
    pot_bend = round(bend.read_u16()/4)   # conversion analogique-numérique 0-65535 vers 16384
    msb = pot_bend >> 7
    lsb = pot_bend & 127 
    my_midi.send_pitch_bend(224,lsb,msb)


#def midiMwh(z):
    #print("mod wheel = ",mw)
    #my_midi.send_control_change(midi.CHANNEL[z], 91, value=mw)

    #91 attaque? , 13 puissant, 12 subtile

# Switch OFF will be HIGH (operating in PULL_UP mode)
#notes = do re mi fa sol la >> row = 13,14,12,15,11,10 / col = 8
#notes = fa# sol# la# si do# re# >> row = 13,14,12,15,11,10 / col = 9
row_pins = [15,13,11,14,10,12]
numrows = len(row_pins)
for rp in range(0, numrows):
    rows.append(Pin(row_pins[rp], Pin.IN, Pin.PULL_UP))

# OPEN DRAIN mode means that when HIGH the pin is effectively disabled.
# According to the RP2 MicroPython code this is simulated on the RP2 chip.
# See https://github.com/micropython/micropython/blob/master/ports/rp2/machine_pin.c
# WARNING: At time of writing, this isn't in the MP release!
#          For now, just use standard Pin.OUT.
#




 #accord = 6,7 notes=8,9
col_pins = [8,9,6,7]
numcols = len(col_pins)
for cp in range(0, numcols):
    cols.append(Pin(col_pins[cp], Pin.OUT))


# Initialise Columns to HIGH (i.e. disconnected)
for c in range(0, numcols):
    cols[c].value(True)
    for r in range(0, numrows):
        # initialise the note list
        playnote.append(0)
        lastnote.append(0)

while True:

    # Activate each column in turn by setting it to low
    for c in range(0, numcols):
        cols[c].value(False)

        # Then scan for buttons pressed on the rows
        # Any pressed buttons will be LOW
        for r in range(0, numrows):
            if (rows[r].value() == False):
                playnote[c*numrows+r] = 1
                
            else:
                playnote[c*numrows+r] = 0

        # Disable it again once done
        cols[c].value(True)


    # Now see if there are any off->on transitions to trigger MIDI on
    # or on->off to trigger MIDI off
    for n in range(0, len(playnote)):
        if (playnote[n] > 0):
            midiPitchBend()
            #midiMwh(canal_1)



        if (playnote[n] == 1 and lastnote[n] == 0):


            for o in grille_basses_notes:
                print("######################################################################")
                print("note : ",firstnote+o[n])

                if (n < 12):

                    if (bout_bass1.value()==0):
                        my_midi.send_note_on(midi.CHANNEL[canal_1], firstnote+o[n], velocity)
                    if (bout_bass1.value()==1 & bout_bass2.value()==1):
                        my_midi.send_note_on(midi.CHANNEL[canal_1], firstnote+o[n]+12, velocity)
                        my_midi.send_note_on(midi.CHANNEL[canal_1], firstnote+o[n], velocity)
                    if (bout_bass2.value()==0):
                        my_midi.send_note_on(midi.CHANNEL[canal_1], firstnote+o[n]+12, velocity)
                        my_midi.send_note_on(midi.CHANNEL[canal_1], firstnote+o[n]+24, velocity)


                if (n > 11):
                    if (bout_acc1.value()==0):
                        utime.sleep_us(debounce_gate)
                        my_midi.send_note_on(midi.CHANNEL[canal_2], firstnote+o[n], velocity)
                    if (bout_acc1.value()==1 & bout_acc2.value()==1):
                        utime.sleep_us(debounce_gate)
                        my_midi.send_note_on(midi.CHANNEL[canal_2], firstnote+o[n], velocity)
                        my_midi.send_note_on(midi.CHANNEL[canal_2], firstnote+o[n]+12, velocity)
                    if (bout_acc2.value()==0):
                        utime.sleep_us(debounce_gate)
                        my_midi.send_note_on(midi.CHANNEL[canal_2], firstnote+o[n]+12, velocity)
                        my_midi.send_note_on(midi.CHANNEL[canal_2], firstnote+o[n]+24, velocity)






        if (playnote[n] == 0 and lastnote[n] == 1):

            utime.sleep_ms(10)
            my_midi.send_note_off(midi.CHANNEL[1], firstnote+o[n])            
            my_midi.send_note_off(midi.CHANNEL[1], firstnote+o[n]+12)            
            my_midi.send_note_off(midi.CHANNEL[1], firstnote+o[n]+24)            
            my_midi.send_note_off(midi.CHANNEL[1], firstnote+o[n])            
            my_midi.send_note_off(midi.CHANNEL[1], firstnote+o[n]+12)            
            my_midi.send_note_off(midi.CHANNEL[1], firstnote+o[n]+24)            




 

        lastnote[n] = playnote[n]





I would be so gratefull

☉ ‿ ⚆

ok, I am stupid. There were 2 buttons and the i2c channel on the same pins

☉ ‿ ⚆

2 Likes

don’t be too hard on yourself.

you know you are a pro developer when you feel productive after successfully hunting one chahracter for three days… :slight_smile:

(edit: from personal xp)

4 Likes

I don’t think we would have spotted that :slight_smile:

I didn’t even look as it’s Python and I have no experience of it, but now we know the issue it’s clearly there in the first 20 lines where pins 4 & 5 are declared twice.

Thanks for the sympathy.

It happened because i unpluged the switches to test the adc. 24h appart. As the higher part of the declarations were working (in my mind) i blamed the adc board and didn’t look close enough to the top of the code. Until i starter to duplicate line by line.

It was sorted rather quickly.

:hand_with_index_finger_and_thumb_crossed:

Hello,

I am once more in need of your help,

Everything is working fine on my accordion keyboard, pitchbend, modulation etc all connected to pots. But I cannot find a way to make the aftertouch erp channel to work at all.

I am using the sensai7 midi lib for micropython. From what I understand it should work properly. It is even recognized in midisnoop but there is no effect on the sound of the synt I want to control. No matter if I put the aftertouch before everything, before the note on or after.

Is there a specificity of this midi message I don’t respect?

here is the code :

# Pi Pico MIDI Matrix Decode
#
# @diyelectromusic
# https://diyelectromusic.wordpress.com/2021/02/03/pi-pico-midi-matrix-decode/
#
#      MIT License
#      
#      Copyright (c) 2020 diyelectromusic (Kevin)
#      
#      Permission is hereby granted, free of charge, to any person obtaining a copy of
#      this software and associated documentation files (the "Software"), to deal in
#      the Software without restriction, including without limitation the rights to
#      use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
#      the Software, and to permit persons to whom the Software is furnished to do so,
#      subject to the following conditions:
#      
#      The above copyright notice and this permission notice shall be included in all
#      copies or substantial portions of the Software.
#      
#      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
#      FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
#      COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHERIN
#      AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
#      WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
from machine import ADC
from machine import Pin, I2C
import utime
import midi
from time import sleep
from ads1x15 import ADS1115

#configuration du ADS1115

i2c=I2C(1, sda=Pin(26), scl=Pin(27))
adc = ADS1115(i2c, address=72, gain=1)


#juste la led de la pico
led = Pin(25, Pin.OUT)

#boutons octaves
bout_bass1 = Pin(19, Pin.IN,Pin.PULL_UP) #basses 
bout_bass2 = Pin(18, Pin.IN,Pin.PULL_UP) #basses
bout_acc1 = Pin(16, Pin.IN,Pin.PULL_UP) #accords
bout_acc2 = Pin(17, Pin.IN,Pin.PULL_UP) #accords
bout_midi1 = Pin(20, Pin.IN,Pin.PULL_UP) #midi
bout_midi2 = Pin(21, Pin.IN,Pin.PULL_UP) #midi



#potards
adc_pin_bend = Pin(28, mode=Pin.IN)
bend = ADC(adc_pin_bend)

#uart = UART(0,31250)

#librairie midi

my_midi = midi.Midi(0,Pin(0),Pin(1))
velocity = 127
note=48
debounce_gate=10





# tentons de faire un tableau de commande

grille_basses_noms=[
    ["fa","do","sol","re","la","mi",
     "si","fad","dod","lab","mib","sib",
     "Afa","Ado","Asol","Are","Ala","Ami",
     "Asi","Afad","Adod","Alab","Amib","Asib"
     ]
]

grille_basses_notes=[
    [                       #### NOTES ###########
     -7,    # FA            #    41   # r=8  c= 13   
     0,     # DO            #    48   #      c= 15     
     -5,    # SOL           #    55   #      c= 11      
     2,     # RE            #    50   #      c= 14      
     -3,    # LA            #    45   #      c= 10     
     -8,    # MI            #    40   #      c= 12     
     -1,    # SI            #    47   # r=9  c= 13     
     -6,    # FA# / SOLb    #    42   #      c= 15     
     1,     # DO# / REb     #    49   #      c= 11     
     -4,    # SOL# / LAb    #    44   #      c= 14     
     3,     # RE# / MIb     #    51   #      c= 10     
     -2,    # LA# / SIb     #    46   #      c= 12
                            #### ACCORDS #########
     5+12,     # fa            #    53   # r=6  c= 13     
     12+12,    # do            #    60   #      c= 15     
     7+12,     # sol           #    67   #      c= 11     
     14+12,    # re            #    62   #      c= 14    
     9+12,     # la            #    57   #      c= 10     
     4+12+12,  # mi            #    52   #      c= 12     
     11+12,    # si            #    59   # r=7  c= 13     
     6+12,     # fa# / solb    #    54   #      c= 15     
     13+12,    # do# / reb     #    61   #      c= 11     
     8+12,     # sol# / lab    #    56   #      c= 14     
     15+12,    # re# / mib     #    63   #      c= 10     
     10+12     # la# / sib     #    58   #      c= 12     
     ]
]





# Details of how to make a keyboard matrix
# http://blog.komar.be/how-to-make-a-keyboard-the-matrix/

firstnote = 48 # C3
rows = []
cols = []
playnote = []
lastnote = []
# MIDI

canal_1 = 1
canal_2 = 2


def bouton1(x):
    if (bout_midi1.value() == 1): 
        x = 1
    if (bout_midi1.value() == 0):
        x = 2

    return (x)

def bouton2(y):
    if (bout_midi2.value() == 1): 
        y = 2
    if (bout_midi2.value() == 0):
        y = 1

    return (y)

    


#pitch sur dac du pico pin 28

def midiPitchBend(x):
    pot_bend = round(bend.read_u16()/4)   # conversion analogique-numérique 0-65535 vers 16384
    msb = pot_bend >> 7
    lsb = pot_bend & 127 
    my_midi.send_pitch_bend(223+x,lsb,msb)

def mod_wheel(x):
    vMW = round(adc.read(7, 3)/206)
    my_midi.send_control_change(midi.CHANNEL[x], 1, value=vMW)
    return(vMW)

def mod_13(x):
    v13 = round(adc.read(7, 2)/206)
    my_midi.send_control_change(midi.CHANNEL[x], 13, value=-v13+127)
    return(v13)

def mod_91(x):
    v91 = round(adc.read(7, 1)/206)
    my_midi.send_control_change(midi.CHANNEL[x], 91, value=v91)
    return(v91)

def mod_64(x):
    v64 = round(adc.read(7, 0)/206)
    my_midi.send_control_change(midi.CHANNEL[x],64, value=v64)
    #my_midi.send_channel_aftertouch(midi.CHANNEL[x],amount=v64)
    return(v64)

def mod_aftertouch(x):
    my_midi.send_channel_aftertouch(midi.CHANNEL[x],amount=40)













    #91 attaque? , 13 puissant, 12 subtile

# Switch OFF will be HIGH (operating in PULL_UP mode)
#notes = do re mi fa sol la >> row = 13,14,12,15,11,10 / col = 8
#notes = fa# sol# la# si do# re# >> row = 13,14,12,15,11,10 / col = 9
row_pins = [15,13,11,14,10,12]
numrows = len(row_pins)
for rp in range(0, numrows):
    rows.append(Pin(row_pins[rp], Pin.IN, Pin.PULL_UP))

# OPEN DRAIN mode means that when HIGH the pin is effectively disabled.
# According to the RP2 MicroPython code this is simulated on the RP2 chip.
# See https://github.com/micropython/micropython/blob/master/ports/rp2/machine_pin.c
# WARNING: At time of writing, this isn't in the MP release!
#          For now, just use standard Pin.OUT.
#




 #accord = 6,7 notes=8,9
col_pins = [9,8,6,7]
numcols = len(col_pins)
for cp in range(0, numcols):
    cols.append(Pin(col_pins[cp], Pin.OUT))


# Initialise Columns to HIGH (i.e. disconnected)
for c in range(0, numcols):
    cols[c].value(True)
    for r in range(0, numrows):
        # initialise the note list
        playnote.append(0)
        lastnote.append(0)

while True:

    # Activate each column in turn by setting it to low
    for c in range(0, numcols):
        cols[c].value(False)

        # Then scan for buttons pressed on the rows
        # Any pressed buttons will be LOW
        for r in range(0, numrows):
            if (rows[r].value() == False):
                playnote[c*numrows+r] = 1
                
            else:
                playnote[c*numrows+r] = 0

        # Disable it again once done
        cols[c].value(True)


    # Now see if there are any off->on transitions to trigger MIDI on
    # or on->off to trigger MIDI off
    for n in range(0, len(playnote)):
        if (playnote[n] > 0):
            
            #mod_aftertouch(canal_1)
            #mod_aftertouch(canal_2)
            #print( "ouaich midi ",  canal_1,canal_2)
            midiPitchBend(canal_1)
            midiPitchBend(canal_2)
            
            mod_wheel(canal_1)
            mod_13(canal_1)
            mod_64(canal_1)
            mod_91(canal_1)

            mod_wheel(canal_2)
            mod_13(canal_2)
            mod_64(canal_2)
            mod_91(canal_2)

           

            canal_1 = bouton1(canal_1)
            canal_2 = bouton2(canal_2)

        if (playnote[n] == 1 and lastnote[n] == 0):
            
            led.value(1)

            for o in grille_basses_notes:
                #print("######################################################################")
                #print("note : ",firstnote+o[n])

                if (n < 12):

                    if (bout_bass1.value()==0):
                        
                        my_midi.send_note_on(midi.CHANNEL[canal_1], firstnote+o[n]-12, velocity)
                        my_midi.send_note_on(midi.CHANNEL[canal_1], firstnote+o[n], velocity)

                    if (bout_bass1.value()==1 & bout_bass2.value()==1):
                        my_midi.send_note_on(midi.CHANNEL[canal_1], firstnote+o[n], velocity)
                        my_midi.send_note_on(midi.CHANNEL[canal_1], firstnote+o[n]+24, velocity)
                        my_midi.send_note_on(midi.CHANNEL[canal_1], firstnote+o[n]+12, velocity)

                    if (bout_bass2.value()==0):
                        my_midi.send_note_on(midi.CHANNEL[canal_1], firstnote+o[n]+12, velocity)
                        my_midi.send_note_on(midi.CHANNEL[canal_1], firstnote+o[n]+24, velocity)


                if (n > 11):
                    if (bout_acc1.value()==0):
                        utime.sleep_us(debounce_gate)
                        my_midi.send_note_on(midi.CHANNEL[canal_2], firstnote+o[n], velocity)
                        my_midi.send_note_on(midi.CHANNEL[canal_2], firstnote+o[n]+12, velocity)
                    if (bout_acc1.value()==1 & bout_acc2.value()==1):
                        utime.sleep_us(debounce_gate)
                        my_midi.send_note_on(midi.CHANNEL[canal_2], firstnote+o[n]-12, velocity)
                        my_midi.send_note_on(midi.CHANNEL[canal_2], firstnote+o[n], velocity)
                        my_midi.send_note_on(midi.CHANNEL[canal_2], firstnote+o[n]+12, velocity)
                    if (bout_acc2.value()==0):
                        utime.sleep_us(debounce_gate)
                        my_midi.send_note_on(midi.CHANNEL[canal_2], firstnote+o[n], velocity)
                        my_midi.send_note_on(midi.CHANNEL[canal_2], firstnote+o[n]-12, velocity)






        if (playnote[n] == 0 and lastnote[n] == 1):
            
            led.value(0)

            #print("####»»»»####»»»»####»»»»#####»»»»####»»»»####")
            utime.sleep_ms(debounce_gate)
            my_midi.send_note_off(midi.CHANNEL[1], firstnote+o[n])            
            my_midi.send_note_off(midi.CHANNEL[1], firstnote+o[n]+12)            
            my_midi.send_note_off(midi.CHANNEL[1], firstnote+o[n]+24)            
            my_midi.send_note_off(midi.CHANNEL[1], firstnote+o[n]-12)             
            my_midi.send_note_off(midi.CHANNEL[2], firstnote+o[n])            
            my_midi.send_note_off(midi.CHANNEL[2], firstnote+o[n]+12)            
            my_midi.send_note_off(midi.CHANNEL[2], firstnote+o[n]+24)            
            my_midi.send_note_off(midi.CHANNEL[2], firstnote+o[n]-12)            
         




 

        lastnote[n] = playnote[n]





Thanks a lot

Just to be clear, midi snoop or whatever can see aftertouch messages on the midi/usb output, but the receiving synth doesn’t respond?

If that’s the case then I think it’s your receiving synth that is at fault and not the code. What synth is it and does it support aftertouch?

Hi yes I know but if I plug another synth, a mini brute for that matter, it does send the aftertouch and the synth responds.

I can’t find an example message of a basic note on / note off with the after touch involved… where to put it .

When nothing is being played the aftertouch should be 0, when you play a note and press harder then the aftertouch message with a value between 0-127 should be sent every time the adc inputs changes that the aftertouch strip is attached too. When you release a key or stop applying pressure the aftertouch should return to 0 and nothing should be sent.

So you have to check the adc input in your loop and and send aftertouch when that input changes regardless of wether a key is pressed or not. In reality it should only change on a keypress with pressure.

I’d separate the two: note on/off when the key changes, aftertouch whenever the ADC pressure changes. Then on key release, force aftertouch back to 0 so the receiving synth doesn’t keep seeing a stuck pressure value.

But the key mechanism should force aftertouch to zero or it’s faulty.

And I didn’t suggest that aftertouch is only triggered during the keypress, what I said was monitor the adc input in the loop and send aftertouch when a change is noted,

1 Like

Thank you. This was for a gig. I did not manage to make it work Before. I was too anxious i guess but now it’s ok thanks to your advices.

This is implémented on the accordion controller

2 Likes