martes, 18 de mayo de 2010

lunes, 17 de mayo de 2010

VISION POR COMPUTADORA

A continuacion se muestra una imagen y un video de la programacion de Matlab

Diagrama del circuito de control


El circuito fue en un principio diseñado con TIP41 pero el exceso de corriente generaba una buena cantidad de calor. Por lo que se opto por el uso de IGBT que resisten una potencia mayor. También para aligerar la potencia del motor se utilizo la técnica de control de PWM por lo que se diseño un circuito de que se describe en el siguiente diagrama (figura 1).


Figura 1.
El control se realiza por puerto serial desde una computadora remota y la señal sale por el puerto B de un PIC16F877A. Para controlar la salida del PWM a cada una de las bobinas del motor de pasos se utilizo una compuerta AND (74LS08). La condición para generara el paso del motor fue que el puerto B del PIC estuviera en ALTO. El PWM está en la otra compuerta de la AND, lo que mandaría un pulso de salida siempre y cuando ambos estuvieran en ALTO en ese momento. Esta señal estaría a un nivel TTL. Para desacoplar la señal y poder asegurar una buena amplitud de voltaje que llegue al Op-Amp se utilizo el opto-acoplador, cuya función también fue separa las etapas de potencia a la de control. La señal que salió del opto tenía una amplitud de 0 a 8 Volts. Esta señal llega a un Op-Amp configurado en modo inversor y sin una resistencia de retroalimentación, que sería un disparador de Schmitt. El umbral de referencia fue tomado de la línea de 16V, por medio de un divisor de voltaje de 10k y 1k ohm. Este umbral fue de 1.7 V, pasando este voltaje se hacia un dispara hasta 15 Volts al GATE del IGBT. Se pudo también observar que la operación óptima del IGBT es cuando recibe 15V.

Por cuestiones de tiempo se inicio utilizando un driver especial para IGBT, que también puede ser utilizado para MOSFETs de potencia. No se utilizaron en la composición final pues se descompletaron, pero revelaron propiedades interesantes del IGBT. Interiormente el IGBT tiene una configuración de capacitores. Estos capacitores junto con un valor específico de resistencia en la entrada del GATE nos dan el tiempo de ENCENDIDO y AMPAGADO del IGBT. El tiempo de apagado es más lento que el encendido, por lo que se utiliza un diodo en paralelo para reducir la resistencia al momento de cambiar el flujo de la corriente acumulada en la capacitancia interna del transistor.
Otro detalle es que cuando no se tiene definido en el GATE si es un O Volts o un 15 Volts en el transistor se destruye (literal explota).

Cada uno de las etapas explicadas anteriormente se repitieron 4 veces por motor, ya que se esta configurando en UNIPOLAR y cuenta con 4 Bobinas. A, A', B y B'. La secuencia es A, B, A' y B' trabajando en pasos completos.

Se tuvieron problemas con el suministro de energía, pues por una extraña razón cuando se arrancaba el control se generaba un consumo muy alto de corriente. Se soluciono parte del problemas haciendo variar la corriente de cada paso por medio del IGBT, pues las inductancias de los motores crea una resistencia al cambio de la corriente, por lo que trabajamos a una frecuencia de 4KHz. Y subió el voltaje en la bobinas. Pero aun así la corriente era demasiada que en algunas fuentes se caía el voltaje por cuestiones de protección.

VISION POR COMPUTADORA, MATLAB

el siguiente codigo que se muestra el toda la programacion en Matlab para la vision por medio de una webcam que en este caso es la Eye 312 de Genius.

%Dar de alta la camara resolucion y caracteristicas

imaqhwinfo; %informacion de las camaras detectadas(*******************NO ES NECESARIO PARA EL PROGRAMA)
vid = videoinput('winvideo',1, 'RGB24_320x240');

%Configuracion del puerto serial para la comunicacion con el micro

SerPIC = serial('COM3');
set(SerPIC,'BaudRate', 2400, 'DataBits', 8, 'Parity', 'none','StopBits', 1, 'FlowControl', 'none');
fopen(SerPIC);

%Declaracion de variables y vectores

objetos=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
laser=66;
grandote=0;

%Reconocimiento de ambiente

a=getsnapshot(vid);
aa=rgb2gray(a);

%Ciclo principal en el que se correra el programa
for k = 0:0.25:7

%Obtiene imagen con cambios
b=getsnapshot(vid);
bb=rgb2gray(b);

%Diferencia entre imagen actual y el entorno aprendido
c=imsubtract(bb,aa);

%binarizacion de la imagen resultado(se calibra a las condiciones de luz)
d=c>=20;

%filtro antiruido
magic=strel('square', 2);
link=imerode(d, magic);

%Despliega foto(*************NO ES NECESARIO PARA EL PROGRAMA)
imshow(link);
hold on

%Obtener informacion de la foto
cen = regionprops(link);
num = numel(cen);

%Condicion donde se debe detectar minimo 1 objeto
if (num ~= 0)

%Identificador de objetos(se tiene que calibrar a las condiciones de luz)
for l = 1:num
if (cen(l).Area <= 47)&&(cen(l).Area >= 5)
laser = l;
end
objetos(l)=cen(l).Area;
end

%algoritmo burbuja para ordenar objetos de mas grande a mas chico
for i=1:9
for j=i+1:10
if (objetos(i) < objetos(j))
temp = objetos(i);
objetos(i) = objetos(j);
objetos(j) = temp;
end
end
end
%fin de algoritmo burbuja

%detectar el num del objeto mas grande
for z=1:num
if (cen(z).Area == objetos(1))
grandote = z;
end
end

%Condiciones para mover la pistola
if (laser == 66)
master = 100;
disp(['DISPARA']); %Despliega en la pantalla(*************NO ES NECESARIO PARA EL PROGRAMA)
else
if (objetos(1) ~= cen(laser).Area)
salidax = cen(grandote).Centroid(1) - cen(laser).Centroid(1);
saliday = cen(grandote).Centroid(2) - cen(laser).Centroid(2);
if (salidax > 0)&&(saliday > 0)
master=41; %muevete a la derecha y arriba
disp(['derecha abajo ']); %Despliega en la pantalla(*************NO ES NECESARIO PARA EL PROGRAMA)
else if (salidax < 0)&&(saliday > 0)
master = 69; %muevete izquerda y arriba
disp(['izquierda abajo ']); %Despliega en la pantalla(*************NO ES NECESARIO PARA EL PROGRAMA)
else if (salidax > 0)&&(saliday < 0)
master = 22; %muevete derecha y abajo
disp(['dereha arriba ']); %Despliega en la pantalla(*************NO ES NECESARIO PARA EL PROGRAMA)
else if (salidax < 0)&&(saliday < 0)
master = 255; %muevete izquierda y abajo
disp(['izquierda arriba ']); %Despliega en la pantalla(*************NO ES NECESARIO PARA EL PROGRAMA)
end
end
end
end
end
end
end

puppet = typecast(master, unit8);
fwrite(SerPIC, '%s', puppet); %Mandar la variable master para mover o disparar


laser=66;
end
%fin del ciclo principal del programa

fclose(SerPIC)
delete(SerPIC)
clear SerPIC

%fin de programa

codigo sentry gun,

/* con este codigo se controlan los dos motores a pasos y tambien se despliega los datos en el puerto D, los dos motores a pasos se encuentran en el puerto B, donde el nibble superior es para el motor que se mueve en Y y el nibble inferior se dejo para el motor que se mueve en X, la secuencia de pasos se despliega en el puerto D.



*/
int i;
int n;
int command;



void main() {
PORTB =0;
TRISB =0;
PORTD =0;
TRISD =0;
Usart_Init(2400);


do {

if (Usart_Data_Ready()) { // If data is received for Y axis
command = Usart_Read();
Usart_Write(command);
}
//++++++++++++++++ condiciones+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if (command ==41){ //si es 255
i++;// derecha
n++;// arriba
}
if (command ==64){ //si es 255
i--; //izquierda
n++; // arriba
}
if (command ==22){ //si es 255
i++; // derecha
n--; // abajo
}
if (command ==255){ //si es 255
i--; // izquierda
n--; // abajo
}

if(i>7){i=0;} //resetear contador de dirrección.
if(i<0){i=7;}>
if(n>7){n=0;} //resetear contador de dirrección.
if(n<0){n=7;}

//++++++++++++++++++++++++++++++++ primer motor+++++++++++++++++++++++++++++++++++++++++++
switch (i){
case 0 : PORTB.F0 = 1;
PORTB.F1 = 0;
PORTB.F2 = 0;
PORTB.F3 = 0; break;
case 1 : PORTB.F0 = 1;
PORTB.F1 = 1;
PORTB.F2 = 0;
PORTB.F3 = 0; break;
case 2 : PORTB.F0 = 0;
PORTB.F1 = 1;
PORTB.F2 = 0;
PORTB.F3 = 0; break;
case 3 : PORTB.F0 = 0;
PORTB.F1 = 1;
PORTB.F2 = 1;
PORTB.F3 = 0; break;
case 4 : PORTB.F0 = 0;
PORTB.F1 = 0;
PORTB.F2 = 1;
PORTB.F3 = 0; break;
case 5 : PORTB.F0 = 0;
PORTB.F1 = 0;
PORTB.F2 = 1;
PORTB.F3 = 1; break;
case 6 : PORTB.F0 = 0;
PORTB.F1 = 0;
PORTB.F2 = 0;
PORTB.F3 = 1; break;
case 7 : PORTB.F0 = 1;
PORTB.F1 = 0;
PORTB.F2 = 0;
PORTB.F3 = 1; break;
default : PORTB = 0; break;
}


switch (i) {
case 0 : PORTD.F0 = 1;
PORTD.F1 = 0;
PORTD.F2 = 0;
PORTD.F3 = 0; break;

case 1 : PORTD.F0 = 1;
PORTD.F1 = 1;
PORTD.F2 = 0;
PORTD.F3 = 0; break;

case 2 : PORTD.F0 = 0;
PORTD.F1 = 1;
PORTD.F2 = 0;
PORTD.F3 = 0; break;

case 3 : PORTD.F0 = 0;
PORTD.F1 = 1;
PORTD.F2 = 1;
PORTD.F3 = 0; break;

case 4 : PORTD.F0 = 0;
PORTD.F1 = 0;
PORTD.F2 = 1;
PORTD.F3 = 0; break;

case 5 : PORTD.F0 = 0;
PORTD.F1 = 0;
PORTD.F2 = 1;
PORTD.F3 = 1; break;

case 6 : PORTD.F0 = 0;
PORTD.F1 = 0;
PORTD.F2 = 0;
PORTD.F3 = 1; break;

case 7 : PORTD.F0 = 1;
PORTD.F1 = 0;
PORTD.F2 = 0;
PORTD.F3 = 1; break;
}

//+++++++++++++++++++++++ segundo motor++++++++++++++++++++++++++++++++++++++++++++++++++++++++

switch (n){
case 0 : PORTB.F4 = 1;
PORTB.F5 = 0;
PORTB.F6 = 0;
PORTB.F7 = 0; break;

case 1 : PORTB.F4 = 1;
PORTB.F5 = 1;
PORTB.F6 = 0;
PORTB.F7 = 0; break;

case 2 : PORTB.F4 = 0;
PORTB.F5 = 1;
PORTB.F6 = 0;
PORTB.F7 = 0; break;

case 3 : PORTB.F4 = 0;
PORTB.F5 = 1;
PORTB.F6 = 1;
PORTB.F7 = 0; break;

case 4 : PORTB.F4 = 0;
PORTB.F5 = 0;
PORTB.F6 = 1;
PORTB.F7 = 0; break;

case 5 : PORTB.F4 = 0;
PORTB.F5 = 0;
PORTB.F6 = 1;
PORTB.F7 = 1; break;

case 6 : PORTB.F4 = 0;
PORTB.F5 = 0;
PORTB.F6 = 0;
PORTB.F7 = 1; break;

case 7 : PORTB.F4 = 1;
PORTB.F5 = 0;
PORTB.F6 = 0;
PORTB.F7 = 1; break;
default : PORTB = 0; break;
}


switch (n) {
case 0 : PORTD.F4 = 1;
PORTD.F5 = 0;
PORTD.F6 = 0;
PORTD.F7 = 0; break;

case 1 : PORTD.F4 = 1;
PORTD.F5 = 1;
PORTD.F6 = 0;
PORTD.F7 = 0; break;

case 2 : PORTD.F4 = 0;
PORTD.F5 = 1;
PORTD.F6 = 0;
PORTD.F7 = 0; break;

case 3 : PORTD.F4 = 0;
PORTD.F5 = 1;
PORTD.F6 = 1;
PORTD.F7 = 0; break;

case 4 : PORTD.F4 = 0;
PORTD.F5 = 0;
PORTD.F6 = 1;
PORTD.F7 = 0; break;

case 5 : PORTD.F4 = 0;
PORTD.F5 = 0;
PORTD.F6 = 1;
PORTD.F7 = 1; break;

case 6 : PORTD.F4 = 0;
PORTD.F5 = 0;
PORTD.F6 = 0;
PORTD.F7 = 1; break;

case 7 : PORTD.F4 = 1;
PORTD.F5 = 0;
PORTD.F6 = 0;
PORTD.F7 = 1; break;
}

Delay_ms(500);// delay entre cada paso


}//while
while(1);

} //~! main

viernes, 23 de abril de 2010

Programador de micros


Para programar el microcontrolador utilizamos el master-prog, el cual puedes conseguir en www.mercadolibre.com a un costo de aproximadamente 450 pesos. Y este programador viene con un CD que incluye varios compiladores y lo necesario para empezar a desarrollar aplicaciones (excepto los micros).

microcontrolador


Eh aquí el esquemático del microcontrolador pic16f877 que utilizamos para ajustar la posición de los motores a pasos. Los 4 bits menos significativos se conectan a las bobinas del motor, (el cómo movemos los motores se agregó anteriormente, hay que destacar que ese código está en C, utilizando el compilador mikroC.) el potenciometro se utiliza para sensar la posición en la que se encuentra el motor, o en este caso en que dirección apunta la pistola de paint balls.