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-
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
) 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 ![]()
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 ![]()
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.