diff --git a/README.md b/README.md index f492682..b9e2b30 100644 --- a/README.md +++ b/README.md @@ -8,23 +8,19 @@ Remember to edit netconf.py for network/OSC configuration. Connect the led strip data line to D5 (GPIO 14) * Computer side : List and hook to all midi devices (real or virtual). OSC commands generated from incoming midi messages : - - /noteon MidiChannel, note, velocity - - /noteoff MidiChannel, note - - /rawcc MidiChannel, CCnumber, CCvalue + - /noteon midichannel, note, velocity + - /noteoff midichannel, note + - /rawcc midichannel, CCnumber, CCvalue - /clock - /start - /stop * Micropython/ESP side : - - interpret /noteon and /noteoff and switch one led in a led strip. Changing or adding functions to clock or other midi msg is easy, look lserver.py. Look midix.py to get extensive list of transmitted midi messages. - + - interpret /noteon and /noteoff and switch one led in a led strip. Changing or adding functions to clock or other midi msg is easy, look lserver.py. - ESP 8266 from https://www.wemos.cc/en/latest/d1/d1_mini_lite.html - - Micropython firmware (select v1.13 with the right RAM amount): https://micropython.org/download/esp8266/ - - Flash firmware, upload python files, run files,... thonny IDE : https://thonny.org/ - - Great tutorials : https://randomnerdtutorials.com/getting-started-thonny-micropython-python-ide-esp32-esp8266/ diff --git a/esp/leds.py b/esp/leds.py index f8753ea..4019e92 100644 --- a/esp/leds.py +++ b/esp/leds.py @@ -57,7 +57,7 @@ def npcycle(): np[j] = (0, 0, 0) np[i % lednumber] = (126, 20, 126) np.write() - time.sleep_ms(150) + time.sleep_ms(15) npcolor(0,0,0) npcycle() diff --git a/esp/lserver.py b/esp/lserver.py index 64da095..c1161e5 100644 --- a/esp/lserver.py +++ b/esp/lserver.py @@ -8,6 +8,7 @@ import sys, time import socket from uosc.server import run_server, split_oscstr, parse_message, parse_bundle from uosc.client import send +from uosc.client import Client from machine import Pin import mynetconf as netconf import machine, neopixel @@ -21,13 +22,15 @@ MAX_DGRAM_SIZE = 1472 OSCport = 9001 ledpin = Pin(2, Pin.OUT) -stripin = Pin(14, Pin.OUT) ESPledstate = False -n = 8 - +stripin = Pin(14, Pin.OUT) +n = 144 np = neopixel.NeoPixel(stripin, n) +motherip = "192.168.2.104" +motherosc = Client(motherip, 9002) +leftnote = 36 def ESPledon(): global ESPledstate @@ -43,6 +46,28 @@ def ESPledoff(): ESPledoff() + +def noteledon(notenumber, velocity, r = 128, g=0 , b=64 ): + + if notenumber > leftnote-1: + + np[int((notenumber-leftnote)*2)] = (velocity*2,g,b) + np[int((notenumber-leftnote)*2)+1] = (velocity*2,g,b) + np.write() + motherosc.send('/noteledon', notenumber) + else: + motherosc.send('/notetoolow', notenumber) + +def noteledoff(notenumber): + + if notenumber > leftnote-1: + np[int((notenumber-leftnote)*2)] = (0, 0, 0) + np[int((notenumber-leftnote)*2)+1] = (0, 0, 0) + np.write() + motherosc.send('/noteledoff', notenumber) + else: + motherosc.send('/notetoolow', notenumber) + def npcycle(): for i in range(2 * n): @@ -50,7 +75,7 @@ def npcycle(): np[j] = (0, 0, 0) np[i % n] = (126, 20, 126) np.write() - time.sleep_ms(150) + time.sleep_ms(15) ''' def npcycle2(r, g, b, wait): @@ -90,32 +115,33 @@ def npbounce(): def OSCHandler(t, msg): - print() + #print() print("OSCHandler") + ''' print("OSC address:", msg[0]) # /on print("Type tags:", msg[1]) # 'i' print("Arguments:", msg[2]) # (1,) print() + ''' # /noteon midichannel note velocity if msg[0] == "/noteon": - print("NOTEON channel", msg[2][0], "note",msg[2][1], "velocity", msg[2][2]) - np[int(msg[2][1]%n)] = (255, 0, 153) - np.write() - + print("ESP : NOTEON channel", msg[2][0], "note",msg[2][1], "velocity", msg[2][2]) + noteledon(int(msg[2][1]), int(msg[2][2])) + #np[int(msg[2][1]%n)] = (255, 0, 153) + #np.write() # /noteoff midichannel note - if msg[0] =='/noteoff': - print("NOTEOFF channel", msg[2][0], "note",msg[2][1]) - np[int(msg[2][1]%n)] = (0, 0, 0) - np.write() + print("ESP : NOTEOFF channel", msg[2][0], "note",msg[2][1]) + noteledoff(int(msg[2][1])) + #np.write() def handle_rawosc(data, src, strict=False): try: head, _ = split_oscstr(data, 0) - if __debug__: print("head", head) + #if __debug__: print("head", head) if head.startswith('/'): messages = [(-1, parse_message(data, strict))] @@ -128,11 +154,12 @@ def handle_rawosc(data, src, strict=False): try: for timetag, (oscaddr, tags, args) in messages: + ''' if __debug__: print("OSC address: %s" % oscaddr) print("OSC type tags: %r" % tags) print("OSC arguments: %r" % (args,)) - + ''' print("Dispatching", timetag, (oscaddr, tags, args, src)) OSCHandler(timetag, (oscaddr, tags, args, src)) @@ -142,12 +169,14 @@ def handle_rawosc(data, src, strict=False): def run_server(saddr, port): + + motherosc.send('/runningserver', 1) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) if __debug__: print("Created OSC UDP server socket.") sock.bind((saddr, port)) - print("Listening for OSC messages on %s:%i.", saddr, port) + print("Listening for OSC messages on", saddr, port) try: while True: diff --git a/esp/main.py b/esp/main.py index 5093bf5..fba9cf1 100755 --- a/esp/main.py +++ b/esp/main.py @@ -10,3 +10,5 @@ print("in main IP :",ip) from lserver import main main(ip) +#from osctest import main +#main() \ No newline at end of file diff --git a/midix.py b/midix.py index 6aaec1b..b1a2045 100644 --- a/midix.py +++ b/midix.py @@ -72,6 +72,7 @@ ccontinue = mido.Message(type ="continue") reset = mido.Message(type ="reset") songpos = mido.Message(type ="songpos") +print(NOTE_ON, NOTE_OFF) #mode = "maxwell" ''' @@ -109,12 +110,12 @@ def SendLeds(oscaddress,oscargs=''): osclientlj = OSCClient() osclientlj.connect((serverIP, OSCPORT)) - #print("MIDI Aurora sending UI :", oscmsg, "to",TouchOSCIP,":",TouchOSCPort) + print("OSC sending to Leds :", oscmsg, "to",serverIP,":", OSCPORT) try: osclientlj.sendto(oscmsg, (serverIP, OSCPORT)) oscmsg.clearData() except: - log.err('Connection to Aurora UI refused : died ?') + log.err('OSC Connection to Leds : died ?') pass #time.sleep(0.001 @@ -158,8 +159,8 @@ def MidinProcess(inqueue, portname): while True: time.sleep(0.001) msg = inqueue_get() - #print("") - #print("Generic from", portname,"msg : ", msg) + print("") + print("Generic from", portname,"msg : ", msg) # NOTE ON message on all midi channels @@ -171,7 +172,7 @@ def MidinProcess(inqueue, portname): print() print("NOTE ON :", MidiNote, 'velocity :', MidiVel, "Channel", MidiChannel) #print("Midi in process send /aurora/noteon "+str(msg[1])+" "+str(msg[2])) - SendLeds("/noteon",[MidiChannel, msg[1], msg[2]]) + SendLeds("/noteon",[MidiChannel, MidiNote, MidiVel]) ''' # Sampler mode : note <63 launch snare.wav / note > 62 kick.wav @@ -192,16 +193,17 @@ def MidinProcess(inqueue, portname): ''' # NOTE OFF or Note with 0 velocity on all midi channels - if NOTE_OFF -1 < msg[0] < 145 or (NOTE_OFF -1 < msg[0] < 160 and msg[2] == 0): + if NOTE_OFF -1 < msg[0] < 144 or (NOTE_OFF -1 < msg[0] < 160 and msg[2] == 0): - print("NOTE_off :",NOTE_OFF) + MidiNote = msg[1] if msg[0] > 143: MidiChannel = msg[0]-144 else: MidiChannel = msg[0]-128 + print("NOTE_off :",MidiNote, "Channel", MidiChannel) #print("NOTE OFF :", MidiNote, "Channel", MidiChannel) #print("Midi in process send /aurora/noteoff "+str(msg[1])) - SendLeds("/noteoff",[MidiChannel, msg[1]]) + SendLeds("/noteoff",[MidiChannel, MidiNote]) # # CC on all Midi Channels @@ -210,7 +212,7 @@ def MidinProcess(inqueue, portname): MidiChannel = msg[0]-175 print() #print("channel", MidiChannel, "CC :", msg[1], msg[2]) - print("Midi in process send /aurora/rawcc "+str(msg[0]-175-1)+" "+str(msg[1])+" "+str(msg[2])) + print("Midi in process send /rawcc "+str(msg[0]-175-1)+" "+str(msg[1])+" "+str(msg[2])) SendLeds("/rawcc",[msg[0]-175-1, msg[1], msg[2]]) '''