sábado, 22 de febrero de 2014

CONTROL DE MOTOR CON MYOPENLAB Y USART

ACTUALIZADO          

          A continuación se realizara la demostración del control de un motor mediante el software MyopenLab e Isis Proteus, con ayuda de Configure Virtual Serial Port Driver para la creación de los puertos virtuales. Para comenzar se explicara con detalle lo que realizara el programa en MyopenLab y el realizado en el microcontrolador AVR, así como también los componentes y configuraciones añadidas al simulado ISIS PROTEUS. 


DESCRIPCIÓN:

MICROCONTROLADOR:

                  El programa en el microcontrolador esta dividido en dos partes principales, de las cuales una es interrupción para la captura de datos enviados por el software MyopenLab, la segunda es la lectura del canal 0 del ADC para mostrar de forma gráfica la posición de un potenciometro.

                  Programa realizado en  WHILE(1)

                El programa principal lee el valor de ADC0 y lo coloca en la variable analog una vez hecho esto se guarda el valor del mismo en tres variables que indicaran centenas, decenas y unidades cada una. A continuación se asignara el valor correspondiente en ASCII a tres variables mas con ayuda de funciones que determinaran el valor que corresponde. Se enviaran los datos por el puerto serial los cuales serán captados por el programa realizado en MyopenLab y serán tratados para ser mostrados por medio de un elemento visual.

analog=convADC();

pot1=analog/100;
pot2=(analog-100*pot1)/10;
pot3=analog-100*pot1-10*pot2;
centenas_pot();
decenas_pot();
unidades_pot();

                 La razón de la conversión del dato obtenido por el convertidor analógico es debido a que el visualizador analógico no lee el valor de la forma deseada debido a que de ser enviado el dato sin realizar estas operaciones lo que lee es un carácter en ASCII el cual no pertenece a los valores validos que puede recibir por lo que la segmentación del valor y su conversión de cada dato en su equivalente en ASCII permite al programa poder leer el valor numérico de forma correcta.
                 

                  Rutina de interrupción 

                  La interrupción se generara cada vez que halla un dato sin leer en el buffer de recepción para ello son los siguientes setbit(UCSR0B,RXCIE0); sei(); esto habilita la interrupción especifica y global respectivamente.
                    La rutina de interrupción lee el dato enviado por el programa y comprueba si es un dato valido, de ser así realiza lo que indique el case correspondiente y vuelve a su función normal. 
                   Algo que aclarar es que los datos que se aceptaran son los caracteres '1', '2' y '3' los cuales en decimal son 49, 50 y 51 respectivamente.
                    Esta interrupcion realiza la lectura de cuatro cracteres enviados por el programa los cuales determinaran el estado del motor (STOP, LEFT y RIGHT) con el primer caracter recibido; los tres caracteres restantes determinaran la velocidad a la que se movera el motor o actuador. Debido que son recibidos como caracteres individuales se realiza una operacion similar a la realizada dentro del ciclo WHILE con la diferencia de que se utilizan las funciones atoi();, strcpy();, strncpy();, de las librerias:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

                        Esto es para la conversión de los caracteres recibidos en su equivalente en byte para su uso mas eficiente en la manipulación de los registros principalmente del registro OCR0A el cual determina el ancho de pulso de la señal PWM y por lo tanto la velocidad del motor

MYOPENLAB:

                    El programa realizado utiliza el componente RS232 y se configuro para conectarse con el puerto virtual COM2 para realizar la comunicación con proteus y envía un dato el cual el programa en el microcontrolador lee y con ello cambia el estado del motor conectado al driver L293B para esto se utilizo convertidores de datos y se muestra el estado del motor mediante leds ademas de poder observarse la posicion de un potenciometro conectado al pin ADC0.

ISIS:
       
                    Dentro del entorno de ISIS se modificaron los parámetros del componente COMPIM que se encuentra en la librería de componentes, este dispositivo es util para conectar el puerto virtual COM1 al microcontrolador.


                    Los parámetros seleccionados deben ser los mismos con los que se configura la comunicación en el microcontrolador para el buen funcionamiento del proyecto, de no ser así el programa no funcionara.

PUERTOS VIRTUALES:

                   Con ayuda del programa Configure Virtual Serial Port Driver se crean dos puertos virtuales, para este caso COM1 y COM2 ademas de asegurarse de que se encuentren en el modo estándar.


NOTA:

                       Al final encontrara los links para descargar tanto el programa del microcontrolador así como el realizado en MyopenLab, esto también se puede realizar en Labview si desea crear su propio programa con ayuda del realizado puede hacerlo.
                       Alguna duda o aclaración puede ingresarla en los comentarios


 /*
 * motorConCadena.c
 *
 * Created: 24/02/2014 17:14:30
 *  Author: TERRAFORMARS
 */ 


#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 8000000UL // XTAL de 8 MHz
#endif
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "UARTAiNit.h"
#include "TIMER0.h"
#include "InitADC.h"
#define setbit(sfr,bit) (_SFR_BYTE(sfr)|=(_BV(bit)))
#define clearbit(sfr,bit) (_SFR_BYTE(sfr)&=~(_BV(bit)))
#define bittoggle(sfr,bit)(_SFR_BYTE(sfr)^=_BV(bit))

unsigned char tempo=0,analog,velocidad=0,i=0,t=1,pot1,pot2,pot3,l,c;
unsigned char a[5]={0},b[5]={0},v1=0,v2=0,v3=0,temp[5]={0},vel0[3]={0},vel1[1]={0},vel2[1]={0},vel3[1]={0},potenciometro[5]={0};
unsigned int vel;
ISR (USART_RX_vect){
//RECIBIR DATO
for(i=0;i<4;i++){
a[i]=ReceiveUART0();
}

//CONVERTIR A CHAR

stringToChar();
//ESTADO DEL MOTOR
switch(tempo){

case 1:
//MOTOR IZQUIERDA
setbit(PORTB,PB1);
COMPAREA_FASTA(2);
clearbit(PORTD,PD5);
break;
case 3:
//MOTOR DERECHA
setbit(PORTB,PB1);
COMPAREA_FASTA(3);
setbit(PORTD,PD5);
break;
case 2:
//MOTOR STOP
clearbit(PORTB,PB1);
vel=65538;
break;
}
if (tempo==1||tempo==2||tempo==3)
{
//CAMBIO DE VELOCIDAD
OCR0A=vel;
}
//borrar();
}

//converir de cadena a char de 8 bits
void stringToChar(){

//ESTADO
strcpy(b,a);
strncpy(temp,b,1);
tempo=atoi(temp);

    //VELOCIDAD
strcpy(b,a);
vel1[0]=b[1];
vel2[0]=b[2];
vel3[0]=b[3];

centenas();
decenas();
unidades();

vel=v1+v2+v3;
     
if (velocidad>=256){velocidad=259;}
if (velocidad>=65534){velocidad=65530;}
/////////////////////

}

void centenas(void){

switch(vel1[0]){

case '2':
v1=200;
break;
case '3':
v1=300;
break;
case '4':
v1=400;
break;
case '5':
v1=500;
break;
}
}

void decenas(void){

switch(vel2[0]){

case '0':
v2=0;
break;
case '1':
v2=10;
break;
case '2':
v2=20;
break;
case '3':
v2=30;
break;
case '4':
v2=40;
break;
case '5':
v2=50;
break;
case '6':
v2=60;
break;
case '7':
v2=70;
break;
case '8':
v2=80;
break;
case '9':
v2=90;
break;
}
}


void unidades(void){

switch(vel3[0]){

case '0':
v3=0;
break;
case '1':
v3=1;
break;
case '2':
v3=2;
break;
case '3':
v3=3;
break;
case '4':
v3=4;
break;
case '5':
v3=5;
break;
case '6':
v3=6;
break;
case '7':
v3=7;
break;
case '8':
v3=8;
break;
case '9':
v3=9;
break;
}
}


void unidades_pot();
void decenas_pot();
void centenas_pot();
//MAIN

int main(void)
{
initADC(2,1,6);
canalADC(0);
initializeUART0(9600,0,8,2,2);
initTIMER0_FAST1();
PREESCALL(3);
COMPAREA_FASTA(2);
setbit(DDRD,DDD5);
setbit(DDRD,DDD6);
clearbit(PORTD,PD5);
setbit(DDRB,DDB1);
setbit(UCSR0B,RXCIE0);
sei();
    while(1)
    {
  
analog=convADC();

pot1=analog/100;
pot2=(analog-100*pot1)/10;
pot3=analog-100*pot1-10*pot2;
centenas_pot();
decenas_pot();
unidades_pot();
//for (c=0;c<2;c++)
//{

for (l=0;l<3;l++)
{
TransmiteUART0(potenciometro[l]);
}
//}
_delay_ms(200);
    }

}


void centenas_pot(void){

switch(pot1){

case 2:
   potenciometro[0]='2';
break;
case 1:
potenciometro[0]='1';
break;
case 0:
potenciometro[0]='0';
break;
}
}

void decenas_pot(void){

switch(pot2){

case 0:
potenciometro[1]='0';
break;
case 1:
   potenciometro[1]='1';
break;
case 2:
   potenciometro[1]='2';
break;
case 3:
   potenciometro[1]='3';
break;
case 4:
   potenciometro[1]='4';
break;
case 5:
   potenciometro[1]='5';
break;
case 6:
   potenciometro[1]='6';
break;
case 7:
   potenciometro[1]='7';
break;
case 8:
   potenciometro[1]='8';
break;
case 9:
   potenciometro[1]='9';
break;
}
}


void unidades_pot(void){

switch(pot3){

case 0:
potenciometro[2]='0';
break;
case 1:
potenciometro[2]='1';
break;
case 2:
potenciometro[2]='2';
break;
case 3:
potenciometro[2]='3';
break;
case 4:
potenciometro[2]='4';
break;
case 5:
potenciometro[2]='5';
break;
case 6:
potenciometro[2]='6';
break;
case 7:
potenciometro[2]='7';
break;
case 8:
potenciometro[2]='8';
break;
case 9:
potenciometro[2]='9';
break;
}
}




IMÁGENES:













PROGRAMA EN ATMEL STUDIO


INTERFAZ CREADA EN MYOPENLAB


SIMULACIÓN DE MAYOPENLAB E ISIS PROTEUS

MOTOR STOP


MOTOR RIGHT



 MOTOR LEFT





PROGRAMA EN ISIS PROTEUS


VÍDEO DEMOSTRATIVO DE FUNCIONAMIENTO



LINKS:

programa del microcontrolador (ACTUALIZADO)
https://mega.co.nz/#!Z4sizQaQ!GUyYZxaatlA7uQLbERorS6fiWk1gZSTm8n7V-WB7-gI

programa en MyopenLab (ACTUALIZADO)
https://mega.co.nz/#!d9twAaxa!O9iNtXYLsdidFbIfXtXeW4Jdcmy70sXYYbTltSGXGWY

si por alguna razón desean obtener los programas anteriores se encuentran a continuación.

programa del microcontrolador
https://mega.co.nz/#!48ll0ApY!YbdodDoA4tHVn70r0frRwUc4PeBTkU9kwfOJ5kWSi6k

programa en MyopenLab
https://mega.co.nz/#!cxkSzAID!clVxvzSyVH7d3e3YjQ3RlV42efhqmzK3SHbtjsPfUCA


1 comentario:

  1. hola amigo muy padre tu trabajo, mi nombre baltazar disculpa la molestia, al igual que tu uso myopenlab y rs232, pero a mi no me enlaza el puerto de comunicación, veo el com virtual del micro y en myopenlab ajusto el mismo com generado por el micro. pero no más no obtengo nada el programa del micro lo pruebo y en un monitor serial y hace lo que le pido pero no se si a myopenlab le haga falta alguna configuración

    ResponderEliminar