Mostrando entradas con la etiqueta SERIAL. Mostrar todas las entradas
Mostrando entradas con la etiqueta SERIAL. 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

COMUNICACIÓN PIC16F84A A PC

TEORIA COBRE COMUNICACIÓN DE LA PC AL MICROCONTROLADOR

La forma más común y sencilla de comunicar cualquier dispositivo con un ordenador es através de si puerto serie, que es compatible con el denominado estándar RS232 (EIA232 standard). En un ordenador puede haber varios puertos series, normalmente denominados COM1, COM2, etc.
Los puertos series son accesibles medinte conectores. La norma RS232 establece 2 tipos de conectores llamados DB-25 (de 25 pines) y DB-9 (9 pines), machos y hembras. Cada una de las patillas del conector RS232 tiene una función especificada por la norma. Hay unos terminales por los que recibe y transmite datos y otros que controlan el establecimiento, flujo y cierre de la comunicación.

Hay circuitos que permiten la conversión entre niveles TTL y niveles RS232. El MAX232 convierte los niveles RS232 (cerca de +12 y -12 V) a voltajes TTL (0 a +5V) y viceversa sin requerir nada más que una fuente de +5V. El chip contiene dos drivers TTL a RS232 y dos RS232 a TTL. Necesita cuatro capacitores externos de unos pocos microfaradios para generar el voltaje RS232 internamente.

Estos son los únicos pines que se necesitan para que pueda comunicarse el pic con la computadora.

-       El pin 3 es para la línea de transmisión TxD, transmite información con niveles RS232, por tanto se conecta al pin de R1IN del MAX232 para convertir estos niveles a TTL y transmitírselos al PIC16F84A a través de la patilla R1OUT.
-       El pin 2 es la línea de recepción RxD, por donde envía la información el PIC16F84A con niveles TTL entra en la línea T1IN del MAX232 para convertirla en niveles RS232 y poder ser recibida por el puerto serie RS232.
-       El pin 5 es de masa/tierra (SG)

Para el control de la comunicación del ordenador con el microcontrolador es necesario el siguiente software:
-       Unas subrutinas que gestionen el software del microcontrolador, como las utilizadas en la librería RS232.INC
-       Un programa para el ordenador que gestione el control del sistema, tal como Hyperterminal de Windows o similar.

     Les dejo el que yo utilizo y funciona muy bien en cualquier Windows.



DESCRIPCIÓN:
En el LCD se visualizarán los caracteres que se escriban en el teclado de la computadora. Cuando llegue al límite de los 16 caracteres que se puedan ver en la primera línea, se cambiará a la segunda línea y cuando termine los 16 de esa línea, estos últimos caracteres se pasaran a la primera línea y continuará escribiendo en la segunda línea y así sucesivamente.


CIRCUITO:



Este es el circuito utilizado para esta práctica. Se tiene a PORTA como salida y entrada de la comunicación con el ordenador; y a PORTB como salida.
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. Los pines RA3 y RA4, son entradas del circuito integrado MAX232, uno se comporta como transmisor y el otro como receptor, respectivamente.
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.
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. El MCLR se puede conectar solo 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 integrado que conecta la comunicación de la PC con el microcontrolador es el MAX232. Los pines 14 y 13, son el transmisor de salida y el receptor de entrada. Los pines 11 y 12 son los pines del transmisor de entrada y el receptor de salida. Los pines restantes son conectados a capacitores de 1uF.


MATERIAL:

-Microcontrolador PIC16F84A
-1 LCD 16x2
-1 cable RS232
-Computadora
-Transceptor MAX232
-4 resistencias de 330 ohms
-Cristal de cuarzo de 4 MHz
-2 capacitores de 22 pF
-4 capacitores de 1uF
-1 capacitor de 100nF
-Alambres
-Protoboard
-Fuente y sus cables

CODIGO DEL PROGRAMA:

;MPLABX*************************************************************************

                LIST                       P=16F84A
                INCLUDE                             <P16F84A.INC>
                __CONFIG           _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC

                CBLOCK  0x0C
    Contador                ;cuenta los caracteres
    Tecla                       ;guarda lo que se ha pulsado
    Contador_ram        ;contador para mostrar los numeros/caracteres
                ENDC
; ZONA DE CÓDIGOS *************************************************************
                ORG       0
                goto        Inicio
;INICIO-------------------------------------------------------------------------
Inicio
    call                     LCD_Inicializa          ;Inicializa el LCD
    call                     RS232_Inicializa        ;Inicializa comunicacion con el puerto
    movlw                PrimeraDir              ;Mueve la primera direccion disponible
    movwf                FSR                     ;de la ram
;CODIGO-PRINCIPAL--------------------------------------------------------------
Main
     call    RS232_LeeDato                                ; Espera recibir un carácter.
     movwf               Tecla                                     ; Guarda el dato recibido.
     call                    LCD_Caracter                                    ; Lo visualiza.
     movf                  Tecla,W                                                ; Y ahora lo reenvía otra vez al ordenador.
     call                    RS232_EnviaDato
    incf                     Contador,F                                          ;Incrementa el contador
    movf                   Contador,W                                         ;lo lee W
    sublw                 .16                                         ;lo resta para saber si llego al max.
    btfss                   STATUS,C                                           ;evalua si es un numero neg.
    call                      Linea2                                                 ;pasa a la segunda linea
MoverLinea
    movf                   Contador,W                                         ;Lee Contador
    sublw                 .32                                         ;Resta para saber si cubrio las 2 lineas
    btfss                   STATUS,C                                           ;Evalua
    call                     A_linea1                                              ;Mueve lo que está en la linea 2 a la 1
    goto                   Main
;SUBRUTINAS--------------------------------------------------------------------
A_linea1
    movlw                PrimeraDir             ;mueve de nueva la primera dir. disponible
    movwf                FSR
    call                     LCD_Linea1           ;Pone el cursor en la linea 1
    movlw                .17                            ;max. de caracteres por linea
    movwf                Contador                ;lo pone en el contador, para que no sobreescriba
    movlw                .16
    movwf                Contador_ram        ;num. max. de caracteres que la ram guardara
Ciclo
    movf                    INDF,W                                ;Lee el contendo que esta en la direccion de FSR
    call                      LCD_Caracter                    ;evaluando si se activo para mostrar este carac-
    incf                     FSR,F                                    ;incrementa la direccion
    decfsz                Contador_ram,F                 ;Decrementa el no. de direcciones (16)
    goto                   Ciclo                                      ;Hasta que termine de mostrar los 16 caracteres
    movlw                PrimeraDir                           ;Termina de mostrar, y lee de nuevo la 1ra dir.
    movwf                FSR
    call                     LCD_Linea2                        ;Llama a la segunda linea
    call                     LCD_LineaEnBlanco        ;limpia la linea
    call                     LCD_Linea2                        ;Vuelve a llamar a la linea
    return
Linea2                                                                  ;Se encarga de ir guardando los caracteres una
    movf                    Contador,W                        ;vez que ya se encuentra el cursor en la segunda
    sublw                  .17                                        ;linea. Evalua si lla llego al max. de los carac-
    btfsc                    STATUS,Z                           ;teres en la segunda linea
    call                     LCD_Linea2                        ;se coloca en la linea 2
    movf                    Tecla,W                               ;lee lo que hay en Tecla
    movwf                INDF                                      ;lo guarda en el registro INDF que esta en cierta
    incf                     FSR,F                                    ;direccion de FSR. Se mueve a la siguiente
    return                                                                ;direccion
;LIBRERIAS----------------------------------------------------------------------
                INCLUDE  <RS232.INC>                                 ; Subrutinas de control del teclado.
                INCLUDE  <LCD_4BIT.INC>
                INCLUDE  <RETARDOS.INC>
    CBLOCK
    PrimeraDir                                                                      ;La primera direccion disponible para llenar
    ENDC
                END


CONCLUSIÓN:

Como en la práctica anterior se había analizado un problema similar al de esta práctica (el cambio de renglón automático) fue mucho más fácil desarrollar esta vez el código. Se reafirmaron los conocimientos sobre usar la memoria RAM del microcontrolador.