Arduino MIDI Controller
Arduino MIDI Controller
Controlador MIDI basado en Arduino UNO. MIDI controller based on Arduino UNO.
sbado, 8 de marzo de 2014
https://bugs.launchpad.net/kicad/+bug/872315
Salud.
Publicado por Pulse en 11:29 No hay comentarios:
Enviar por correo electrnicoEscribe un blogCompartir con TwitterCompartir con FacebookCompartir en Pinterest
MIDI: http://playground.arduino.cc/Main/MIDILibrary
U8glib: http://code.google.com/p/u8glib/
M2tklib: http://code.google.com/p/m2tklib/ ( no es imprescindible, pero si alguien se anima a modificar cosas, esta es sin
duda una herramienta de gran ayuda )
El cdigo lo hice en diferentes archivos, teneis el principal y a continuacin los ".h" que componen el total del cdigo.
Podeis aadir con el IDE que viene por defecto en Arduino los archivos .h tal y como se indica aqui:
http://arduino.cc/es/Guide/Environment
To compile the code I must first state that I use the following libraries:
MIDI: http://playground.arduino.cc/Main/MIDILibrary
U8glib: http://code.google.com/p/u8glib/
M2tklib: http://code.google.com/p/m2tklib/ (not required, but if anyone is encouraged to changethings, this is definitely
a useful tool)
I did the code in different files, you have the main and then. "H" that make up the total code. .IDE you can add to
the default one h files in Arduino as shown here:
http://arduino.cc/es/Guide/Environment
// http://en.wikipedia.org/wiki/The_C_Programming_Language
#include
#include "avr/pgmspace.h"
#include "potenciometros_y_display.h"
#include "CC_defs.h"
#include "constants.h"
#include "U8glib.h"
ControlStatus current_status;
//#define DEBUG_MENU
//#define DEBUG_KNOBS
//#define DEBUG_MIDI
//#define ENCODER
//#define ENCODER_PRIMER_PASO
//#define ENCODER_SEGUNDO_PASO
//#define BOTON_PULSADO
//#define SALIDA
void loop()
{
static unsigned int clock = 0;
const unsigned int period = 100;
input_update(¤t_status);
}
}
//------------- EMPIEZAN LAS FUNCIONES-------------------------------------------
#ifdef ENCODER
char btmp[127];
sprintf(btmp, "cs->encoder.encoder_target %i", cs->encoder.encoder_target);
Serial.println(btmp);//zz
#endif
/*
int update_from_encoder(ControlStatus *cs, int enc_pos, int x);
ejemplo:
*/
#ifdef ENCODER_PRIMER_PASO
char btmp[127];
char btmp1[127];
char btmp2[127];
sprintf(btmp, "cs->encoder.positions[cs->encoder.encoder_target]: %i", cs-
>encoder.positions[cs->encoder.encoder_target]);
sprintf(btmp1, "update_from_encoder(cs, cs->encoder.positions[cs-
>encoder.encoder_target], NUM_MENUS): %i", update_from_encoder(cs, cs-
>encoder.positions[cs->encoder.encoder_target], NUM_MENUS));
sprintf(btmp2, "Valor de cs->encoder.encoder_target: %i", cs->encoder.encoder_target );
Serial.println(btmp1);//zz
Serial.println(btmp);
Serial.println(btmp2);
Serial.println("\n");
,
#endif
if (update_from_button(¤t_status) == BUTTON_PRESSED)
{
switch (cs->encoder.positions[MenuEncoderNdx]
{
case ME_KnobGroup:
cs->encoder.encoder_target = KnobGroupEncoderNdx;
break;
case ME_Knob:
cs->encoder.encoder_target = KnobEncoderNdx;
break;
case ME_ControlChange:
cs->encoder.encoder_target = ControlChangeEncoderNdx;
break;
case ME_MidiChannel:
cs->encoder.encoder_target = MidiChannelNdx;
break;
case ME_Behavior:
cs->encoder.encoder_target = BehaviorNdx;
break;
}
#ifdef ENCODER_SEGUNDO_PASO
char btmp[127];
char btmp1[127];
char btmp2[127];
sprintf(btmp, "cs->encoder.positions[cs->encoder.encoder_target]: %i", cs-
>encoder.positions[cs->encoder.encoder_target]);
sprintf(btmp1, "update_from_encoder(cs, cs->encoder.positions[cs-
>encoder.encoder_target], NUM_MENUS): %i", update_from_encoder(cs, cs-
>encoder.positions[cs->encoder.encoder_target], NUM_MENUS));
sprintf(btmp2, "Valor de cs->encoder.encoder_target: %i", cs->encoder.encoder_target );
Serial.println(btmp1);//zz
Serial.println(btmp);
Serial.println(btmp2);
Serial.println("\n");
#endif
}
update_encoder_targets(cs);
break;
// Serial.println("Knob group");
cs->encoder.positions[cs->encoder.encoder_target] =
update_from_encoder(¤t_status, cs->encoder.positions[cs->encoder.encoder_target],
NUM_KNOB_GROUPS);
#ifdef DEBUG_MENU
sprintf(btmp, "KnobGroupEncoderNdx: %i", cs->encoder.positions[cs-
>encoder.encoder_target]);
Serial.println(btmp);//zz
#endif
// Serial.println("Knob");
cs->encoder.positions[cs->encoder.encoder_target] =
update_from_encoder(¤t_status, cs->encoder.positions[cs->encoder.encoder_target],
NUM_KNOBS);
#ifdef DEBUG_MENU
sprintf(btmp, "KnobEncoderNdx: %i", cs->encoder.positions[cs->encoder.encoder_target]);
Serial.println(btmp);//zz
#endif
// Serial.println("Canal Midi");
cs->encoder.positions[cs->encoder.encoder_target] =
update_from_encoder(¤t_status, cs->encoder.positions[cs->encoder.encoder_target],
NUM_MIDI);
#ifdef DEBUG_MENU
sprintf(btmp, "MidiChannelNdx: %i", cs->encoder.positions[cs->encoder.encoder_target]);
Serial.println(btmp);//zz
#endif
if (update_from_button(¤t_status) == BUTTON_RELEASED)
{
// Assign midi channel
int group = cs->encoder.positions[KnobGroupEncoderNdx];
int knob = cs->encoder.positions[KnobEncoderNdx];
cs->knobs[group].channel[knob] = cs->encoder.positions[cs->encoder.encoder_target];
// Return to menu:
cs->encoder.encoder_target = MenuEncoderNdx;
}
break;
cs->encoder.positions[cs->encoder.encoder_target] =
update_from_encoder(¤t_status, cs->encoder.positions[cs->encoder.encoder_target],
NUM_CONTROL_CHANGE);
#ifdef DEBUG_MENU
sprintf(btmp, "ControlChangeEncoderNdx: %i", cs->encoder.positions[cs-
>encoder.encoder_target]);
Serial.println(btmp);//zz
#endif
if (update_from_button(¤t_status) == BUTTON_RELEASED) // pressed
{
// Assign control change:
int group = cs->encoder.positions[KnobGroupEncoderNdx];
int knob = cs->encoder.positions[KnobEncoderNdx];
cs->knobs[group].control_change[knob] = cs->encoder.positions[cs-
>encoder.encoder_target];
// Return to menu:
cs->encoder.encoder_target = MenuEncoderNdx;
}
break;
#ifdef DEBUG_MENU
sprintf(btmp, "BehaviorNdx: %i", cs->encoder.positions[cs->encoder.encoder_target]);
Serial.println(btmp);//zz
#endif
}//switch
lcd_draw_header();
// Dynamic data:
lcd_draw_menu(cs);
lcd_draw_knob(cs);
input_update(cs);
}
while (u8g.nextPage());
}
int update_from_button(ControlStatus * cs)
{
// read the pushbutton input pin:
int salida = BUTTON_IDLE; // Initialize, always
if (cs)
{
cs->button.buttonState = digitalRead(PIN_Button); // PIN_Button = 2;
#ifdef BOTON_PULSADO
Serial.println("on");
Serial.print("number of button pushes: ");
Serial.println(cs->button.buttonPushCounter);
#endif
salida = BUTTON_PRESSED;
}
else
{
// if the current state is LOW then the button
// wend from on to off:
#ifdef DEBUG_MENU
Serial.println("off");
#endif
salida = BUTTON_RELEASED;
}
}
// save the current state as the last state,
// for next time through the loop
cs->button.lastButtonState = cs->button.buttonState;
#ifdef SALIDA
Serial.print(salida == BUTTON_PRESSED? "BUTTON_PRESSED" : salida == BUTTON_RELEASED?
"BUTTON_RELEASED" : "" );
#endif
return salida;
}
enc_pos--;
// lcd.clear();
}
else
{
#ifdef DEBUG_MENU
Serial.println("+");//zz!
#endif
enc_pos++;
// lcd.clear();
}
}
cs->encoder.ultimaPosicionPinA = lecturaPin;
if (enc_pos < 0)
{
#ifdef DEBUG_MENU
Serial.println("- [0]");//zz!
#endif
enc_pos = 0;
}
if (enc_pos > x)
{
enc_pos = x;
}
}
return enc_pos;
}
char btmp[32];
sprintf(btmp, "knob[%i, %i]: %i",
knob_group, i, knob_current_value);
Serial.println(btmp);//zz!
#endif
}
}
}
u8g.setFont(u8g_font_micro);
// Knob %
u8g.drawStr(1 + 20 * i + 6, 64 - value, strcpy_P(buzzer, (char
*)pgm_read_word(&(strin_table[pct])))); // sample
}
}
void lcd_draw_header()
{
u8g.drawFrame(79, 0, 49, 64); // X, Y ; ancho , alto Recuadro grupo
u8g.drawLine(0, 30, 79, 30); // linea entre el texto y los potes
u8g.drawLine(0, 37, 79, 37); // "" ""
u8g.drawLine(79, 24, 128, 24); // linea separadora grupo y auto
}
//u8g.setFont(u8g_font_6x10);
u8g.drawStr( 80, 15,"d" );
}
// Draw cursor:
u8g.drawStr(1, 5 + (menu_pos * font_height), ">");
// Draw value:
//const int text_offset = (strlen(menu_labels[i]) ) * font_width;
}
}
}
cs->encoder.encoder_target = 0;
cs->encoder.ultimaPosicionPinA = LOW;
for ( int i = 0; i < NUM_KNOB_GROUPS; i++ )
{
for ( int j = 0; j < NUM_KNOBS; j++ )
{
cs->knobs[i].knob[j] = 0;
cs->knobs[i].behavior[j] = 0;
cs->knobs[i].control_change[j] = 0;
cs->knobs[i].channel[j] = 0;
}
}
for ( int i = 0; i < NUM_MIDI; i++ )
{
cs->midi_status[i].cc = 0;
cs->midi_status[i].knob_value = 0;
}
}
------------------------------------------------------------------ CC_defs.h
// Changelog:
// 20120813: cleanup
// 2012????.Albert: implementation
#ifndef CC_defs_h
#define CC_defs_h
char buffer[16];
prog_char string_0[] PROGMEM = "00-BankSelMSB"; // "String 0" etc are strings to store -
change to suit.
prog_char string_1[] PROGMEM = "01-Mod Wheel";
prog_char string_2[] PROGMEM = "02-Breath Cntrl";
prog_char string_3[] PROGMEM = "03-CC 03";
prog_char string_4[] PROGMEM = "04-Foot Cntrl";
prog_char string_5[] PROGMEM = "05-Porta Time";
prog_char string_6[] PROGMEM = "06-Data Entry"; // "String 0" etc are strings to store -
change to suit.
prog_char string_7[] PROGMEM = "07-Volume";
prog_char string_8[] PROGMEM = "08-Balance";
prog_char string_9[] PROGMEM = "09-CC 09";
prog_char string_10[] PROGMEM = "10-Pan";
prog_char string_11[] PROGMEM = "11-Expression ";
prog_char string_12[] PROGMEM = "12-fx Cntrl 1";
prog_char string_13[] PROGMEM = "13-fx Cntrl 2";
prog_char string_14[] PROGMEM = "14-CC 14";
prog_char string_15[] PROGMEM = "15-CC 15";
prog_char string_16[] PROGMEM = "16-GPCntrl1LSB1";
prog_char string_17[] PROGMEM = "17-GPCntrl1LSB2";
prog_char string_18[] PROGMEM = "18-GPCntrl1LSB3";
prog_char string_19[] PROGMEM = "19-GPCntrl1LSB3";
prog_char string_20[] PROGMEM = "20-CC 20";
prog_char string_21[] PROGMEM = "21-CC 21";
prog_char string_22[] PROGMEM = "22-CC 22";
prog_char string_23[] PROGMEM = "23-CC 23";
prog_char string_24[] PROGMEM = "24-CC 24";
prog_char string_25[] PROGMEM = "25-CC 25";
prog_char string_26[] PROGMEM = "26-CC 26";
prog_char string_27[] PROGMEM = "27-CC 27";
prog_char string_28[] PROGMEM = "28-CC 28";
prog_char string_29[] PROGMEM = "29-CC 29";
prog_char string_30[] PROGMEM = "30-CC 30";
prog_char string_31[] PROGMEM = "31-CC 31";
prog_char string_32[] PROGMEM = "32-BankSelLSB";
prog_char string_33[] PROGMEM = "33-Mod Wheel LSB";
prog_char string_34[] PROGMEM = "34-Breath Cntrl LSB";
prog_char string_35[] PROGMEM = "35-CC 35";
prog_char string_36[] PROGMEM = "36-Foot Cntrl LSB";
prog_char string_37[] PROGMEM = "37-Porta Time LSB";
prog_char string_38[] PROGMEM = "38-Data Entry LSB";
prog_char string_39[] PROGMEM = "39-Volume LSB";
prog_char string_40[] PROGMEM = "40-Balance LSB";
prog_char string_41[] PROGMEM = "41-CC 41";
prog_char string_42[] PROGMEM = "42-Pan LSB ";
prog_char string_43[] PROGMEM = "43-Expression LSB";
prog_char string_44[] PROGMEM = "44-fx 1 LSB ";
prog_char string_45[] PROGMEM = "45-fx 2 LSB";
prog_char string_46[] PROGMEM = "46-CC 46";
prog_char string_47[] PROGMEM = "47-CC 47";
prog_char string_48[] PROGMEM = "48-GPCntrl1LSB ";
prog_char string_49[] PROGMEM = "49-GPCntrl2LSB ";
prog_char string_50[] PROGMEM = "50-GPCntrl3LSB ";
prog_char string_51[] PROGMEM = "51-GPCntrl4LSB";
prog_char string_52[] PROGMEM = "52-CC 52";
prog_char string_53[] PROGMEM = "53-CC 53";
prog_char string_54[] PROGMEM = "54-CC 54";
prog_char string_55[] PROGMEM = "55-CC 55";
prog_char string_56[] PROGMEM = "56-CC 56";
prog_char string_57[] PROGMEM = "57-CC 57";
prog_char string_58[] PROGMEM = "58-CC 58";
prog_char string_59[] PROGMEM = "59-CC 59";
prog_char string_60[] PROGMEM = "60-CC 60";
prog_char string_61[] PROGMEM = "61-CC 61";
prog_char string_62[] PROGMEM = "62-CC 62";
prog_char string_63[] PROGMEM = "63-CC 63";
prog_char string_64[] PROGMEM = "64-Damper Pedal";
prog_char string_65[] PROGMEM = "65-Porta Pedal";
prog_char string_66[] PROGMEM = "66-Sostenuto";
prog_char string_67[] PROGMEM = "67-Soft Pedal";
prog_char string_68[] PROGMEM = "68-Legato Foot Sw";
prog_char string_69[] PROGMEM = "69-Hold-2";
prog_char string_70[] PROGMEM = "70-Sound Vari";
prog_char string_71[] PROGMEM = "71-Timbre/Harmonics";
prog_char string_72[] PROGMEM = "72-Realease Time";
prog_char string_73[] PROGMEM = "73-Attack Time";
prog_char string_74[] PROGMEM = "74-Brighness";
prog_char string_75[] PROGMEM = "75-Decay Time";
prog_char string_76[] PROGMEM = "76-Vib.Rate";
prog_char string_77[] PROGMEM = "77-Vib.Depth";
prog_char string_78[] PROGMEM = "78-Vib.Delay";
prog_char string_79[] PROGMEM = "79-Sound Ctrl10";
prog_char string_80[] PROGMEM = "80-GeneralPurp10 ";
prog_char string_81[] PROGMEM = "81-GeneralPurp6";
prog_char string_82[] PROGMEM = "82-GeneralPurp7";
prog_char string_83[] PROGMEM = "83-GeneralPurp8";
prog_char string_84[] PROGMEM = "84-PortaCntrl";
prog_char string_85[] PROGMEM = "85-CC 85";
prog_char string_86[] PROGMEM = "86-CC 86";
prog_char string_87[] PROGMEM = "87-CC 87";
prog_char string_88[] PROGMEM = "88-CC 88";
prog_char string_89[] PROGMEM = "89-CC 89";
prog_char string_90[] PROGMEM = "90-CC 90";
prog_char string_91[] PROGMEM = "91-Reverb Depth";
prog_char string_92[] PROGMEM = "92-Tremolo Depth";
prog_char string_93[] PROGMEM = "93-Chorus Depth";
prog_char string_94[] PROGMEM = "94-Detune Depth";
prog_char string_95[] PROGMEM = "95-Phaser Depth";
prog_char string_96[] PROGMEM = "96-Data Inc";
prog_char string_97[] PROGMEM = "97-Data Dec";
prog_char string_98[] PROGMEM = "98-NRPN LSB";
prog_char string_99[] PROGMEM = "99-NRPN-MSB";
prog_char string_100[] PROGMEM = "100-RPN LSB";
prog_char string_101[] PROGMEM = "101-RPN MSB";
prog_char string_102[] PROGMEM = "102-CC 102";
prog_char string_103[] PROGMEM = "103-CC 103";
prog_char string_104[] PROGMEM = "104-CC 104";
prog_char string_105[] PROGMEM = "105-CC 105";
prog_char string_106[] PROGMEM = "106-CC 106";
prog_char string_107[] PROGMEM = "107-CC 107";
prog_char string_108[] PROGMEM = "108-CC 108";
prog_char string_109[] PROGMEM = "109-CC 108";
prog_char string_110[] PROGMEM = "110-CC 110 ";
prog_char string_111[] PROGMEM = "111-CC 111";
prog_char string_112[] PROGMEM = "112-CC 112";
prog_char string_113[] PROGMEM = "113-CC 113";
prog_char string_114[] PROGMEM = "114-CC 114";
prog_char string_115[] PROGMEM = "115-CC 115";
prog_char string_116[] PROGMEM = "116-CC 116";
prog_char string_117[] PROGMEM = "117-CC 117";
prog_char string_118[] PROGMEM = "118-CC 118";
prog_char string_119[] PROGMEM = "119-CC 119";
prog_char string_120[] PROGMEM = "120-All Sound OFF";
prog_char string_121[] PROGMEM = "121-RST all Cntrl";
prog_char string_122[] PROGMEM = "122-Local Cntrl";
prog_char string_123[] PROGMEM = "123-All note Off";
prog_char string_124[] PROGMEM = "124-Omni Off";
prog_char string_125[] PROGMEM = "125-Omni On";
prog_char string_126[] PROGMEM = "126-Mono Mode On";
------------------------------------------------------------------ constants.h
// Changelog:
// 20120813: cleanup
// 2012????.Albert: implementation
#ifndef constants_h
#define constants_h
#include "Arduino.h"
char buzzer[16];
prog_char strin_0[] PROGMEM = "0"; // "String 0" etc are strings to store // change to
suit.
prog_char strin_1[] PROGMEM = "1";
prog_char strin_2[] PROGMEM = "2";
prog_char strin_3[] PROGMEM = "3";
prog_char strin_4[] PROGMEM = "4";
prog_char strin_5[] PROGMEM = "5";
prog_char strin_6[] PROGMEM = "6"; // "String 0" etc are strings to store - // change to
suit.
prog_char strin_7[] PROGMEM = "7";
prog_char strin_8[] PROGMEM = "8";
prog_char strin_9[] PROGMEM = "9";
prog_char strin_10[] PROGMEM = "10";
prog_char strin_11[] PROGMEM = "11";
prog_char strin_12[] PROGMEM = "12";
prog_char strin_13[] PROGMEM = "13";
prog_char strin_14[] PROGMEM = "14";
prog_char strin_15[] PROGMEM = "15";
prog_char strin_16[] PROGMEM = "16";
prog_char strin_17[] PROGMEM = "17";
prog_char strin_18[] PROGMEM = "18";
prog_char strin_19[] PROGMEM = "19";
prog_char strin_20[] PROGMEM = "20";
prog_char strin_21[] PROGMEM = "21";
prog_char strin_22[] PROGMEM = "22";
prog_char strin_23[] PROGMEM = "23";
prog_char strin_24[] PROGMEM = "24";
prog_char strin_25[] PROGMEM = "25";
prog_char strin_26[] PROGMEM = "26";
prog_char strin_27[] PROGMEM = "27";
prog_char strin_28[] PROGMEM = "28";
prog_char strin_29[] PROGMEM = "29";
prog_char strin_30[] PROGMEM = "30";
prog_char strin_31[] PROGMEM = "31";
prog_char strin_32[] PROGMEM = "32";
prog_char strin_33[] PROGMEM = "33";
prog_char strin_34[] PROGMEM = "34";
prog_char strin_35[] PROGMEM = "35";
prog_char strin_36[] PROGMEM = "36";
prog_char strin_37[] PROGMEM = "37";
prog_char strin_38[] PROGMEM = "38";
prog_char strin_39[] PROGMEM = "39";
prog_char strin_40[] PROGMEM = "40";
prog_char strin_41[] PROGMEM = "41";
prog_char strin_42[] PROGMEM = "42";
prog_char strin_43[] PROGMEM = "43";
prog_char strin_44[] PROGMEM = "44";
prog_char strin_45[] PROGMEM = "45";
prog_char strin_46[] PROGMEM = "46";
prog_char strin_47[] PROGMEM = "47";
prog_char strin_48[] PROGMEM = "48";
prog_char strin_49[] PROGMEM = "49";
prog_char strin_50[] PROGMEM = "50";
prog_char strin_51[] PROGMEM = "51";
prog_char strin_52[] PROGMEM = "52";
prog_char strin_53[] PROGMEM = "53";
prog_char strin_54[] PROGMEM = "54";
prog_char strin_55[] PROGMEM = "55";
prog_char strin_56[] PROGMEM = "56";
prog_char strin_57[] PROGMEM = "57";
prog_char strin_58[] PROGMEM = "58";
prog_char strin_59[] PROGMEM = "59";
prog_char strin_60[] PROGMEM = "60";
prog_char strin_61[] PROGMEM = "61";
prog_char strin_62[] PROGMEM = "62";
prog_char strin_63[] PROGMEM = "63";
prog_char strin_64[] PROGMEM = "64";
prog_char strin_65[] PROGMEM = "65";
prog_char strin_66[] PROGMEM = "66";
prog_char strin_67[] PROGMEM = "67";
prog_char strin_68[] PROGMEM = "68";
prog_char strin_69[] PROGMEM = "69";
prog_char strin_70[] PROGMEM = "70";
prog_char strin_71[] PROGMEM = "71";
prog_char strin_72[] PROGMEM = "72";
prog_char strin_73[] PROGMEM = "73";
prog_char strin_74[] PROGMEM = "74";
prog_char strin_75[] PROGMEM = "75";
prog_char strin_76[] PROGMEM = "76";
prog_char strin_77[] PROGMEM = "77";
prog_char strin_78[] PROGMEM = "78";
prog_char strin_79[] PROGMEM = "79";
prog_char strin_80[] PROGMEM = "80";
prog_char strin_81[] PROGMEM = "81";
prog_char strin_82[] PROGMEM = "82";
prog_char strin_83[] PROGMEM = "83";
prog_char strin_84[] PROGMEM = "84";
prog_char strin_85[] PROGMEM = "85";
prog_char strin_86[] PROGMEM = "86";
prog_char strin_87[] PROGMEM = "87";
prog_char strin_88[] PROGMEM = "88";
prog_char strin_89[] PROGMEM = "89";
prog_char strin_90[] PROGMEM = "90";
prog_char strin_91[] PROGMEM = "91";
prog_char strin_92[] PROGMEM = "92";
prog_char strin_93[] PROGMEM = "93";
prog_char strin_94[] PROGMEM = "94";
prog_char strin_95[] PROGMEM = "95";
prog_char strin_96[] PROGMEM = "96";
prog_char strin_97[] PROGMEM = "97";
prog_char strin_98[] PROGMEM = "98";
prog_char strin_99[] PROGMEM = "99";
prog_char strin_100[] PROGMEM = "100";
};
------------------------------------------------------------- potenciometros_y_display.h
// Changelog:
// 20120813: cleanup
// 2012????.Albert: implementation
#ifndef potenciometros_y_display_h
#define NUM_KNOB_GROUPS 8
#define NUM_KNOBS 4 // 4 knobs * 4 knobs/bank = 16 total knobs
#define NUM_MENUS 4
#define NUM_MIDI 16
#define NUM_CONTROL_CHANGE 127
#define BUTTON_IDLE 0
#define BUTTON_RELEASED 1
#define BUTTON_PRESSED 2
/*
Version para Mega
const int PIN_Encoder0A = 30;
const int PIN_Encoder0B = 31;
const int PIN_Button = 22;
*/
// version para UNO
/*const int PIN_Encoder0A = 0;
const int PIN_Encoder0B = 2;
*/
enum EncoderIndexes
{
MenuEncoderNdx = 0,
KnobGroupEncoderNdx,
KnobEncoderNdx,
ControlChangeEncoderNdx,
MidiChannelNdx,
BehaviorNdx,
KnobEncoderElems
};
enum MenuElems
{
ME_KnobGroup = 0,
ME_Knob,
ME_ControlChange,
ME_MidiChannel,
ME_Behavior,
ME_Elems
};
// Data structures:
typedef struct
{
int knob[NUM_KNOBS];
int behavior[NUM_KNOBS];
int control_change[NUM_KNOBS];
int channel[NUM_KNOBS];
} KnobStatus;
typedef struct
{
int buttonPushCounter; // counter for the number of button presses
int buttonState; // current state of the button
int lastButtonState; // previous state of the button
} Button;
typedef struct
{
int encoder_target; // it will point to knob_ndx/control_change_ndx/menu_ndx.
int positions[KnobEncoderElems];
int ultimaPosicionPinA;
} Encoder;
typedef struct
{
int cc;
int knob_value;
} MIDI_STATUS;
typedef struct
{
KnobStatus knobs[NUM_KNOB_GROUPS];
Encoder encoder;
Button button;
MIDI_STATUS midi_status[NUM_MIDI];
} ControlStatus;
// Function prototypes:
// Macros:
#endif // potenciometros_y_display_h
Pido de antemano disculpas por cualquier error u omisin que afecte al cdigo, si tenis alguna duda respecto al cdigo
hacdmela saber.
Espero que disfrutis con vuestro nuevo controlador MIDI.
I ask in advance apologies for any errors or omissions affecting the code, if you have any questions
regarding hacdmela know code.
Material
Este es el listado de material de la ltima versin que tengo en marcha del controlador que sale en la foto.
Hubo una versin anterior con un display de 162 y otra versin posterior con un display de 164 caracteres, pero debido
a que se me quedaba corto decid implementar un display GLCD de 128X64 pxeles con la posibilidad de aadir grficos.
A continuacin describo los elementos que he utilizado en esta ltima (?) versin.
This is the list of material that I have latest version of the driver up in the photo.
There was an earlier version with a display of 16 2 and a later version with a display of 16 4 character, but because
I fell short I decided to implement a 128X64 GLCD display pixels with the ability to add graphics.
Below I describe the items that I have used in the last (?) Version.
Ncleo / Core :
Control:
Control:
Schematic where you can see the different modules MIDI IN, OUT and THRU comprising it and its components.
Conectores DIN 5 hembra (hay muchos modelos, yo escog el que NO era areo y podia soldarlo en la PCB).
5 female DIN connectors (there are many models, I chose the one that was NO air and I couldsolder on the PCB).
Opto-acoplador Sharp PC-900 o equivalente para el modulo MIDI IN.
Resistencias de 220 y 280 Ohms y diodo 1N914, tal y como se indica en el esquemtico.
Pcb con pistas y agujeros para trabajar con mas facilidad a la hora de soldar, evitando pegotes de estao y por ende
falsos contactos.
Resistors 220 and 280 Ohms and 1N914 diode, as indicated in the schematic.
Pcb with tracks and holes to work more easily when welding, avoiding globs of tin and thereforefalse contacts.
Cable rgido y las herramientas que corresponda.
Como elemento final, eleg reunir todos estos elementos en una pieza de metacrilato por varios motivos:
Elegante.
Relativamente fcil de manipular.
As a final element, I chose to bring all these elements in a piece of acrylic for several reasons:
Elegant.
Edit
Despus de muchas horas, pruebas y de casi no poder acabarlo, os presento mi primer controlador MIDI basado en
Arduino UNO.
After many hours of testing and almost unable to finish it, I present my first MIDI controller based on Arduino UNO.
Como funciona
How does it work?
Elegimos entre el P0, P1, P2, P3, ( los cuatro potenciometros reales ).
Chose between P0, P1, P2, P3, ( the four real potentiometers ).
Una vez elegidos, asignamos mediante el pulsador ( manteniendo pulsado ) y el encoder mecnico, uno de
los Control Change que aparece en el listado de Control Change que a continuacin aparece en el display .
Once selected, assigned by the button (holding down) and mechanical encoder, choose one of the Control
Change that appears in the display.
Habiendo asignado el nmero de canal al potenciometro, es decir que el canal MIDI no est en midi = 0. El
controlador empezar a enviar mensajes por la salida de MIDI OUT.
Having allocated channel number potentiometer, ie the MIDI channel is not in midi = 0. The controller will start
sending out messages for MIDI OUT.
Podis observar que el funcionamiento es muy sencillo. Este uno de los objetivos mas importantes que quera conseguir,
pues como msico electrnico y usuario de hardware me he encontrado con mquinas que no hacen lo que se supone
tienen que hacer, y este era el caso de mi controlador Evolution UC-33
You can see that the operation is very simple. This one of the most important goals I wanted to achieve, because as
electronic musician and hardware user I found machines that do not do what they are supposed to do, and this was the
case of my Evolution UC-33 controller.
No es que sea una mala mquina, pero es que ( yo creo ) que no es prctico tener 24 potenciometros, 8 deslizadores
adems de pulsadores y que la nica informacin que obtienes de su bonito display azul sea tan criptico como esto:
It's not a bad machine, but is that (I believe) it is not practical to have 24 potentiometers, 8 sliders and buttons as well as
the only information you get from her pretty blue display is as cryptic as this:
Obligndote de esta manera a introducir un elemento ms en tu "set-up"... la cinta de pintor para poder saber que has
asignado en cada potenciometros.
Thus forcing you to introduce another element in your "set-up" ... masking tape to know that you assigned in
each potentiometers.
.
.
.
Os imaginis hacer una actuacin y que perdis la cinta para anotar adonde asignasteis cada funcin?
Can you imagine doing a show and you miss the tape to record where each function was asigned ?
Knob: Potenciometro
Knob: Potentiometer
Los niveles indican la posicin absoluta del potenciometro, esto va muy bien para ver a simple vista doce tienes el
potenciometro.
The levels indicate the absolute position of the potentiometer, this is nice to see at a glance twelve have the
potentiometer.
El controlador se basa completamente en un Arduino UNO, utilizando todas las entradas menos el pin nmero 0 ( de
momento ) ya que en en breve quiero implementar un par de cosas ms, y entre ellas estr la capacidad de poder sumar
una seal MIDI externa ( MIDI Merge ) y tendr que utilizar el que me queda como entrada serie.
The controller is based on an Arduino UNO copmpletamente, using all entries but the pin number 0 (for now) and that
soon I want to implement a few more things, including stress and the ability to add external MIDI signal ( MIDI Merge) and
I have to use the one I have as input series.
El controlador solo maneja CC ( Control Change ), el motivo por el cual eleg esta particularidad antes de abordar tems
como el Program Change o el Play / Stop es que pueden emplearse para modificar cualquier parmetro y para mi E-MU
5000 me v de perlas, as que si el sintetizador que queremos gobernar permite manejar CC, no habr problemas para
comunicarse con l.
The controller only handles CC (Control Change), the reason why I chose this feature before boarding issues as Program
Change or the Play / Stop is that they can be used to modify any parameter of my E-MU 5000, so if the synthesizer you
want to handle CC rule, there will be no problem communicating with it.
Por otra parte al no ser una de las partes estandarizadas en el protocolo MIDI, copi uno a uno los 127 parmetros
que reconoca mi AKAI MPC 1000 con su sistema operativo actualizado al
JJOS2XL http://www7a.biglobe.ne.jp/~mpc1000/os2xl/ as que haciendo esto me aseguraba que los parmetros que
copiaba por lo menos estaban "actualizados" como mi AKAI.
On the other hand not being a party in the MIDI standard, I copied one by one the 127 parameters that recognized my
AKAI MPC 1000 with its updated operating system to JJOS2XL http://www7a.biglobe.ne.jp/ ~ MPC1000 / os2xl / so doing
that I made sure that the parameters were copied at least "updated" as my AKAI.
You can see that this show is not for the Arduino UNO board, but to make you a quick idea of how the wiring goes I think
it serves.
Por cierto el programa que hace estos graficos tan chulos se llama Fritzing y es Open Software.
Certainly the graphics program that makes these so cool is called Fritzing and Open Software.
Debo sealar que controlarlo por soft junto con el pulsador fue un infierno. Ya que al montarlo en la protoboard y con el
juego que a veces tienen los cables me daban falsas seales y me pas das en busca de la falla.
I should note that for soft control with the push was hell. Since when mounted on the breadboard and the game that
sometimes have the cables gave me false signs and I spent days looking for the fault.
Aqu os adjunto un vdeo ( calidad telfono mvil ) del funcionamiento de la primera versin del controlador conectado a
la MPC 1000.
Here I attached a video (mobile phone quality) performance of the first version of MPC 1000connected to the controller.
Sugerencias:
Suggestions:
A mi me ha servido y me sigue sirviendo de mucho este libro, encuentro que es una joya, y su autor es espectacular el
como explica las cosas.
Arduino Internals
Muy interesante.
Very interesting.
Programming And Customizing The AVR Microcontroller
Actualizacin:
http://www.mupuf.org/project/arduide.html
De una forma muy sencilla podis instalaros un IDE mucho ms completo con respecto a la informacin que ofrece,
rpido y agradable a la hora de compilar.
Primer paso:
Despus de la experiencia con el entorno de desarrollo que viene por defecto con el paquete de Arduino, he decidido
cambiar y aprovechar para aprender a utilizar Vim.
Ahora mismo tal y como lo estoy utilizando es probablemente una de las maneras menos eficientes de utilizarlo,
pero despus de un da entero de bsqueda, y con decenas de pruebas fallidas, doy por finalizada la "cacera" hasta otro
momento.
En primer lugar se trata de abrir el archivo que vayamos a editar/crear con el editor Vim.
Una vez hayamos abierto el archivo, el siguiente paso es abrir el IDE del Arduino y en las preferencias elegir "Usar editor
externo".
De esta manera al editar o crear el texto que nos convenga, y una vez hayamos hechas las correcciones pertinentes en
nuestro archivo, cuando salvemos el archivo debemos recordar que la extensin que utilizar el IDE de Arduino es .ino.
Ahora vamos al IDE de Arduino, abrimos el mismo archivo y podremos compilarlo y subirlo a nuestra placa siempre que
est bien.
Una de las pequeas ventajas que de cierta manera nos ofrece esta configuracin, es que una vez editemos el archivo y
lo guardemos al tener el modo "usar editor externo", el IDE de Arduino nos mostrar los cambios que hayamos
realizados en Vim o en el editor que hayamos elegido.
Tambin es cierto que estamos obligados a hacer un paso mas a la hora de trabajar, pero eso ya depende de cada cual.