blinkm maxm and midi, programming advices needed!

Hello,

I need some basic programming advice on my project. I'm driving maxm rgb led modules with midi from ableton live. I want to be able to control the color (hue) with the note intensity value, the saturation with the channel volume control change and the value with the channel control n°14.
For now, when one of this message is received, the BlinkM_fadeToHSB() is called with the changed parameters. The problem is I can't get led's off with the intensity at 1 because the other functions are still called by the other functions fadeToHSB called. How can I manage this better?

Second short question, my midi data values are from 1 to 127 and I would like to transform them from 0 to 255 with artificial +1 increments, is there an elegant way to do that?

Last one, due to the midi specific baud rate, I can't get the serial monitor working to have a look at my variables or midi in messages. Is there a workaround for that?

Thanks to all, here is my code. Maxm is externaly powered, midi in arrives on rx pin.

#include "Wire.h"
#include "BlinkM_funcs.h"
#include <MIDI.h>  

#define LED 13  

byte blinkm_addr = 0x09; 
int color = 0;
int intensity = 255;
int saturation= 255;

// Below is my function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity
void MyHandleNoteOn(byte channel, byte pitch, byte velocity) {
  digitalWrite(LED,HIGH);  //Turn LED on
  if (velocity == 1) {//A NOTE ON message with a velocity = 1is actualy a NOTE OFF
    digitalWrite(LED,LOW);//Turn LED off
    BlinkM_fadeToHSB(blinkm_addr, 0, 0, 0);
  }
  color = velocity*2+1; 
  BlinkM_fadeToHSB(blinkm_addr, color, saturation, intensity);
}

void HandleControlChange (byte channel, byte number, byte value){
  if (number == 7){
    intensity = value*2+1;
    BlinkM_fadeToHSB(blinkm_addr, color, saturation, intensity);
    }
    if (number == 14){
    saturation = value*2+1;
    BlinkM_fadeToHSB(blinkm_addr, color, saturation, intensity);
    
  }
 

void setup() {
  BlinkM_begin();
  BlinkM_stopScript(blinkm_addr);
  BlinkM_fadeToHSB(blinkm_addr, 0, 0, 0);
  BlinkM_setFadeSpeed(blinkm_addr,255);
 
  pinMode (LED, OUTPUT); 
  MIDI.begin(MIDI_CHANNEL_OMNI); 
 
  MIDI.setHandleNoteOn(MyHandleNoteOn); 
  MIDI.setHandleControlChange (HandleControlChange);
 
}

void loop() { // Main loop
  MIDI.read(); // Continually check what Midi Commands have been received
 
}

rrok:
Last one, due to the midi specific baud rate, I can't get the serial monitor working to have a look at my variables or midi in messages. Easy there a workaround for that?

Hi!

I don't see where you are attempting to do serial prints in the sketch you posted.

I've deleted them for now but they were here for eventual troubleshooting :

void MyHandleNoteOn(byte channel, byte pitch, byte velocity) {
  digitalWrite(LED,HIGH);  //Turn LED on
  if (velocity == 1) {//A NOTE ON message with a velocity = 1is actualy a NOTE OFF
    digitalWrite(LED,LOW);//Turn LED off
    BlinkM_fadeToHSB(blinkm_addr, 0, 0, 0);
  }
  color = velocity*2+1; 
  BlinkM_fadeToHSB(blinkm_addr, color, saturation, intensity);

Serial.write(velocity);

}

and adding Serial.begin(38400) to the setup

What pins on your board are you using for MIDI, and what ones for Serial debugging?

I m using pin 0, Rx for midi in. I have no idea how to specify another in for serial debugging.
Thanks!

That is because you can't specify other pins for debugging.
You could use software serial and then build a TTL to RS232 converter. Then use a USB to RS232 lead and another serial monitor like putty,, but that is complex.

Transforming 1 to 127 into 0 to 255 can be done with the map function.

Ok thanks that's very clear.
I'll try the map function for the range conversion.

Do you think it'll be better to keep my functions :

BlinkM_fadeToHSB(blinkm_addr, color, saturation, intensity);

in the loop part and just change the color, saturation, intensity variables value in the midi callbacks?

My code is a bit better now, the map function work perfectly, thanks! I still can't figure out how to interrupt the leds when I receive a note at velocity>1. I've tried many different scheme but nothing works. Maybe it's more a midi than LED problem...Here is a version with a boolean between the two callbacks.

#include "Wire.h"
#include "BlinkM_funcs.h"

#include <MIDI.h>  // Add Midi Library

#define LED 13    // Arduino Board LED is on Pin 13

byte blinkm_addr = 0x09; // addresse du master controle
int color = 0;
int intensite = 255;
int saturation = 255;
boolean oklight = true; 

// Below is my function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity
void MyHandleNoteOn(byte channel, byte pitch, byte velocity) {
  digitalWrite(LED,HIGH);  //Turn LED on
  if (velocity == 1) {//A NOTE ON message with a velocity = Zero is actualy a NOTE OFF
    digitalWrite(LED,LOW);//Turn LED off
    oklight = false;
  }
  if (velocity > 1) {
   oklight = true;
  } 
}

void HandleControlChange (byte channel, byte number, byte value){  
while (oklight == true) { 
    if (number == 7 ){
      intensite = map(value, 0, 127,0, 255);
      BlinkM_fadeToHSB(blinkm_addr, color, saturation , intensite);
      }
      if (number == 14 ){
      saturation = map(value, 0, 127,0, 255);
      BlinkM_fadeToHSB(blinkm_addr, color, saturation, intensite);
      }
      if (number == 13 ){
      color = map(value, 0, 127, 0, 255); 
      BlinkM_fadeToHSB(blinkm_addr, color, saturation, intensite);
      }
}
  }
 

void setup() {
  BlinkM_begin();
  BlinkM_stopScript(blinkm_addr);
  BlinkM_fadeToHSB(blinkm_addr, 43, 0, 255);
  BlinkM_setFadeSpeed(blinkm_addr,255);
 
  pinMode (LED, OUTPUT); // Set Arduino board pin 13 to output
  MIDI.begin(MIDI_CHANNEL_OMNI); // Initialize the Midi Library.
// OMNI sets it to listen to all channels.. MIDI.begin(2) would set it
// to respond to channel 2 notes only.
 
  MIDI.setHandleNoteOn(MyHandleNoteOn); // This is important!! This command
  // tells the Midi Library which function I want called when a Note ON command
  // is received. in this case it's "MyHandleNoteOn".
  MIDI.setHandleControlChange (HandleControlChange);
 
}

void loop() { // Main loop
  MIDI.read(); // Continually check what Midi Commands have been received
 
}

Someone inspired?

still can't figure out how to interrupt the leds when I receive a note at velocity>1

This is because you are using those built in functions to control your LEDs. These functions do not return until the fading is compleate. To get over this you will have to code this yourself in an interruptable fashion along the lines of the blink without delay sketch.

well I though I could find a way to have one instance of the builtin function in the loop() and sending paramaters from the callbacks but that doesn't work or I'm doing it wrong. I've change the fade time to "instantaneous" so these functions returns quite fast, maybe a wait(1) could be the solution.

here is the code of the fadetohsb function

// Fades to an HSB color
static void BlinkM_fadeToHSB(byte addr, byte hue, byte saturation, byte brightness)
{
  Wire.beginTransmission(addr);
  Wire.write('h');
  Wire.write(hue);
  Wire.write(saturation);
  Wire.write(brightness);
  Wire.endTransmission();
}

.

I suppose the problem appears when I open two connection on the wire. But strangely this code where the led changes are only from midi control change callback works :

#include "Wire.h"
#include "BlinkM_funcs.h"
#include <MIDI.h>  // Add Midi Library
#define LED 13    // Arduino Board LED is on Pin 13

byte blinkm_addr = 0x09; // addresse du master controle
int color = 0;
int intensite = 255;
int saturation = 255;

// Below is my function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity
void MyHandleNoteOn(byte channel, byte pitch, byte velocity) {
  digitalWrite(LED,HIGH);  //Turn LED on
  if (velocity == 1) {//A NOTE ON message with a velocity = Zero is actualy a NOTE OFF
    //BlinkM_fadeToHSB(blinkm_addr, 0, 0, 0);
  }
  if (velocity > 1) {
  //color = map(velocity, 1, 127, 0, 255);
  } 
}

void HandleControlChange (byte channel, byte number, byte value){   
    if (number == 7 ){
      intensite = map(value, 0, 127,0, 255);
      BlinkM_fadeToHSB(blinkm_addr, color, saturation , intensite);
      }
      if (number == 14 ){
      saturation = map(value, 0, 127,0, 255);
      BlinkM_fadeToHSB(blinkm_addr, color, saturation, intensite);
      }
      if (number == 13 ){
      color = map(value, 0, 127, 0, 255); 
      BlinkM_fadeToHSB(blinkm_addr, color, saturation, intensite);
      }
  }
 

void setup() {
  BlinkM_begin();
  BlinkM_stopScript(blinkm_addr);
  BlinkM_fadeToHSB(blinkm_addr, 43, 0, 255);
  BlinkM_setFadeSpeed(blinkm_addr,255);
 
  pinMode (LED, OUTPUT); // Set Arduino board pin 13 to output
  MIDI.begin(MIDI_CHANNEL_OMNI); // Initialize the Midi Library.
// OMNI sets it to listen to all channels.. MIDI.begin(2) would set it
// to respond to channel 2 notes only.
 
  MIDI.setHandleNoteOn(MyHandleNoteOn); // This is important!! This command
  // tells the Midi Library which function I want called when a Note ON command
  // is received. in this case it's "MyHandleNoteOn".
  MIDI.setHandleControlChange (HandleControlChange);
 
}

void loop() { // Main loop
  MIDI.read(); // Continually check what Midi Commands have been received
 
}

So I've added two boolean “tokens“ between the midiNoteOn and midiControlChange callbacks and it works! It thus wait the return of the function before being able to lauch a new transmission. Not sure it's the most elegant wait to do it but as for now it's a good start.

#include "Wire.h"
#include "BlinkM_funcs.h"

#include <MIDI.h>  // Add Midi Library

#define LED 13    // Arduino Board LED is on Pin 13

byte blinkm_addr = 0x09; // addresse du master controle
int color = 0;
int intensite = 255;
int saturation = 255;
boolean oklight = true; 
boolean oksignal = true;

// Below is my function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity
void MyHandleNoteOn(byte channel, byte pitch, byte velocity) {
  digitalWrite(LED,HIGH);  //Turn LED on
  if (velocity == 1) {//A NOTE ON message with a velocity = Zero is actualy a NOTE OFF
    digitalWrite(LED,LOW);//Turn LED off

    if (oksignal==true) {
      oklight = false;
      BlinkM_fadeToHSB(blinkm_addr, 0, 0, 0);
    }
  }
  if (velocity > 1) {
  BlinkM_fadeToHSB(blinkm_addr, color, saturation , intensite);
  oklight = true;
   } 
}

void HandleControlChange (byte channel, byte number, byte value){   
    if (number == 7 ){
      intensite = map(value, 0, 127,0, 255);
      }
      if (number == 14 ){
      saturation = map(value, 0, 127,0, 255);
      //BlinkM_fadeToHSB(blinkm_addr, color, saturation, intensite);
      }
      if (number == 13 ){
      color = map(value, 0, 127, 0, 255); 
      //BlinkM_fadeToHSB(blinkm_addr, color, saturation, intensite);
      }
      if (oklight== true){
      oksignal = false;
      BlinkM_fadeToHSB(blinkm_addr, color, saturation , intensite);
      oksignal = true;
      }
  }
 

void setup() {
  BlinkM_begin();
  BlinkM_stopScript(blinkm_addr);
  BlinkM_fadeToHSB(blinkm_addr, 43, 0, 255); // instant fade
  BlinkM_setFadeSpeed(blinkm_addr,255);
 
  pinMode (LED, OUTPUT); // Set Arduino board pin 13 to output
  MIDI.begin(MIDI_CHANNEL_OMNI); // Initialize the Midi Library.
// OMNI sets it to listen to all channels.. MIDI.begin(2) would set it
// to respond to channel 2 notes only.
 
  MIDI.setHandleNoteOn(MyHandleNoteOn); // This is important!! This command
  // tells the Midi Library which function I want called when a Note ON command
  // is received. in this case it's "MyHandleNoteOn".
  MIDI.setHandleControlChange (HandleControlChange);
 
}

void loop() { // Main loop
  MIDI.read(); // Continually check what Midi Commands have been received 
}