I am sure that the code can be optimised quite a bit further.
This post is in response to a number of comments by an anonymous user in regards to an earlier example of using the Arduino to output continuous controller MIDI data (see here).
In this example, eight pots and eight switches are read and sent as various MIDI controller numbers.
Schematic
This circuit uses a 4051 to multiplex the pots and a 4021 to shift in the switch states.
Notes:
- The value of R17 should be 220Ω
- The value of R1 - R8 should be somewhere between 4kΩ and 20kΩ. I have used 20kΩ 0.25W 5% resistors in the photo examples.
- Jumpers JP1 represent Arduino digital pins 11, 10 and 12
- Jumpers JP2 represent Arduino digital pins 4, 3 and 2
- Jumpers JP3 represent Arduino 5V and TX pins (see here for an example of connecting the Arduino to a MIDI connection).
- Jumpers JP5 represent the MIDI connection (see here for an example of connecting the Arduino to a MIDI connection)
- Jumper JP4 represents Arduino analog input pin 0
The 8 x SPST DIP switch and the 4021.
Arduino Code
The sketch will only send data for a given pot / switch if that controllers state has changed since the last loop. This saves any unnecessary MIDI data from being sent.
Important Variables:
The sketch will only send data for a given pot / switch if that controllers state has changed since the last loop. This saves any unnecessary MIDI data from being sent.
Important Variables:
- status_byte (default: 176)
This sets the fact that it is controller data that is being sent. Values from 176 to 191 sets the channel from 1 to 16. Each control shares the same status byte (and therefore is sent using the same channel). - cc_on_byte (default: 127)
This sets the value of a switch when that switch is high / pressed. This value is the same for all eight switches. - cc_off_byte (default: 0)
This sets the value of a switch when that switch is low / depressed. This value is the same for all eight switches. - ana_cc[] (default: {20, 21, 22, 23, 24, 25, 26, 27})
This array sets the controller numbers for the pots 1 to 8 - dig_cc[] (default: {28, 29, 30, 31, 32, 33, 34, 35})
This array sets the controller numbers for the switches 1 to 8
/*
Digital and Analog Data to MIDI Output
by Sebastian Tomczak
*/
byte status_byte = 176;
// control change on channel 1
byte cc_on_byte = 127;
// data to send if button is pressed
byte cc_off_byte = 0;
// data to send if button is depressed
byte ana_cc[] = {
20, 21, 22, 23, 24, 25, 26, 27}
; // set controller numbers for the pots
byte dig_cc[] = {
28, 29, 30, 31, 32, 33, 34, 35}
; // set controller numbers for the switches
byte data_ana_cc[] = {
255, 255, 255, 255, 255, 255, 255, 255}
;
byte data_dig_cc[] = {
0, 0, 0, 0, 0, 0, 0, 0}
;
byte data = 0;
int latchPin = 10; // set the latch pin
int clockPin = 11; // set the clock pin
int dataPin = 12;// set the data in pin
byte digital_data = 0;
int state = 0;
void setup() {
Serial.begin(31250);
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(latchPin,OUTPUT);
pinMode(clockPin,OUTPUT);
pinMode(dataPin,INPUT);
digitalWrite(latchPin,HIGH);
digitalWrite(clockPin,HIGH);
}
void loop() {
delayMicroseconds(20);
digitalWrite(latchPin,0);
byte myDataIn = 0;
for (int j=7; j>=0; j--)
{
digitalWrite(clockPin, 0);
delayMicroseconds(20);
state = digitalRead(dataPin);
if (state) {
if(data_dig_cc[j] != 1) {
Serial.print(status_byte);
Serial.print(dig_cc[j]);
Serial.print(cc_on_byte);
data_dig_cc[j] = 1;
}
}
else {
if(data_dig_cc[j] != 0) {
Serial.print(status_byte);
Serial.print(dig_cc[j]);
Serial.print(cc_off_byte);
data_dig_cc[j] = 0;
}
}
digitalWrite(clockPin, 1);
}
digitalWrite(latchPin, 1);
for(byte i = 0; i <= 7; i++) { PORTD = i * 4; data = analogRead(0) >> 3;
if(data_ana_cc[i] != data) {
Serial.print(status_byte);
Serial.print(ana_cc[i]);
Serial.print(data);
data_ana_cc[i] = data;
}
}
}
13 comments:
Anonymous would like to thank you...:)
thanks seb, great stuff.
Hopefuly I'll find some time tomorrow to test it on my circuit. thanks again
yeah okay good luck... let me know how it all goes!
who is this by the way???
Anonymous user, i have updated the code a little. It allows for more functions to be set initially for each controller...
http://little-scale.blogspot.com/2007/11/more-pots-and-switches-to-midi-data.html
hi seb, your example seems to work ok in my circuit.
However, my 4021 is faulty so I had to modify your code in order to use 3 digital pins as inputs (for 3 switches).
just a couple of questions though:
i) workPort = (i / 2) * 4;
PORTD = workPort;
I'm not sure I understand what these 2 lines do
ii) byte data_send = 0; // stores outgoing byte for spi bus
is this referred to the communocation between the atmeg and the multiplexers?
Finally, I noticed that this example sends MIDI data
continuously, even when I don't rotate any pot or press any switch. Is this normal?
thanks for your help.
Hey Warpie,
Can't seem to find either of the lines you are talking about in the code in this example.
Could you point out where abouts they are? Are you using this code from *this* post?
Also... in regards to sending MIDI data all of the time... see the newer version at:
http://little-scale.blogspot.com/2007/11/more-pots-and-switches-to-midi-data.html
byte data_send looks like it is a hangover from an SPI protocol i might have been working on.
workPort = i ...
looks like it might have something to do with the multiplexers but not in this context... hmmm... strange...
regards,
sebastian tomczak
ehh sorry seb,
these 2 lines are in your original MIDI out example. The one with the 2 4051s.
warpie
ahh, thought so.
Is there any difference in the sketch if I put a 4051 and 8 SPDT where is the 4021
Thanks for posting this, i'd be a little lost without it.
I have one question though-
I have one 10k pot wired to a 4051 and it only partially works- it will turn a virtual midi knob half way and that's it. Also, the arduino is sending non-stop random midi messages that can't be stopped.
do i need more than one pot wired to test it or should it work with just one pot?
Any ideas?
Hi, I'm a beginner in electronics and I have built this project. On Arduino I get this error message:
sketch_sep04c:0: error: expected constructor, destructor, or type conversion before '&&' token
sketch_sep04c.cpp: In function 'void loop()':
sketch_sep04c:68: error: 'status_byte' was not declared in this scope
sketch_sep04c:76: error: 'status_byte' was not declared in this scope
sketch_sep04c:88: error: 'status_byte' was not declared in this scope
(I have replaced the switch with buttons...)
Besides, in the monitor view's baudrate menu 31250 does not show.
Is there anybody out there to help?
Sorry but now it's compiled the error is:
Binary sketch size: 3 164 bytes (of a 14 336 byte maximum)
avrdude: stk500_getsync(): not in sync: resp=0x44
What does it mean?
I hope someone can help. Thanks.
I too am having issues with some pots only working partially, and sometimes, I get the constant random sending of all sorts of messages?
One of my thoughts is that it needs a sort of denounce, but not sure if it can simply be done with a pull-down resistor to ground and if so whats a good size resistor, or can it be done in the code? I think Id rather add a resistor it would seem to be more stable, not sure where to start on the ohm-age though.
I used
if( cc >= ( lastAnalogValue[i] + 2 ) || cc <= ( lastAnalogValue[i] - 2 ) )
for the input change check.
It effectively halves the resolution of the pots but solved the random number issues I was getting. Obviously not great for applications where exact values are required but otherwise works well.
Post a Comment