MIDi note velocity

I'm new to Arduino, and have a background in MIDI.

I followed a project by Jason Bauer to use a Leonardo to run solenoids for a drum robot. It worked with the sketch I got here: https://efundies.com/src/arduino/midi-solenoids.ino

Now I am trying to get the MIDI notes to work with velocity. The way the code was posted runs the solenoids at full velocity.

Please see attached pics. In the first pic you can see jason's notes about how to get velocity turned on.

In the 2nd pic... I don't get what to change from his comments (circled in blue).

The "analogWrite" circled in red is a change I made, it had been "digitalWrite" like below circled in green. I'm hoping that is what you'd change to get the kick drum solenoid (kickMidi) to change to velocity. ,

The other instructions where it says "just be sure to double to value because midi is 0-127"... I'm not sure if that's a typo and should read "double the value" or if I'm supposed to enter those specific words somewhere in the sketch? Maybe he means to just compress the MIDI velocities so they are using a range, say of 100 to 127 instead of 000 to 127 because solenoids draw a lot of juice at startup.

I'm using Cubase to output notes to the card and it works fine. On my MIDI track you can't double the values and get anything to be over 127. Or does it mean that I'm supposed to do something in the sketch so the velocity is doubled there?

Sorry for my layman's terminology.

thanks

MIDI.jpg

analogWrite.jpg

Try posting text as text not as pictures. And post the complete program. It's a lot more likely that people will help if you make it easy for them.

With what little you have posted I have no idea where 'velocity' comes from or what values it might. So I can't tell if you might want to double it or not. But I can guess that you'll probably want to remove the if statement and the "velocity = HIGH;" line.

Steve

Thanks slipstik, I'll try and delete the if statement. When I change the digitalWrite to analogWrite on the snare there was no solenoid movement on that pin (pin 1).

Here is the complete program:

#include <MIDIUSB.h>

// these are the arduino pins that the solenoids are hooked up to
enum drumPins {kickPin = 0, snarePin = 1, hhPin = 2, crashPin = 3, cowbellPin = 4 , openhatPin = 5};

// these are the midi notes that each solenoid triggers on, as well as an alternate for each
enum midiNotes {kickMidi = 36, snareMidi = 38, hhMidi = 42, crashMidi = 49, cowbellMidi = 39, openhatMidi = 46};
enum midiNoteAlts {kickMidiAlt = 44, snareMidiAlt = 48, hhMidiAlt = 45, crashMidiAlt = 149, cowbellMidiAlt = 47, openhatMidiAlt = 146};

void setup() {
 // the serial port is just used as a monitor for debugging
 // it is not needed for midi
 Serial.begin(115200);

 // setup all output pins
 for(int i=0; i<=8; i++) {
   pinMode(i, OUTPUT);
 }
}

void loop() {
 //listen for new MIDI messages
 midiEventPacket_t rx = MidiUSB.read();
 processMidi(rx);
}

void processMidi(midiEventPacket_t rx) {
   switch (rx.header) {
   case 0x0:
     // do nothing
     break;

   // note on
   case 0x9:
     handleNoteOn(rx.byte1 & 0xF, rx.byte2, rx.byte3);
     break;
   
     // note off
     case 0x8:
       handleNoteOn(rx.byte1 & 0xF, rx.byte2, 0);
     break;

   // control change
   case 11:
       Serial.print("CC: ");
       Serial.print(rx.byte2);
       Serial.print(":");
       Serial.print(rx.byte3);
       Serial.print("\n");
     break;

   default:
     Serial.println(rx.header);
     break;
 }
}

void handleNoteOn(byte channel, byte pitch, byte velocity) {
 // it is possible to use the actual midi velocity here, just be sure to
 // double to value because midi is 0-127
 // and then change digitalWrite to analogWrite
 if(velocity > 0) {
   velocity = HIGH;
 }

 switch (pitch) {
   case kickMidi:
   case kickMidiAlt:
     Serial.print("Kick: ");
     digitalWrite(kickPin, velocity);
     break;
   case snareMidi:
   case snareMidiAlt:
     Serial.print("Snare: ");
     digitalWrite(snarePin, velocity);
     break;
   case hhMidi:
   case hhMidiAlt:
     Serial.print("HH: ");
     digitalWrite(hhPin, velocity);
     break;
   case crashMidi:
   case crashMidiAlt:
     Serial.print("Crash: ");
     digitalWrite(crashPin, velocity);
     break;
   case cowbellMidi:
   case cowbellMidiAlt:
     Serial.print("Cowbell: ");
     digitalWrite(cowbellPin, velocity);
     break;
   case openhatMidi:
   case openhatMidiAlt:
     Serial.print("Open hat: ");
     digitalWrite(openhatPin, velocity);
     break;
   default:
     // print the midi note value, handy for adding new notes
     Serial.print("Note(");
     Serial.print(pitch);
     Serial.print("): ");
     break;
 }

 if(velocity == 0) {
   Serial.println("off");
 } else {
   Serial.println("on");
 }
}

I tried deleting:

if(velocity > 0) {
velocity = HIGH;

and I changed digitalWrite to analogWrite for the snarePin (pin 1) and it compiled and loaded fine but now pins o and 2 work but snarePin is silent.

I also tried changing the above if statement to:

if(velocity > 150) {
velocity = HIGH;

and also to:

if(velocity > 126) {
velocity = HIGH;

to no avail. I don't have a clue what I'm doing so I am just trying anything.

I found this page:

It says on my Leonardo card only pins 3, 5, 6, 9, 10, 11, 13 are capable of using analogWrite.

So pins 0,1,2,4,7,8 and 12 cannot be used with velocity with MIDI. I hope I have that right.

I reloaded the original code (post#2 above) and changed pin 3 (crash note number 49) to analogWrite and it appears to work but the signal is too weak to move the solenoid. The if statement discussed above is still there.

I am powering a 12V solenoid with a mosfet card which has an led that is indicating it is getting a signal from pin 3, but the led is much dimmer than with the other digitalWrite pins. I am sending a MIDI velocity of 127 to pin 3 just like the other pins that work but it appears that because they are set to digitalWrite they are getting a much hotter signal.

It feels like I need to increase the MIDI velocity as was described earlier in order to increase the PWN signal to a useable level. Is there a way to do that in MidiUsb?

I am powering a 12V solenoid with a mosfet card

Can you supply a link to this card please, the MOSFET might not be a logic level one.

Using a digital write results in no PWM at all, it gives a full logic output for any number above zero.
To increase the velocity signal simply multiply it by two.

Please read the how to use this forum sticky post, it tells you how to post code here. Go back and edit your posts with code in them so that it is posted correctly.

So pins 0,1,2,4,7,8 and 12 cannot be used with velocity with MIDI. I hope I have that right

That is correct.

Only use analogWrite on pins capable of PWM operation. Applying PWM to a solenoid has only a very limited effect on the pull in time. You might want to use a map function to compress the range of velocities you get into a range that actually works for the solenoids you have.

re: "To increase the velocity signal simply multiply it by two."

The signal comes from a MIDI track, it is already at 127, the max for a MIDI note velocity. How do I multiply it by two if it's already maxed out?

The card is: IRF520 24V MOSFET Driver Module

I will edit earlier posts when I can get back to my other computer thanks for the tip.

The same way as you multiply any variable by two

velocity = velocity * 2;

Where do I put that in the sketch please?

And yes, as far as compressing the velocities into a range that works i am familiar with doing that on Cubase. The problem is though that when using analogWrite and the max velocity is 127 that only gives me what seems like 50% of what using digitalWrite gives to the solenoid, not enough to move the solenoid at all.

So I think I need to do what you mentioned with the velocity = velocity * 2; code but I don't know where to put it in the sketch.

After I do that I can fine tune the MIDI velocities in Cubase.

You replace this code

if(velocity > 0) {
   velocity = HIGH;
 }

With

velocity = velocity * 2;

Then use PWM capable pins along with analogWrite for the solenoids you want to use proportionally.

The problem is though that when using analogWrite and the max velocity is 127 that only gives me what seems like 50% of what using digitalWrite gives to the solenoid, not enough to move the solenoid at all.

Yes 50% is what you get when you generate PWM with a value of 127, that is because the maximum PWM value is 255.
See http://www.thebox.myzen.co.uk/Tutorial/PWM.html

After I do that I can fine tune the MIDI velocities in Cubase.

If you still don’t get them pulling in enough then increase the time between a note on and note off message.

Youza - it worked. Thanks Mike!

I was able to only get a narrow range of volume, the solenoid didn't hit the cowbell until a velocity of 124. But it does give you some variation in tone, the 124 hits sound less bright.

Good idea about making the notes longer, will try that.

Mahalos!

I'm making a robot drum project using a Leonardo card and 12V solenoids with IRF520 24V MOSFET driver modules.

I'm using a MIDI track to supply the Leonardo with MIDI note data and using note velocity to change the PWM thus the solenoid voltage.

I've been studying analogWrite() - Arduino Reference

I'm trying to decide which pins I should use for which solenoids. I am using velocity, so I need to use the pins that work with analogWrite, the PWM pins.

I know that the PWM frequency for pins 3 & 11 is 980 Hz, and the rest use 490 Hz, and have read the warning that pins 5 and 6 will have higher-than-expected duty cycles. I see where it says it may result in a value of 0 not fully turning off the output on pins 5 and 6. I understand that you wouldn't want the solenoid to not turn off. I'm trying to determine if any of these factors should affect my pin choices.

I might be adding some servo motors to the project at some point if that matters.

My Leonardo card has a ≈ symbol next to pins 3,5,6,9,10 and 11 and designates them as PWM. It says "DIGITAL (PWM ≈). But there's no ≈ symbol next to pin 13 but the analogWrite page says pin 13 is PWM capable.

As far as my project, can I just use pins 3,5,6,9,10,11 and 13 as if they are identical?

You can you any of the PWM pins. As for your driver modules, the IRF520 is not a logic level mosfet. Are you using them directly or is there other circuitry to drive the gate at voltages above 5V?

I have an 12V AC adapter hooked up to the IRF520 Mosfet card to power the 12V solenoid.

Am I correct in thinking that for what I'm doing I wouldn't notice any difference in any of the PWM pins?

And do I need to be concerned about the warning that pins 5 and 6 can act oddly with a value of zero?

Thanks

And do I need to be concerned about the warning that pins 5 and 6 can act oddly with a value of zero?

I don't understand that warning.

analogWrite(pin, 0) is executed as digitalWrite(pin, LOW)

From wiring_analog.c

void analogWrite(uint8_t pin, int val)
{
	// We need to make sure the PWM output is enabled for those pins
	// that support it, as we turn it off when digitally reading or
	// writing with them.  Also, make sure the pin is in output mode
	// for consistenty with Wiring, which doesn't require a pinMode
	// call for the analog output pins.
	pinMode(pin, OUTPUT);
	if (val == 0)
	{
		digitalWrite(pin, LOW);
	}
	else if (val == 255)
	{
		digitalWrite(pin, HIGH);
	}
	else
	{

It may just be me, but if I was writing that code, I would have made it:

       else if (val >= 255)
        {
                digitalWrite(pin, HIGH);
        }

The IRF520 is generally OK up to 500 mA driven by 5 V. For a higher current, you would want an IRL device.

Thanks cattledog, I was referring to this page:

where at the bottom under "Notes and Warnings" is says:

"The PWM outputs generated on pins 5 and 6 will have higher-than-expected duty cycles. This is because of interactions with the millis() and delay() functions, which share the same internal timer used to generate those PWM outputs. This will be noticed mostly on low duty-cycle settings (e.g. 0 - 10) and may result in a value of 0 not fully turning off the output on pins 5 and 6."

It probably (hopefully) isn't important but the fact that pin 13 doesn't, when viewing the Leonardo card from the side, have the "≈" near it like the other PWM pins made me wonder if there was something particular about that pin. My "≈" symbol is as close to the actual symbol I can find on my Mac.

Paul thanks and I'll do my power calculations and look at IRL's if I exceed what the IRF520's can provide. The ones I bought say they are 24V <5a which is probably optimistic but they are only on for a very short amount of time and don't get hot.

Pin 13 is a PWM pin on the Leonardo; you can write a simple test sketch to fade it with analogWrite.

void loop()
{
  for(int cnt=0; cnt <=255;cnt++)
  {
    analogWrite(LED_BUILTIN, cnt);
    delay(50);
  }
}

Not tested.

Thanks, I appreciate all the help.

I think I answered this question in your other thread on the same topic.
Which finished with the words

Youza - it worked. Thanks Mike!

Why ask again what I told you in the first place?

You asked

So pins 0,1,2,4,7,8 and 12 cannot be used with velocity with MIDI. I hope I have that right.

To which I replied
That is correct.

Why disrespect this forum by cross posting, which is specifically against the rules?