Mostrando entradas con la etiqueta CONTROL MOTOR. Mostrar todas las entradas
Mostrando entradas con la etiqueta CONTROL MOTOR. Mostrar todas las entradas

jueves, 13 de noviembre de 2014

ROBOT SENCILLO ARDUINO Y MATLAB

ROBOT DE EXPLORACIÓN SENCILLO
Ivan Alberto Mendoza Encinas
Instituto de ingeniería y tecnología
Matricula 103405

(656)-284-92-96

ivan.mendoza@outlook.com

Objetivo
El objetivo del proyecto es realizar un vehículo de exploración, que sea capaz de desplazarse hacia cualquier lado deseado, controlado vía Bluetooth, utilizando una programación en lenguaje C simplificado y Matlab.

Material
Hojas de Policarbonato
2 Motores de 12V
1 circuito integrado L293b
Tablilla Perforada
8 Diodos
2 llantas pequeñas
1 rueda omnidireccional
3 servomotores
1 Cámara
Arduino 1
1 Batería 7.5 V

Desarrollo

1.      Se desarrollo el programa que mandara las señales al arduino para controlar los movimientos del vehículo de exploración.


int izquierda0 = 12; // Pin 12 - izquierda0
int derecha0 = 11;  // Pin 11 - derecha0
int izquierda1 = 10;                         // Pin 10 - izquierda1
int derecha1 = 9;                         // Pin 9  - derecha1
int turbo = 8;                        // Pin 8  - Turbo
int luces = 7;             // Pin 7  - Luces Cortas
int lucesA = 13;              // Pin 6  - Luces Largas
int lucesB = 5;             // Pin 5  - Luces traseras
int lucesR = 4;         // Pin 4  - Luz de derecha0
int motor=3; //El pin numero 3 correspondera al motor
char tecla;  // Val es la variable que se recibira por medio de bluetooth
void setup() {
  // Declaramos los pines como salida con su correspondiente variable
pinMode(izquierda0, OUTPUT);
pinMode(derecha0, OUTPUT);
pinMode(izquierda1, OUTPUT);
pinMode(derecha1, OUTPUT);
pinMode(turbo, OUTPUT);
pinMode(luces, OUTPUT);
pinMode(lucesA, OUTPUT);
pinMode(lucesB, OUTPUT);
pinMode(lucesR, OUTPUT);

Serial.begin(9600);            // Inicializamos el puerto serial a 9600 baudios
}
// izquierda0
void F_izquierda(){
digitalWrite(izquierda0, HIGH);
digitalWrite(izquierda1, LOW);

digitalWrite(derecha0, LOW);
digitalWrite(derecha1, HIGH);
}
// derecha0
void F_derecha() {
digitalWrite(izquierda0, LOW);
digitalWrite(izquierda1, HIGH);
digitalWrite(derecha0, HIGH);
digitalWrite(derecha1, LOW);
}
// Detener Funcion izquierda0
void F_parar() {
digitalWrite(izquierda0, LOW);
digitalWrite(izquierda1, LOW);
digitalWrite(derecha0, LOW);
digitalWrite(derecha1, LOW);
}             
void F_Adelante() {
digitalWrite(izquierda0, LOW);
digitalWrite(izquierda1, HIGH);
digitalWrite(derecha0, LOW);
digitalWrite(derecha1, HIGH);
}
void F_Reversa() {
digitalWrite(izquierda0, HIGH);
digitalWrite(izquierda1, LOW);
digitalWrite(derecha0, HIGH);
digitalWrite(derecha1, LOW);
}
// Frenar - Parar
void Alto_Total() {
digitalWrite(izquierda0, LOW);
digitalWrite(derecha0, LOW);
digitalWrite(turbo, LOW);
digitalWrite(derecha1, LOW);
digitalWrite(izquierda1, LOW);
digitalWrite(lucesR, LOW);
}
// Encender luces bajas
void luces_on() {
digitalWrite(luces, HIGH);
digitalWrite(lucesB, HIGH);
}
// Apagar luces bajas
void luces_off() {
digitalWrite(luces, LOW);
digitalWrite(lucesB, LOW);
}
// Encender luces Altas
void lucesA_on() {
digitalWrite(lucesA, HIGH);
}
// Apagar luces altas
void lucesA_off() {
digitalWrite(lucesA, LOW);
}
// Encender luces de derecha0
void lucesR_on() {
digitalWrite(lucesR, HIGH);
}
// Apagar luces de derecha0
void lucesR_off() {
digitalWrite(lucesR, LOW);
}
// Funcion Switch case en funcion de la variable Val que se lee del serial.
void Comando() {
if (Serial.available()) {
tecla = Serial.read();
  }
  if (tecla>='0' && tecla<='9'){

        //De acuerdo a la variable le asignamos una proporcion entre 0 y 255
        int velocidad = map(tecla,'0','9',0,180);
                //Cambiamos el valor de PWM
        analogWrite(motor,velocidad);
        //Mensaje para el usuario
        Serial.print("El motor gira a velocidad ");
        Serial.println(tecla);
       }
      else if (tecla == 'a') { // izquierda0
F_izquierda();
    } else if (tecla == 'd') { // derecha0
F_derecha();
    } else if (tecla == ' ') { // Parar derecha0
F_parar();
    } else if (tecla == 'w') { // Turbo
F_Adelante();
    } else if (tecla == 's') { // Turbo
F_Reversa();
    }
}
void loop() { //ciclo infinito de muestreo de la variable Val para el Switch de casos
Comando();
}

2.      Se acondicionaron los motores con un puente H para poder controlar los giros de cada motor.








3.      Se creó la base del vehículo de exploración y se probó la conexión del Arduino con el circuito integrado.


4.      Se agregó un Módulo Bluetooth, el cual mandara las señales indicadas para que el dispositivo se mueva de la manera deseada.



5.       Se creó el programa en Matlab para mandar la señal de video a la computadora


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
close all;clear all;clc;

PS=serial('COM12');
set(PS,'Baudrate',9600); % se configura la velocidad a 9600 Baudios
set(PS,'StopBits',1); % se configura bit de parada a uno
set(PS,'DataBits',8); % se configura que el dato es de 8 bits, debe estar entre 5 y 8
set(PS,'Parity','none'); % se configura sin paridad
set(PS,'Terminator','CR/LF');% “c” caracter con que finaliza el envío
set(PS,'OutputBufferSize',2); % ”n” es el número de bytes a enviar
set(PS,'InputBufferSize' ,2); % ”n” es el número de bytes a recibir
set(PS,'Timeout',5); % 5 segundos de tiempo de espera


fopen(PS);

% primero se captura un stream de video usando videoinput, con argumento
%de winvideo, numero de dispositivo y formato de la camara, si no sabes usa la
%funcion imaqtool para averiguarlo es YUY o RGB
vid =  videoinput('winvideo',1,'RGB24_160x120');

%640x480 160x120
% Se configura las opciones de adquision de video
set(vid, 'FramesPerTrigger', Inf);
set(vid, 'ReturnedColorspace', 'rgb')
vid.FrameGrabInterval = 2;
%framegrabinterval significa que tomara cada 5 frame del stream de video adquirida
%con start(vid) se activa la adquisicion, pero todavia se toma la primera foto
start(vid)

% creamos un bucle que puede ser while always o while true en este caso
%y como mi compu es una netbook trucha(trucha=cagada=lenta=barata)
%hago que despues de 100 frames adquiridos se salga del bucle para evitar colgadas
while(vid.FramesAcquired<=200)

% se toma una snapshot del stream y se la almacena en data para trabajar mas
%facil
data = getsnapshot(vid);

% ahora vamos a reconocer el color rojo en tiempo real
% tenemos que extraer el color rojo
% de la imagen en escala de grises de la imagen adquirida en data
diff_im = imsubtract(data(:,:,1), rgb2gray(data));
%imsubstract sirve para sacar algun valor constante de una imagen, usamos como
%argumento el array de data y la funcion rgb2gray de data
%se usa medfilt2 para filtrar la senial del ruido
diff_im = medfilt2(diff_im, [3 3]);
% Convertir la imagen en escala de grises a una imagen binaria.
diff_im = im2bw(diff_im,0.18);

% para determinar el tamanio a reconocer se usa bwareopen para descartar
%imagen de rojo de menos de 300 pixels
diff_im = bwareaopen(diff_im,300);

% Etiquetamos los elementos conectados en la imagen
bw = bwlabel(diff_im, 8);

% Ahora hacemos el analisis del "objeto" detectado(que solo son pixels rojos)
%agrupados de mas de 300
% onfiguramos la region etiquetada
stats = regionprops(bw, 'BoundingBox', 'Centroid');

% mostramos la imagen
imshow(data)

hold on

%este es un bucle para encerrar el objeto rojo en un rectangulp y una cruz en el
%centroide(solo es programacion basica de matlab)
for object = 1:length(stats)
bb = stats(object).BoundingBox;
bc = stats(object).Centroid;
rectangle('Position',bb,'EdgeColor','r','LineWidth',2)
plot(bc(1),bc(2), '-m+')
a=text(bc(1)+15,bc(2), strcat('X: ', num2str(round(bc(1))), ' Y: ', num2str(round(bc(2)))));
set(a, 'FontName', 'Arial', 'FontWeight', 'bold', 'FontSize', 12, 'Color', 'yellow');

equis= num2str(round(bc(1)));

if equis < 99
fwrite(PS,equis,'uint8');

display(equis);

end
        
end

hold off
end
% aqui terminan los 2 bucles
% detenemos la captura
stop(vid);

%FLUSHDATA remueve la imagen del motor de adquisicion y la almacena en el buffer
flushdata(vid);
fclose(PS);
delete(PS);
clear PS;
% borramos todo(como en cualquier programa)
clear all
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%')

6.      Se creó y agrego el programa en lenguaje C simplificado para controlar los servomotores para el movimiento de la cámara.


int izquierda0 = 12; // Pin 12 - izquierda0
int derecha0 = 11;  // Pin 11 - derecha0
int izquierda1 = 10;                         // Pin 10 - izquierda1
int derecha1 = 9;                         // Pin 9  - derecha1
int turbo = 8;                        // Pin 8  - Turbo
int luces = 7;             // Pin 7  - Luces Cortas
int lucesA = 13;              // Pin 6  - Luces Largas
int lucesB = 5;             // Pin 5  - Luces traseras
int lucesR = 4;         // Pin 4  - Luz de derecha0

int motor=3; //El pin numero 3 correspondera al motor


char tecla;  // Val es la variable que se recibira por medio de bluetooth

void setup() {

  // Declaramos los pines como salida con su correspondiente variable
pinMode(izquierda0, OUTPUT);
pinMode(derecha0, OUTPUT);
pinMode(izquierda1, OUTPUT);
pinMode(derecha1, OUTPUT);
pinMode(turbo, OUTPUT);
pinMode(luces, OUTPUT);
pinMode(lucesA, OUTPUT);
pinMode(lucesB, OUTPUT);
pinMode(lucesR, OUTPUT);

Serial.begin(9600);            // Inicializamos el puerto serial a 9600 baudios
}


// izquierda0
void F_izquierda(){
digitalWrite(izquierda0, HIGH);
digitalWrite(izquierda1, LOW);

digitalWrite(derecha0, LOW);
digitalWrite(derecha1, HIGH);
}

// derecha0
void F_derecha() {
digitalWrite(izquierda0, LOW);
digitalWrite(izquierda1, HIGH);

digitalWrite(derecha0, HIGH);
digitalWrite(derecha1, LOW);
}

// Detener Funcion izquierda0
void F_parar() {
digitalWrite(izquierda0, LOW);
digitalWrite(izquierda1, LOW);

digitalWrite(derecha0, LOW);
digitalWrite(derecha1, LOW);
}



void F_Adelante() {
digitalWrite(izquierda0, LOW);
digitalWrite(izquierda1, HIGH);

digitalWrite(derecha0, LOW);
digitalWrite(derecha1, HIGH);
}

void F_Reversa() {
digitalWrite(izquierda0, HIGH);
digitalWrite(izquierda1, LOW);

digitalWrite(derecha0, HIGH);
digitalWrite(derecha1, LOW);
}



// Frenar - Parar
void Alto_Total() {
digitalWrite(izquierda0, LOW);
digitalWrite(derecha0, LOW);
digitalWrite(turbo, LOW);
digitalWrite(derecha1, LOW);
digitalWrite(izquierda1, LOW);
digitalWrite(lucesR, LOW);
}

// Encender luces bajas
void luces_on() {
digitalWrite(luces, HIGH);
digitalWrite(lucesB, HIGH);
}

// Apagar luces bajas
void luces_off() {
digitalWrite(luces, LOW);
digitalWrite(lucesB, LOW);
}

// Encender luces Altas
void lucesA_on() {
digitalWrite(lucesA, HIGH);
}

// Apagar luces altas
void lucesA_off() {
digitalWrite(lucesA, LOW);
}

// Encender luces de derecha0
void lucesR_on() {
digitalWrite(lucesR, HIGH);
}

// Apagar luces de derecha0
void lucesR_off() {
digitalWrite(lucesR, LOW);
}

// Funcion Switch case en funcion de la variable Val que se lee del serial.
void Comando() {
if (Serial.available()) {
tecla = Serial.read();
  }
  if (tecla>='0' && tecla<='9'){

        //De acuerdo a la variable le asignamos una proporcion entre 0 y 255
        int velocidad = map(tecla,'0','9',0,180);
       
        //Cambiamos el valor de PWM
        analogWrite(motor,velocidad);
        //Mensaje para el usuario
        Serial.print("El motor gira a velocidad ");
        Serial.println(tecla);

       }
      else if (tecla == 'a') { // izquierda0
F_izquierda();
    } else if (tecla == 'd') { // derecha0
F_derecha();
    } else if (tecla == ' ') { // Parar derecha0
F_parar();
    } else if (tecla == 'w') { // Turbo
F_Adelante();
    } else if (tecla == 's') { // Turbo
F_Reversa();
    }

}

void loop() { //ciclo infinito de muestreo de la variable Val para el Switch de casos
Comando();
}
 7. Se agregó al vehículo una base con tres  servomotores para agregarle movimiento a la cámara.


8.      Se probó la funcionalidad del vehículo de exploración.


Conclusión

El proyecto se realizó en aproximadamente 30 horas con un costo de $350 pesos ya que se contaba con la mayoría del material.
Los resultados del proyecto fueron en parte satisfactorios, el vehículo funciona correctamente al igual que el movimiento de la cámara realizado con servomotores. Se tuvieron complicaciones con el programa en Matlab y no se concluyó la conexión a la computadora. Se le agrego el manejo de los servomotores con un control  de joystick.




























viernes, 23 de mayo de 2014

CONTROL SERIAL DE PWM Y CAMBIO DE GIRO MOTOR PIC16F84A

Hola que tal hoy les dejo este sencillo codigo y una breve explicacion para poder controlar  la velocidad de un motor y hacer cambio del sentido del mismo por medio del pc, utilizando un micro PIC16F84A.

Se controlará un motor de DC por medio de una computadora, usando la comunicación por RS232. A la vez se mostraran mensajes en el LCD de a cuánta intensidad va girando el motor. También se usará el Puente H para hacer que el motor cambie de sentido. Se debe usar la interrupción externa para leer los datos que envíe la PC y que el motor continúe girando.


CIRCUITO:



Este es el circuito utilizado para esta práctica. El PORTA es para las salidas que están conectados hacia el LCD: el pin RS con el pin RA0 y el pin RA2 con el pin E del LCD. El pin R/W del LCD puede ir conectado a tierra o al pin RA1 del micro controlador, siempre y cuando este mandando un 0 a R/W, pero en esta ocasión se utilizó para la salida hacia el LED.
En el PORTB se utiliza la parte alta del registro como salidas para el LCD. Van del RB4:RB7 y del LCD D4:D7. Se activan las resistencias pull-up, ya que el RB0 se conecta como entrada de la PC. RB1 y RB2 se utilizan como salidas hacia el circuito integrado L293D.
En los pines 15 y 16 del micro controlador, irá el oscilador de cuarzo de 4 MHz conectado en paralelo. Se conectará un capacitor de 22pF a cada pin del oscilador y conectados a tierra. El MCRL estará conectado sólo a voltaje.
Los pines 15 y 16 del LCD, irán a voltaje por medio de una resistencia de 330 ohms y a tierra, respectivamente.
El circuito L293 es el integrado que simula el Puente H, los pines 2 y 7 son entradas para el microcontrolador. Los pines 3 y 6 son salidas hacia el motor. Se conectan sus respectivos pines a tierra y a voltaje. El pin de Enable está conectado a voltaje, para que siempre esté habilitado.


MATERIAL:

-Microcontrolador PIC16F84A
-1 LCD 16x2
-1 L293D
-Motor DC
-1 resistencia de 330 ohms
-1 cable para RS232
-Computadora
-Cristal de cuarzo de 4 MHz
-2 capacitores de 22 pF
-Alambres
-Protoboard
-Fuente y sus cables

CÓDIGO:

CODIGO DEL PROGRAMA:
; ZONA DE DATOS *****************************************************
                LIST                       P=16F84A
                INCLUDE                             <P16F84A.INC>
                __CONFIG           _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC
                CBLOCK  0x0C
                V_tecla
                V_encendido
                V_apagado
                Enciende
                 Apaga
                VCambioG
                ENDC
#DEFINE     Giro1       PORTB,1
#DEFINE     Giro2       PORTB,2
; ZONA DE CÓDIGOS **********************************************
                ORG       0
                goto    Inicio
                ORG 04h
                goto    Interrupcion
;MENSAJES--------------------------------------------------------------------
Mensajes
                addwf     PCL,F                   ;Tabla de mensajes
MensajeN                                            ; Posición inicial del mensaje.
                DT "Deana 103696",0x0
Mensaje10
                DT "Velocidad a 10% ",0x0
Mensaje20
                DT "Velocidad a 20% ",0x0
Mensaje30
                DT "Velocidad a 30% ",0x0
Mensaje40
                DT "Velocidad a 40% ",0x0
Mensaje50
                DT "Velocidad a 50% ",0x0
Mensaje60
                DT "Velocidad a 60% ",0x0
Mensaje70
                DT "Velocidad a 70% ",0x0
Mensaje80
                DT "Velocidad a 80% ",0x0
Mensaje90
                DT "Velocidad a 90% ",0x0
Mensaje100
    DT "Velocidad a 100%",0x0
Mensaje0
    DT "Velocidad a   0%",0x0
;********************************************************
    ORG 0x100
;********************************************************
Inicio
    call     LCD_Inicializa                    ;inicializa LCD
    call    RS232_Inicializa                  ;Inicializa comunicacion con la PC
    bsf     STATUS,RP0                        ;accesa al banco 1
    bcf     Giro1                                      ;PORTB1 como salida
    bcf     Giro2                                      ;PORTB2 como salida
    bcf     OPTION_REG,INTEDG      ;interrupcion por flanco de bajada
    bcf     OPTION_REG,NOT_RBPU ;habilita resistencias pull-up
    bcf     STATUS,RP0                        ;accesa al banco 0
    movlw   b'10010000'                      ;habilita la interrupcion externa
    movwf   INTCON
    call    LCD_Linea1                         ;se posiciona en la linea 1
    movlw   MensajeN                         ;Mensaje de nombre y mat.
    call    LCD_Mensaje                      ;se muestra en el LCD
    call    LCD_Linea2                         ;se posiciona en la linea 2
    movlw   Mensaje0                          ;mensaje de velocidad 0
    call    LCD_Mensaje                      ;lo muestra en el LCD
;-CODIGO-PRINCIPAL-------------------------------------------------------------
Main
    movf    V_apagado,W                    ;mueve lo que obtuvo de apagado en la
    movwf   Apaga                                ;interrupcion
    movf    V_encendido,W                 ;mueve lo que obtuvo de encendido en la
    movwf   Enciende                           ;interrupcion
    sublw   .10                                       ;maximo de velocidad
    btfsc   STATUS,Z            ;llego a la velocidad maxima?
    goto    Cien                                      ;si, ve a cien
    movf    Enciende,W                        ;lee de nuevo la variable
    sublw   .0                                          ;para saber si no gira
    btfsc   STATUS,Z            ;velocidad=0?
    goto    Cero                                      ;si, ve a cero
    btfsc   VCambioG,0                        ;ha cambiado de sentido?
    goto    CambioGiro                         ;si, cambia el sentido del giro
CicloEncendido
    bsf     Giro1                                      ;gira hacia un lado
CambioGiro1
    call    Retardo_50micros               ;espera
    decfsz  Enciende,F                        ;decrementa la variable, llego a 0?
    goto    CicloEncendido+1             ;no, ve a esperar de nuevo
    goto    CicloApagado                     ;si, salta a apagado
CambioGiro
    bsf     Giro2                                      ;cambia el giro
    goto    CambioGiro1                      ;regresa a ciclo de encendido
CicloApagado
    bcf     Giro1                                      ;apaga esa salida
    bcf     Giro2                                      ;apaga esa salida
    call    Retardo_50micros               ;espera
    decfsz  Apaga,F                              ;decrementa la variable, llego a 0?
    goto    CicloApagado+2                ;no, espera de nuevo
    goto    Fin                 ;
Cien
    btfss   VCambioG,0          ;Cambio el bit?
    goto    Cambia100           ;si, cambia el sentido
    bsf     Giro2                       ;no, continúa en el mismo
    goto    Fin                 ;
Cambia100
    bsf     Giro1                       ;ahora gira en este sentido
    goto    Fin
Cero
    clrf   PORTB                     ; PORTB apagado
Fin goto    Main                   ;haz todo de nuevo
;INTERRUPCION------------------------------------------------
Interrupcion
    call    RS232_LeeDato                  ;tecla presionada
    movwf   V_tecla                              ;la guarda
    call    RS232_EnviaDato             ;envía dato a la pc
    movf    V_tecla,w                            ;rutina 10
    xorlw   'q'                                   ;compara tecla con q
    btfsc   STATUS,Z                            ;presiono q?
    goto    Diez                                      ;si
    movf    V_tecla,W           ;no, lee de nuevo
    xorlw   'w'                                          ;compara con w
    btfsc   STATUS,Z            ;es la tecla w?
    goto    Veinte                                   ;si, ve a 20
    movf    V_tecla,W           ;
    xorlw   'e'                 ;
    btfsc   STATUS,Z            ;fue la tecla e?
    goto    Treinta                                  ;si, ve a 30
    movf    V_tecla,W
    xorlw   'r'
    btfsc   STATUS,Z            ;fue la tecla r?
    goto    Cuarenta                              ;si, ve a 40
    movf    V_tecla,W
    xorlw   't'                
    btfsc   STATUS,Z            ;presiono t?
    goto    Cincuenta                            ;si, ve 50
    movf    V_tecla,W
    xorlw   'y'            
    btfsc   STATUS,Z                             ;presiono y?
    goto    Sesenta                                ;si, ve a 60
    movf    V_tecla,W
    xorlw   'u'
    btfsc   STATUS,Z            ;presiono u?
    goto    Setenta                                 ;si, ve a 70
    movf    V_tecla,W
    xorlw   'i'
    btfsc   STATUS,Z                             ;presiono i?
    goto    Ochenta                                ;si, ve a 80
    movf    V_tecla,W
    xorlw   'o'                
    btfsc   STATUS,Z                             ;presiono o?
    goto    Noventa                               ;si, ve a 90
    movf    V_tecla,W
    xorlw   'p'                
    btfsc   STATUS,Z                             ;presiono p?
    goto    Cien1                                     ;si, ve a 100
    movf    V_tecla,W
    xorlw   'g'                
    btfsc   STATUS,Z                             ;presiono g?
    goto    Girog                                     ;si, cambia el giro
    movf    V_tecla,W           ;
    xorlw   'h'                
    btfsc   STATUS,Z            ;presiono h?
    goto    Giroh                                     ;si, cambia el giro
    movf    V_tecla,W           ;rutina cero
    xorlw   'c'
    btfss   STATUS,Z                              ;presiono c?
    goto    FinInterrupcion                   ;no, termina
Para
    call    LCD_Linea2        ;si, posicionate en la linea 2
    movlw   Mensaje0                           ;mensaje vel. 0
    call    LCD_Mensaje                       ;muestra en el LCD
    movlw   .0                                   ;pone a 0 la variable
    movwf   V_encendido
    goto    FinInterrupcion          ;termina la interrupcion
Diez
    call    LCD_Linea2           ;se posiciona en la linea 2
    movlw   Mensaje10                         ;mensaje vel. 10
    call    LCD_Mensaje                 ;muestra el mensaje
    movlw   .1                                          ;velocidad 10%
    movwf   V_encendido
    movlw   .9
    movwf   V_apagado
    goto    FinInterrupcion                         ;termina la interrupcion
Veinte
    call    LCD_Linea2
    movlw   Mensaje20                        ;mensaje de 20%
    call    LCD_Mensaje
    movlw   .2                                          ;velocidad 20%
    movwf   V_encendido
    movlw   .8
    movwf   V_apagado
    goto    FinInterrupcion
Treinta
    call    LCD_Linea2
    movlw   Mensaje30                        ;mensaje de 30%
    call    LCD_Mensaje    
    movlw   .3                                     ;velocidad de 30%
    movwf   V_encendido
    movlw   .7
    movwf   V_apagado
    goto    FinInterrupcion
Cuarenta
    call    LCD_Linea2
    movlw   Mensaje40                        ;mensaje de 40%
    call    LCD_Mensaje
    movlw   .4                                      ;velocidad de 40%
    movwf   V_encendido
    movlw   .6
    movwf   V_apagado
    goto    FinInterrupcion
Cincuenta
    call    LCD_Linea2
    movlw   Mensaje50
    call    LCD_Mensaje
    movlw   .5
    movwf   V_encendido
    movlw   .5
    movwf   V_apagado
    goto    FinInterrupcion
Sesenta
    call    LCD_Linea2
    movlw   Mensaje60
    call    LCD_Mensaje
    movlw   .6
    movwf   V_encendido
    movlw   .4
    movwf   V_apagado
    goto    FinInterrupcion
Setenta
    call    LCD_Linea2
    movlw   Mensaje70
    call    LCD_Mensaje
    movlw   .7
    movwf   V_encendido
    movlw   .3
    movwf   V_apagado
    goto    FinInterrupcion
Ochenta
    call    LCD_Linea2
    movlw   Mensaje80
    call    LCD_Mensaje
    movlw   .8
    movwf   V_encendido
    movlw   .2
    movwf   V_apagado
    goto    FinInterrupcion
Noventa
    call    LCD_Linea2
    movlw   Mensaje90
    call    LCD_Mensaje
    movlw   .9
    movwf   V_encendido
    movlw   .1
    movwf   V_apagado
    goto    FinInterrupcion
Cien1
    call    LCD_Linea2
    movlw   Mensaje100
    call    LCD_Mensaje
    movlw   .10
    movwf   V_encendido
    goto    FinInterrupcion
Girog
    bsf     VCambioG,0                         ;activa bit para cambiar en este sentido
    bcf     Giro1                                      ;apaga este sentido de giro
    goto    FinInterrupcion
Giroh
    bcf     VCambioG,0                          ;desactiva bit para regresar el giro de inicio
    bcf     Giro2                                      ;apaga el otro sentido de giro
FinInterrupcion
    bcf     INTCON,INTF                        ;vuelve a habilitar las interrupciones
    retfie
; Librerias ----------------------------------------------------
                INCLUDE  <LCD_MENS.INC>                                       ; Subrutina LCD_MensajeMovimiento.
                INCLUDE  <LCD_4BIT.INC>                                          ; Subrutinas de control del LCD.
                INCLUDE  <RETARDOS.INC>                                       ; Subrutinas de retardos.
                INCLUDE  <RS232.INC>                                                 ;subrutina para comunicacion con la PC
                END                                                                                                                     ; Fin del programa.


CONCLUSIÓN:


El programa tiene que hacer muchas comparaciones debido a que son 12 teclas que tiene que estar evaluando. La interrupción debe de estar por flanco descendente y la llamada para saber que tecla pulsó, debe estar dentro del servicio a la interrupción. Así no estará verificando continuamente el pin de recepción para el inicio de la comunicación con el RS232. Los retardos se tuvieron que bajar de 100us a 50us, porque el motor tenía problemas con el pwm, ya que no estaba girando al porcentaje especificado.

Espero les sea de utilidad.