MIDI to Stepper motors

Hello, does anybody has experienced to send MIDI serial data to stepper motors? I’m trying to send either MIDI notes and CC controller to the stepper. My target is to move (starting from position zero C3 central note ) back and forth following the semitones sequence. Any suggestion to start?

You will have to give a much better explination about what you want to do and also post some code showing what you have tried.

You have first to split your task into two pieces and get those working, then
combine. One reads MIDI messages and extracts pitch info. The other moves a
stepper to a given position.

I’m trying to do the same thing. I’m very new to coding but I’ve been plugging away at it and I think I’m starting to understand the syntax. All of the code that I’ve seen that has tried to implement stepper motors with MIDI have been written with what I think is a modified Arduino firmware called usbMIDI. I also think that the only way to really be able to play ‘notes’ is messing with the timers. Please forgive me, I don’t have all the proper terminology yet… but here is my first attempt at trying to make a sketch that doesn’t require a modified firmware. It might be impossible, I really don’t know. What i’ve got so far is really quite large too, I’m not sure what the exact limit is to the size here but any feedback would be really deeply appreciated. I left a lot of notes just for myself to remember things I learned, and how I got places, etc…

#include<MIDI.h>
#include<Stepper.h>
#include<float_notes.h>


// LED pin
int ledPin = 13;
//how many steps per revolution for your stepper?
const int stepsPerRevolution = 200;
//assign outputs to the motor driver (my motor is named MrHappy)
Stepper MrHappy(stepsPerRevolution, 3,5,6,9);
// Are we currently playing a note?
bool playing = false;
//The desired delay between motor steps to achieve the requested note/frequency
float desired_delay = 0.0;
//The current delay between motor steps
float curr_delay = 0.0;
//The last note that was received - used to decide when to turn off the motor
byte last_note = 0.0;
//The speed at which the controller will glide from one note to the next
//units is the number of microseconds to add to curr_delay per iteration
//until it reaches desired delay
int const glide = 10;
//convert a midi note to the number of microseconds we need to delay 
float note2microseconds(byte note)
 //******************************************
//***************HELP!!!!!!!!!!**************
// {
 // return 1.0 / notes[note] * 1000000.0;
 // }
 
 //should i replace [note] with [byte note]?
//*******************************************
//*******************************************
void OnNoteOn(byte channel, byte pitch, byte velocity) {
  //
 {
  last_note = note;
  //set the desired delay by converting the MIDI note
  desired_delay = note2microseconds(note);
  
  //if we're not currently playing, then we should try to accelerate
  //into the requested note
  if(!playing)
    curr_delay = desired_delay + 600;
    
  playing = true;
  digitalWrite(ledPin, HIGH);
}

//Called when we recieve a MIDI note-off event
void OnNoteOff(byte channel, byte note, byte velocity)
{
  //only turns off the last requested note
  if(note == last_note)
  {
    playing = false;
    digitalWrite(ledPin, LOW);
  }
}

/////////////////SETUP!
////////////////////////
////////////////////////
////////////////////////
////////////////////////

void setup()
{
  pinMode(ledPin, OUTPUT);
  //get that serial party started at a baudrate that synthesizers like
  Serial.begin(31250); 
  //I AM NOT SURE ABOUT THS BIT- WHICH ONE IS BETTER TO USE?
  MIDI.begin(MIDI_CHANNEL_OMNI); 
  //Connect the HandleNoteOn function to the lib, so it is called upon 
  //reception of a NoteOn.  
  MIDI.setHandleNoteOff(OnNoteOff); //
  MIDI.setHandleNoteOn(OnNoteOn); //PUT THE NAME OF THE FUNCTION
  
  digitalWrite(ledPin,HIGH); //little LED lights up when he is ready

  //pinMode(3, OUTPUT); //digital out to first stepper driver is on pin 3
  //pinMode(5, OUTPUT); //digital out to second stepper driver is on pin 5
  //pinMode(6, OUTPUT); //digital out of third stepper driver is on pin 6
  //pinMode(9, OUTPUT); //you get the idea...
  //pinMode(13, OUTPUT); //...
  //WOOPS AGAIN! THIS WENT AWAY WHEN WE STARTED USING THE STEPPER LIB
}

void loop() {
  //call MIDI.read as fast as you can to avoid that latency. QUICK!
  MIDI.read();
  
}

also, here is my .h file i made from a code i found written for this usbMIDI firmware. I am unfamiliar with that whole syntax but I am certain that this is the really important part… I am wondering if it has to do with the [note] definition that I couldn’t identify as well.

float notes[] = {
  8.1757989156,   // 0
  8.6619572180,   // 1
  9.1770239974,   // 2
  10.3008611535,  // 3
  10.3008611535,  // 4
  10.9133822323,  // 5
  11.5623257097,  // 6
  12.2498573744,  // 7
  12.9782717994,  // 8
  13.7500000000,  // 9
  14.5676175474,  // 10
  15.4338531643,  // 11
  16.3515978313,  // 12
  17.3239144361,  // 13
  18.3540479948,  // 14
  19.4454364826,  // 15
  20.6017223071,  // 16
  21.8267644646,  // 17
  23.1246514195,  // 18
  24.4997147489,  // 19
  25.9565435987,  // 20
  27.5000000000,  // 21
  29.1352350949,  // 22
  30.8677063285,  // 23
  32.7031956626,  // 24
  34.6478288721,  // 25
  36.7080959897,  // 26
  38.8908729653,  // 27
  41.2034446141,  // 28
  43.6535289291,  // 29
  46.2493028390,  // 30
  48.9994294977,  // 31
  51.9130871975,  // 32
  55.0000000000,  // 33
  58.2704701898,  // 34
  61.7354126570,  // 35
  65.4063913251,  // 36
  69.2956577442,  // 37
  73.4161919794,  // 38
  77.7817459305,  // 39
  82.4068892282,  // 40
  87.3070578583,  // 41
  92.4986056779,  // 42
  97.9988589954,  // 43
  103.8261743950,  // 44
  110.0000000000,  // 45
  116.5409403795,  // 46
  123.4708253140,  // 47
  130.8127826503,  // 48
  138.5913154884,  // 49
  146.8323839587,  // 50
  155.5634918610,  // 51
  164.8137784564,  // 52
  174.6141157165,  // 53
  184.9972113558,  // 54
  195.9977179909,  // 55
  207.6523487900,  // 56
  220.0000000000,  // 57
  233.0818807590,  // 58
  246.9416506281,  // 59
  261.6255653006,  // 60
  277.1826309769,  // 61
  293.6647679174,  // 62
  311.1269837221,  // 63
  329.6275569129,  // 64
  349.2282314330,  // 65
  369.9944227116,  // 66
  391.9954359817,  // 67
  415.3046975799,  // 68
  440.0000000000,  // 69
  466.1637615181,  // 70
  493.8833012561,  // 71
  523.2511306012,  // 72
  554.3652619537,  // 73
  587.3295358348,  // 74
  622.2539674442,  // 75
  659.2551138257,  // 76
  698.4564628660,  // 77
  739.9888454233,  // 78
  783.9908719635,  // 79
  830.6093951599,  // 80
  880.0000000000,  // 81
  932.3275230362,  // 82
  987.7666025122,  // 83
  1046.5022612024, // 84
  1108.7305239075, // 85
  1174.6590716696, // 86
  1244.5079348883, // 87
  1318.5102276515, // 88
  1396.9129257320, // 89
  1479.9776908465, // 90
  1567.9817439270, // 91
  1661.2187903198, // 92
  1760.0000000000, // 93
  1864.6550460724, // 94
  1975.5332050245, // 95
  2093.0045224048, // 96
  2217.4610478150, // 97
  2349.3181433393, // 98
  2489.0158697766, // 99
  2637.0204553030, // 100
  2793.8258514640, // 101
  2959.9553816931, // 102
  3135.9634878540, // 103
  3322.4375806396, // 104
  3520.0000000000, // 105
  3729.3100921447, // 106
  3951.0664100490, // 107
  4186.0090448096, // 108
  4434.9220956300, // 109
  4698.6362866785, // 110
  4978.0317395533, // 111
  5274.0409106059, // 112
  5587.6517029281, // 113
  5919.9107633862, // 114
  5919.9107633862, // 115
  6644.8751612791, // 116
  7040.0000000000, // 117
  7458.6201842894, // 118
  7902.1328200980, // 119
  8372.0180896192, // 120
  8869.8441912599, // 121
  9397.2725733570, // 122
  9956.0634791066, // 123
  10548.0818212118, // 124
  11175.3034058561, // 125
  11839.8215267723, // 126
  12543.8539514160 // 127
};

Finally, OnNoteOn and OnNoteOff don’t seem to be attached to any definition and I believe that it is also part of the usbMIDI firmware. Is there a syntactically graceful way to replace that with the if, then statements from the void(OnNoteOn) piece from before the setup?

Thank YOU!

The Thread stepper motor basics may have some useful stuff.
Sorry I know nothing about music.

...R

woops correction-

the firmware is called usbSerial, not usbMIDI.

or whatever this is-

https://www.pjrc.com/teensy/td_midi.html

I agree with Mark T - it's pretty much a data translation you're dealing with - with the arduino sitting in the middle doing that

Two hardware tasks into and out of the arduino:

~ The electronic connection between a MIDI cable and arduino - current driven logic using optoisolators if I recall
~ The electronic connection between a stepper and arduino - see Robins post

One translation task inside the arduino:

Turning the MIDI info into a variable - you'll need to look up the protocol for sifting/addressing/translating the MIDI note or mod wheel serial data into into a number - then simply send that 'number' using whatever your stepper driver needs.

It'll no doubt have things to think about in terms of optimising your resolution/bit depth for best results. I reckon although it is another task to add to the list, interfacing and LCD or connection to a serial monitor from the arduino will be very helpful (for this and other projects) - you'll be able to see the data inside the arduino.

ooohhh,

You want to use the frequency of the steppers to make tones ... I see, so it's more velocity oriented than position.

heh heh - I guess same problem applies, but you'll just have to fiddle with the stepper frequencies until they're tuned.

Resolution/bit-depth might be critical here

exactly. but i guess what i’m wondering is what the next thing to learn is-
what is the syntax for applying the data in the .h file to the MIDI.read command? at this point, i think i have the right commands to make the stepper go at a certain speed. i just don’t know how to connect each note to the speed in the .h file.

I hate reverse engineering code - often find that if it doesn't make sense, it's because there is an error - lot's of wasted time

So, I'll just ask what does MIDI.read give you? i.e. what does it return?

The key played in some form? An int that maps 144 keys ?

If so, I'd suggest that the numbers in float_notes.h are the translation from 'key' to stepper frequency.

You'll not that the fraction between '0' and '12' is 2 ... i.e. 12 notes per octave ...

If so, it's very likely something along the lines of:

stepperFrequency = float notes[MIDI.read];

then use 'steperFrequency' to send the command to whatever you're using to drive the stepper...

aaaaand - if MIDI.read just gives you the raw MIDI data, you'll need to look up the protocol in the MIDI spec (been around since before the internet).

General approach will be to filter out the note information from the packets - i.e. some kind of conditional check on maybe the first byte (whatever the protocol is...) - then know how to extract the actual note from the rest of the packet - might be very simple, as in the bytes are simply the numbers themselves, or maybe the data is efficient (or inefficient :roll_eyes:) and spread over multiple bytes and you'll have to use bitwise operations. Maybe MIDI.read is half way there, it does some of the above, but you still need to tell it, what you're interested in...

BUT, you're going to have to do some of the work :smiley:

Bitwise operations although pretty simple are perhaps a little heavy going to learn if you're new to this - do you understand binary, does 'MSB' mean anything to you?

No worries though, we're here to help :slight_smile:

If the stepper driver you are using has step and direction inputs, you can simply drive step with the tone library.

If someone still needs information on that, i used midi callbacks for controling steppers with midi cc.

As someone already said, you will need a midi interface with an optocoupler.

Hello !

how do I get I'm on a project that needs contrlar stepper motor with midi
can you help me ?

levino:
Hello !

how do I get I'm on a project that needs contrlar stepper motor with midi
can you help me ?

No.
Start your own thread. Do not hijack this one.

when I try to send the first midi message, the MOTOR 1 start to move slowly in one direction and never stops.

Have you tried sending a note off message, that is the same as note on but with a zero velocity?

Grumpy_Mike:
Have you tried sending a note off message, that is the same as note on but with a zero velocity?

Hello Mike, no I didn't but I will... although it's about a continuous controller message, not a note message.

Are you not trying to get a note out of the noise that a motor gives?
If you are sending CC messages then send one with a value of zero.