Controlador MIDI por USB con PIC para Virtual Dj

Calculo que no, hay algunos que tienen mas polos en el estator... y depende de eso. Pero comparado con las 40 mas o menos de un mouse es diferencia ;)
MouseEncoder.jpg

Respecto a lo de las salidas no se que es, pero en la pc de escritorio me quedan a 0 y en la notebook a 1 :unsure::confused:
 
Bueno, nada más que pueda te hago el código, que es simple.
Bueno, te lo agradeceria... no tanto el codigo sino la explicacion. hay algo está fallando en mi código... aparte que al no usar interrupciónes hay que usar bits para indicar que el incremento o decremento ya se envió y no lo haga en cada comparación...
 
Gente estuve probando con un código que encontré que es el siguiente:
Código:
Interrupcion:                 '-------- Decodificador de Encoder --------------
       
    Context SAVE              ' Salva en contexto de los registros antes de operar con la
                              ' interrupción.
    
    If PORTB.0 = 1    Then    ' Si RB0 se ha puesto a 1 (flanco de subida),
       INTEDG  = 0            ' entonces activar la siguiente interrupción por flanco de
                              ' bajada.
       If PORTB.1 = 1 Then    ' Si RB1 está a 1,
          Inc x               ' entonces incrementar el contador X.
       EndIf
    Else                      ' Si RB0 se ha puesto a 0 (flanco de bajada),  
       INTEDG  = 1            ' entonces activar la siguiente interrupción por flanco de
                              ' subida.
       If PORTB.1 = 1 Then    ' Si RB1 está 1,
          Dec x               ' entonces decrementar el contador X.
       EndIf
    EndIf
     
    INTF = 0                  ' Borra el "flag" de la interrupción RB0/INT para poder permitir
                              ' la siguiente interrupción cuando ocurra. 
    Context Restore           ' Restablece el contexto de los registros tal como estaban antes
                              ' de la interrupción.
[LEFT]
Pero tengo un problema, si giro el encoder en un sentido todo bien, pero cuando lo giro en el otro a baja velocidad me indica el giro al revés del sentido real... alguien sabe por que puede ser? estará mal el código ese?
[/LEFT]
 
Ese código no termino de ver como puede funcionar, para mi que le faltan cosas. Además es con interrupciones también
Este es el que yo he hecho así rápidamente sin interrupciones:

Código:
x=0;
for(;;){	
	pos2=pos;

if(bit_test(PORTB,0)){
	if(bit_test(PORTB,1)) pos=3;
	else pos=2;
}
if(!(bit_test(PORTB,0))){
	if(bit_test(PORTB,1)) pos=4;
	else pos=1;
}
if (pos2!=pos){
	switch(pos){
		case 1: if(pos2==4) x++;
				else x--;
				break;
		case 2: if(pos2==1) x++;
				else x--;
				break;
		case 3: if(pos2==2) x++;
				else x--;
				break;
		case 4: if(pos2==3) x++;
				else x--;
				break;
}
}
}

A cada combinación de las entradas le doy un número, correspondiente a las 4 combinaciones posibles de los canales A y B. Al principio copio la posición anterior para luego comparar donde estaba. Leo la posición actual.
Si no ha cambiado, vuelo al principio.
Si ha cambiado compruebo si ha ido hacia adelante o hacia atrás, e incremento o decremento el contador.
No lo he probado, pero creo que puede funcionar. Se aceptan sugerencias, mejoras y todo lo demás.

Un saludo
 
Navegando por la red encontré un muy similar, que lo estaba posteando desde la pc de escritorio... venia bien con la explicación hasta que se me cortó la luz, y de ahi me dió bronca y me fui a hacer otra cosa :D
Es muy parecido al tuyo pero parece que toma dos pasos y no los cuatro posibles (11,10,01,00).
En un rato lo paso al proton, la idea ya está... se agradece el aporte compañero.
Este es el código:

viejo=actual
actual = ~PORTA & 3

If viejo= 2 And actual= 3 Then
USBBuffer[0]= %00000000
USBBuffer[1]= %00000001
GoSub DoUSBOut
USBBuffer[0]= %00000000
USBBuffer[1]= %00000000
GoSub DoUSBOut
EndIf

If viejo=3 And actual=2 Then
USBBuffer[0]= %00000000
USBBuffer[1]= %00000010
GoSub DoUSBOut
USBBuffer[0]= %00000000
USBBuffer[1]= %00000000
GoSub DoUSBOut
EndIf

Para que detecte todas las transiciones habria que hacer lo mismo para el resto de los cambios no? por ejemplo 3-2 2-1 1-0 0-3 y 0-1 1-2 2-3 3-0
 
Última edición:
Pero esa parte solo es la que detecta para que lado va y hace el envío USB, ¿no? Faltarían las otras detecciones para detectar todos las posibilidades, y antes de eso, hay que leer los pines del puerto para detectar los pulsos.
 
Exactamente, y ya lo tengo solucionado, ahora no me gusta porque es demasiado sensible jaja.
Cuando esté en la otra pc subo las cosas completas, el problema que me surgió es que como en el ejemplo detectaba la transición de 3 a 2 y de 2 a 3 yo dije bueno, el resto es 0-1 1-2 etc y no, no es asi.
Con un dibujo me di cuenta :D en un rato lo subo.
 
Ahora si está completo y detecta todas las transiciones... el problema era que debido a la forma de leer los pines los valores no eran 0 1 2 3... sino 0 2 3 1 debido a que el "peso" del bit A es 1 y el B es 2, de esto me di cuenta cuando vi la imagen que aparece acá http://sites.google.com/site/proyec...coder-por-software/encoder-simple-con-16f628a
Asi que bueno, ya está todo funcionando, jogwheels, leds, faders, potes, botones... yo la verdad no se si voy a armar una consola, era para decir yo puedo hacer esto por mi cuenta, barato, y con la satisfacción que deja saber que es algo que hizo uno mismo (y)
Código:
'****************************************************************
'*  Name    : Conexion usb                                      *
'*  Author  : FERNANDOAE                                        *
'****************************************************************
Config_Start
   PLLDIV = 1 ; No prescale (4 MHz oscillator input drives PLL directly)
   CPUDIV = OSC1_PLL2 ; [OSC1/OSC2 Src: /1][96 MHz PLL Src: /2]
   USBDIV = 2 ; USB clock source comes from the 96 MHz PLL divided by 2
   FOSC = XTPLL_XT ; XT oscillator, PLL enabled, XT used by USB
   PWRT = On ; PWRT enabled
   BOR = OFF ; Brown-out Reset disabled in hardware and software
   VREGEN = On ; USB voltage regulator enabled
   WDT = OFF ; HW Disabled - SW Controlled
   MCLRE = OFF ; RE3 input pin enabled; MCLR disabled
   PBADEN = OFF ; PORTB<4:0> pins are configured as digital I/O on Reset
   LVP = OFF ; Single-Supply ICSP disabled
   Debug = OFF ; Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
Config_End

'SELECCIONAMOS EL PIC Y LA FRECUENCIA DE TRABAJO (48Mhz PARA USB)
Device = 18F2550
Xtal = 48    
All_Digital= 1
'ESTA FILA LA GENERA EL MISMO "EASYHID USB WIZARD" Y LA COLOCA 
'JUNTO A ESTE ARCHIVO .BAS DONDE TRABAJAREMOS LA APLICACIÓN 
'(EN LA MISMA CARPETA)
USB_Descriptor = "DESCRIPTOR.inc"

'LOS TAMAÑOS DEL BUFFER USB
Symbol USBBufferSizeMax = 8
Symbol USBBufferSizeTX  = 8
Symbol USBBufferSizeRX  = 8
Dim    USBBuffer[USBBufferSizeMax] As Byte


                                                
'REGISTROS Y BANDERAS
Dim PP0 As Byte System        ' REGISTRO DENTRO DEL PIC USBPOLL STATUS
Symbol CARRY_FLAG = STATUS.0  ' EN ESTADO ALTO SI EL PIC NO TIENE 
                              ' EL CONTROL SOBRE EL BUFFER
Symbol ATTACHED_STATE = 6     ' SI USB ESTÁ CONECTADO

Clear                         'LIMPIO LA RAM AL INICIAR

 TRISA = %11111111         
 TRISB = %11111111

GoSub AttachToUSB             'ME VOY A VER SI ESTÀ CONECTADO
                              'AL INICIAR EL PROGRAMA

' *****************************************************************     
' *****************************************************************
' * LAZO PRINCIPAL DEL PROGRAMA MIENTRAS SE ESTÁ CONECTADO A USB; *
' * RECUERDA QUE DEBES MANTENER LA CONEXIÓN "VIVA" CON LLAMADOS   *
' * CONSTANTES A LAS RUTINAS USBPoll, USBIn or USBOut CADA ALGUNOS*
' * MILISEGUNDOS O MÁS                                            *
' *****************************************************************
' *****************************************************************
Dim x As Byte
Dim viejo As Byte
Dim actual As Byte

viejo=0
actual=0


INICIO:

viejo=actual
actual = ~PORTA & 3

If viejo= 0 And actual= 2 Then
GoSub incremento
EndIf
If viejo= 2 And actual= 3 Then
GoSub incremento
EndIf
If viejo= 3 And actual= 1 Then
GoSub incremento
EndIf
If viejo= 1 And actual= 0 Then
GoSub incremento
EndIf


If viejo= 1 And actual= 3 Then
GoSub decremento
EndIf
If viejo= 3 And actual= 2 Then
GoSub decremento
EndIf
If viejo= 2 And actual= 0 Then
GoSub decremento
EndIf
If viejo= 0 And actual= 1 Then
GoSub decremento
EndIf


USBIn 1, USBBuffer, USBBufferSizeRX,norecibi
norecibi:
GoTo INICIO                'CIERRO EL LAZO DESPUÉS DE TODO EL TRABAJO

' ************************************************************
' *               RUTINA DE RECEPCIÓN DE DATOS               *
' ************************************************************
DoUSBIn:
   USBIn 1, USBBuffer, USBBufferSizeRX, DoUSBIn
   Return
   
' ************************************************************
' *              RUTINA DE TRANSMISIÓN DE DATOS              *
' ************************************************************
DoUSBOut:   
   USBOut 1, USBBuffer, USBBufferSizeTX, DoUSBOut
   Return

' ************************************************************
' *           ESPERA HASTA QUE EL USB SE CONECTE             *
' ************************************************************
AttachToUSB:
   Repeat                                
   USBPoll        
   Until PP0 = ATTACHED_STATE
   Return
   
decremento:
USBBuffer[0]= %00000000
USBBuffer[1]= %00000010
GoSub DoUSBOut
USBBuffer[0]= %00000000
USBBuffer[1]= %00000000
GoSub DoUSBOut
Return

incremento:
USBBuffer[0]= %00000000
USBBuffer[1]= %00000001
GoSub DoUSBOut
USBBuffer[0]= %00000000
USBBuffer[1]= %00000000
GoSub DoUSBOut
Return

http://www.youtube.com/watch?v=6Tv9YiPQIRc&feature=youtu.be
 
Última edición:
¡Buen trabajo! Este lenguaje no lo entiendo muy bien, ¿cual es?
¿Me puedes decir que siginifica esta instrucción? :
Código:
actual = ~PORTA & 3

A mi me pasa como a tí, que no se si le daré uso a la consola, pero es un placer verlo funcionar, jejej

La mia definitivamente la voy a dejar en Midi, porque es compatible con mas software, y no me sigo comiendo la cabeza con los leds, que los dejo por imposible.

Un saludo.



Vale, ya entiendo la instrucción. He visto la web que has puesto y el código está claro en CCS. Es bastante sencillo, pero para los motores paso a paso del disco duro, mejor utilizar todas las transiciones para tener más sensibilidad, ¿no?

De todas formas, y no es por ser cabezón, prefiero utilizar interrupciones para no estar millones de ciclos esperando por algo que no llega, porque cuando no se mueve el jogwhell estás perdiendo tiempo en escanear unas entradas que no cambian.
 
Última edición:
¡Buen trabajo! Este lenguaje no lo entiendo muy bien, ¿cual es?
Es el de Proton, si no me equivoco se llama Proton Basic.

¿Me puedes decir que siginifica esta instrucción? : Código:
actual = ~PORTA & 3
"~" Es para invertir los bits del puerto A(porque el encoder en reposo me da 11), o sea, no cambia el valor del puerto... solamente toma el valor invertido. Calculo que en CCS seria algo como "not porta" :rolleyes:
"&" es el operador AND, se utiliza como máscara, para que solo considere los valores del bit 1 y el bit 2 del puerto, por eso va un 3 en este caso... asi ignora el resto, es como decirle "mirá solamente estos dos bits".

A mi me pasa como a tí, que no se si le daré uso a la consola, pero es un placer verlo funcionar, jejej
O también podés venderla :D

La mia definitivamente la voy a dejar en Midi, porque es compatible con mas software, y no me sigo comiendo la cabeza con los leds, que los dejo por imposible.
Pero si los leds los hice funcionar, fijate.

A mi me interesa el tema del midi, podrias explicar como se maneja el tema con ccs?

pero para los motores paso a paso del disco duro, mejor utilizar todas las transiciones para tener más sensibilidad, ¿no?
Si, es lo mejor. Queda con muy buena sensibilidad, incluso girandolo MUUUUY lento detecta todo. (y)

De todas formas, y no es por ser cabezón
:unsure: jaja

, prefiero utilizar interrupciones para no estar millones de ciclos esperando por algo que no llega, porque cuando no se mueve el jogwhell estás perdiendo tiempo en escanear unas entradas que no cambian.
Eso tambien quiero probar, de hacerlo con interrupciones. Perooo, y cuando tengo dos encoders y se mueven en simultaneo?:confused:



Ah rachelies, como es esto? que va en cada buffer?

buf[1] = 0x90; COMANDO
buf[0]=buf[1]>>4; Y ACA??? QUE SE HACE Y POR QUE? :D
buf[2] = 0x00; NOTA
buf[3] = 0; VELOCIDAD

Serias tan amable de explicarme como enviar CC y el resto de los comandos?
 
Última edición:
Hola.
Cuando tengas dos encoders y se muevan a la vez, en realidad no es simultaneo, porque es prácticamente imposible que el cambio de dos flancos sea exactamente en el mismo nanosegundo. Además y de esto no estoy cierto, si cuando estás en una interrupción ocurre otra, entra en la segunda al salir de la primera, pero ojo, de esto no estoy seguro. Pero de todas formas no te preocupes, que no van a llegar 2 flancos al mismo instante.

Lo del buffer midi:

buffer[0]=0x09 que significa note-on
buffer[1]=0x90 que no recuerdo porque, pero hay que invertir los nybbles

Despues la nota, y la velocidad.

Para enviar un note-on, con la nota 1, velocidad 127 (que es el máximo) tienes que enviar 09 90 01 7F

Un note-off sería:
08 80 01 00

Lo saqué todo del manual usb-midi que adjunto.

Para enviar los CC sería:

buf[0]=0x0B
buf[1]=0xB0
buf[2]=0x XX (cc que quieres manejar)
buf[3]=0x XX (el valor que quierer darle)

0B B0 01 00

Espero que más o menos lo vayas entendiendo.
Un saludo
 

Adjuntos

  • USB_MIDI.pdf
    175.8 KB · Visitas: 127
Hasta ahi va todo bien, voy entendiendo :) para los potes se usa CC y para los botones las notas no? o es lo mismo?
Tenés algun ejemplo básico sobre como configurar los adc en el 18F2250 y enviarlos por midi?
 
Al principio del todo ponemos esto, para decirle la resolucion del ADC. 8 bits para el pitch será suficiente.
Código:
#device ADC=8
Además, en el midi solo se podrá enviar hasta el 127, así que habrá que convertir el valor leido antes de enviarlo.
Lo siguiente lo metemos ya dentro del main()
Código:
setup_adc_ports(AN0_TO_AN1);
setup_adc(ADC_CLOCK_INTERNAL);

Con esto decimos que AN0 y AN1 sean analógicos, y seleccionamos el reloj interno del adc, que para esto será suficiente.
Y por último, leemos por ejemplo el canal 0, lo convertimos al rango que envía el Midi, comprobamos si ha cambiado desde la última lectura, y si ha cambiado, lo enviamos por USB.

Código:
set_adc_channel(0);
delay_us(30);
tempoA1=read_adc();
tempoA11=tempoA1/2;	//convierte del rango 0xFF a 0x7F para Midi

//comprueba si ha cambiado el pitch para enviarlo			
if(tempoA11!=tempoA2)
	{	tempA[1]=0xB0;
		tempA[0]=tempA[1]>>4;
		tempA[2]=0x00;
		tempA[3]=tempoA11;
		usb_put_packet(1,tempA,4,USB_DTS_TOGGLE);
		tempoA2=tempoA11;
}

El byte 0 y 1 son el comando CC, el byte 2 el nº de comando y el tercer byte, el valor del potenciometro.
Espero haberte ayudado. Un saludo
 
Fernandoae, el código que pusistes en Proton IDE no está completo, sólo pusistes la interrupción.

El código completo para un 16F876 y que funciona mediante interrupción por RB0/INT es este:

Código:
Device=16F876A

REMINDERS = FALSE
     Config XT_OSC, PWRTE_ON, CPD_OFF, WDT_OFF, BODEN_OFF, LVP_OFF
REMINDERS = TRUE

Symbol INTF   = INTCON.1         ' RB0 External Interrupt Flag
Symbol INTE   = INTCON.4         ' RB0 External Interrupt Enable
Symbol GIE    = INTCON.7         ' Global Interrupt Enable
Symbol INTEDG = OPTION_REG.6     ' Flag = 0 Flanco bajada. Flag = 1 Flanco subida.

On_INTERRUPT GoTo Interrupcion   ' Interrupción por hardware (es la más rápida).

GIE    = 1                       ' Activa interrupciones generales.
INTE   = 1                       ' Activa la interrupción externa RB0/INT.
INTEDG = 1                       ' Hace que inicialmente la interrupción se dispare
                                 ' por flanco de subida.

ALL_DIGITAL = TRUE               ' Todas las entradas y salidas son digitales.
                                                                              
TRISA  = %111111
TRISB  = %11111111               ' Puerto A y B todo entradas.
TRISC  = %00000000               ' Puerto C como salida para visualizar a través de los LED.
           
Dim x As  Byte                   ' Variable X ---> contador de posición actual.

x=0                              
 
While 1=1                        ' |------ Programa Principal ------|
     
     PORTC = x                   ' El contenido de X se visualiza en el Puerto C a través de los LED.

Wend                             ' |--------------------------------|
             
End                              

    
Interrupcion:                 '-------- Decodificador de Encoder --------------
       
    Context SAVE              ' Salva en contexto de los registros antes de operar con la interrupción.
    
    If PORTB.0 = 1    Then    ' Si RB0 se ha puesto a 1 (flanco de subida),
       INTEDG  = 0            ' entonces activar la siguiente interrupción por flanco de bajada.
       If PORTB.1 = 1 Then    ' Si RB1 está a 1
          Inc x               ' entonces incrementar el contador X.
       EndIf
    EndIf
    
    If PORTB.0 = 0    Then    ' Si RB0 se ha puesto a 0 (flanco de bajada),
       INTEDG  = 1            ' entonces activar la siguiente interrupción por flanco de subida.
       If PORTB.1 = 1 Then    ' Si RB1 está 1
          Dec x               ' entonces decrementar el contador X.
       EndIf
    EndIf
     
    INTF = 0                  ' Borra el "flag" de la interrupción RB0/INT     
                              ' para poder permitir la siguiente interrupción.
    Context Restore           ' Restablece el contexto de los registros tal como estaban antes de la
                              ' interrupción.

Funciona de la siguiente manera: Podemos hacer que la interrupción se active con un flanco de subida o de bajada, esto es programable modificando el registro INTEDG. Cuando ocurre una interrupción por flanco de subida hemos de programar la siguiente interrupción para que se active por flanco de bajada e incrementamos el contador si RB1 está a 1. Y viceversa, si ocurre una interrupción por flanco de bajada hemos de programar la siguiente interrupción por flanco de subida y decrementamos el contador si RB1 está a 1. La única condición que ha de cumplir es que cuando ocurra la interrupción previamente programada (sea de subida o de bajada) en RB0, RB1 ha de estar a 1. No tiene más secretos y cuenta los pulsos de forma muy eficiente.

Esquema:

Encoder16F876FotoBarrera.PNG


Por otra parte, el encoder que usas es el de un ratón, tiene muchos dientes, si eso lo colocas en un motor son muchos pulsos por vuelta y no creo que al PIC le diera tiempo de leer los pulsos. El máximo es de 5 pulsos por vuelta en un motor a toda velocidad.

Más info aquí: https://sites.google.com/site/proyectosroboticos/encoder/encoder-por-software
 
Subi tantas cosas que ya ni se lo que subi jeje... pero por las dudas acá te adjunto lo de las jogwheels, más atrás subi lo de los botones y lo de los leds... completo no hay nada, estan las partes :D.
En cuanto pueda voy a estudiar lo de las interrupciones, ademas creo que en los pics de la serie 18F las interrupciones se manejan de forma distinta... pero en la ayuda está todo.
Y en la página que pusiste también, yo de ahi saqué varias cosas.
Este es el código para las interrupciones en el 18F4550:
Código:
[LEFT]Device = 18F4550  ' Usamos el PIC 18F4550, pero puedes declarar cualquiera de los 18Fxx5x.


REMINDERS = 1     ' Comunicar todos los avisos de compilación.


XTAL = 4          ' Pon el cristal que quieras; en principio usamos un cristal de 4MHz.




Symbol INTF   = INTCON.1         ' RB0 External Interrupt Flag
Symbol INTE   = INTCON.4         ' RB0 External Interrupt Enable
Symbol GIE    = INTCON.7         ' Global Interrupt Enable
Symbol INTEDG = INTCON2.6        ' Flag = 0 int. por flanco bajada. Flag = 1 int. por flanco subida.


On_INTERRUPT GoTo Interrupcion   ' Interrupción por Hardware (es la más rápida).


GIE    = 1                       ' Activa interrupciones generales.
INTE   = 1                       ' Activa la interrupción externa RB0/INT.
INTEDG = 1                       ' Hace que inicialmente la interrupción se habilite
                                 ' por flanco de subida.
ALL_DIGITAL = TRUE               ' Todas las entradas y salidas son digitales.
                                                                              
TRISA  = %11111111               ' Puerto A todo entradas, en este caso no usamos el Puerto A.
TRISB  = %11111111               ' Puerto B todo entradas, sólo usamos las entradas RB0 y RB1.
TRISC  = %11111111               ' Puerto C todo entradas, en este caso no usamos el Puerto C.
TRISD  = %00000000               ' Puerto D todo salidas  (8 bits que irán a los LEDs).
TRISE  = %11111111               ' Puerto E todo entradas, en este caso no usamos el Puerto E.          


Dim x As  Byte                   ' Variable X ---> contador de posición actual con resolución
                                 ' 0..255
x=0                              
 
While 1=1                        ' |------ Programa Principal ------|
     
     PORTD = x                   ' El contenido de X se visualiza en el Puerto D a través de
                                 ' los LED.
Wend                             ' |--------------------------------|
             
End                              


Interrupcion:                 '-------- Decodificador de Encoder --------------
       
    Context SAVE              ' Salva en contexto de los registros antes de operar con la
                              ' interrupción.
    
    If PORTB.0 = 1    Then    ' Si RB0 se ha puesto a 1 (flanco de subida),
       INTEDG  = 0            ' entonces activar la siguiente interrupción por flanco de
                              ' bajada.
       If PORTB.1 = 1 Then    ' Si RB1 está a 1,
          Inc x               ' entonces incrementar el contador X.
       EndIf
    Else                      ' Si RB0 se ha puesto a 0 (flanco de bajada),  
       INTEDG  = 1            ' entonces activar la siguiente interrupción por flanco de
                              ' subida.
       If PORTB.1 = 1 Then    ' Si RB1 está 1,
          Dec x               ' entonces decrementar el contador X.
       EndIf
    EndIf
     
    INTF = 0                  ' Borra el "flag" de la interrupción RB0/INT para poder permitir
                              ' la siguiente interrupción cuando ocurra. 
    Context Restore           ' Restablece el contexto de los registros tal como estaban antes
                              ' de la interrupción.
[/LEFT]

Y respecto a lo de los 5 pulsos por vuelta... eso es con cristal de 4Mhz según lo que dice, pero con el pic trabajando a 48Mhz se pueden leer más pulsos.
 
Hola.

Vengo referenciado del foro Todopic.

Primero quiero felicitarlos por el proyecto. Es muy interesante. Algún día seguramente también lo haga. aunque tal vez utilice un ARM para ello.

En cuanto a la lectura e interpretación del Quadrature, lo mejor sería utilizar dos pines de entre los [RB4-RB7] ya que ellos permiten configurar una interrupción de cambio de estado(sin importar el flanco). Por ende interrumpirían ante cualquier cambio, y sólo habría que manipular una interrupción en lugar de 2.

Con respecto al problema de tener más de una interrupción y ambas sucedan al mísmo tiempo:
Hasta la serie 16F e inferiores, sólo poseen un nivel de prioridad de interrupciones, por lo que se levantarían ambos flags a la vez, y se ingresaría al vector de interrupción(0x004) y el código del usuario sería quien elija cuál de ambas se atiende primero según el orden ingresado(en caso de utilizar un compilador el orden será elegido por defecto por el compilador, aunque por lo general permiten especificar el orden de atención de las interrupciones).
En la serie 18F y superiores ya aparecen niveles de prioridad, en el caso de los 18F, uno puede elegir seleccionar ciertas interrupciones como de baja prioridad y otras como de alta. En caso de tener dos interrupciones que se produzcan a la vez pero ambas están configuradas con el mísmo nivel de prioridad(sea tanto bajo como alto) se aplicaría el caso que explico anteriormente.

En caso de que una sea configurada con nivel bajo y la otra con alto:
  • De producirse ambas exáctamente a la vez, se atenderá primero a la alta y luego se atenderá la baja.
  • En caso de producirse la alta mientras el uC está atendiendo la baja, se interrumple la baja, se atiende la alta y se la procesa. Luego una vez que se sale de la alta, se continúa con la baja, siempre y cuando no vuelva a ocurrir una de alto nivel.
  • En caso de producirse una baja mientras se atiende una alta, sólo una vez que se retorna de la alta se atenderá a la baja.

Digamos que como bien dice la palabra "prioridad", lo que está más arriba puede interrumpir a lo que está más abajo, pero no al reves.
Interrupción alta prioridad
Interrupción baja prioridad
Flujo de código normal
P.D. Los jogwheel estaría bueno hacerlos con ruedas capacitivas, no?

Saludos.
 
Última edición:
Ahora está más claro lo de las interrupciones ;)

P.D. Los jogwheel estaría bueno hacerlos con ruedas capacitivas, no?
Yo cuando tenga tiempo voy a ver si hago algo asi, busca en google, con un pin y una resistencia se puede hacer, creo que hay que poner el pin a 1, esperar 5 useg y leer la entrada...
Yo tengo ganas de hacer un teclado midi capacitivo ahora que ya están las bases del midi con el 18f2550 y funciona. Cualquier novedad les comento.

Justo encontré el link http://mondo-technology.com/touch.html
 
En cuanto a la lectura e interpretación del Quadrature, lo mejor sería utilizar dos pines de entre los [RB4-RB7] ya que ellos permiten configurar una interrupción de cambio de estado(sin importar el flanco). Por ende interrumpirían ante cualquier cambio, y sólo habría que manipular una interrupción en lugar de 2.

Sería lo ideal, pero esas entradas son las que se utilizan para los botones.

Saludos y gracias por las aportaciones.



No sé si el video será de vuestro gusto, pero aquí podeis ver lo que se puede llegar a hacer con el midi. Aguantad hasta el minuto 4:15 para ver lo que hace.

Este tipo antes solo utilizada un pad midi Akay, y viendolo fue lo que me llevó a plantearme el controlador midi, y que sería posible hacerlo en casa, jejeje
 
Última edición:
Atrás
Arriba