Mostrando entradas con la etiqueta PWM. Mostrar todas las entradas
Mostrando entradas con la etiqueta PWM. Mostrar todas las entradas

domingo, 23 de marzo de 2014

SISTEMA DE CONTROL CON LABVIEW Y MICROCONTROLADOR AVR

                                   A continuación se presentara el funcionamiento de un programa realizado en un microcontrolador AVR con ayuda del software LABVIEW, para el control de motores y la recepción de la distancia medida por un sensor ultrasonico. Esto se explicara con detalle principalmente en cuanto al microcontrolador dejando a LABVIEW debido a su fácil manejo aclarando solo en funcionamiento en general.



DESCRIPCIÓN:

MICROCONTROLADOR:


ISR(TIMER1_CAPT_vect):

                                  Esta rutina de interrupción realiza la medición de la distancia realizada por el sensor ultrasonico esto lo realiza activando entrada por captura del comparador analógico y configurándolo para realizar la interrupción cuando surja un flanco de bajada.

COMPARADOR():

                                   Configura el comparador analógico para utilizar AIN1 como entrada negativa y habilita la captura de entrada.

TEMPORIZADOR():

                                          Configura el TIMER1 con un preescalamiento de 64, en modo normal y detección de flanco de bajada de entrada de captura.

ISR(USART_RX_vect):

                                          Esta sección del codigo realiza prácticamente lo mismo realizado en el codigo presentado del control de motor con el software MYOPENLAB con la excepción del apagado y encendido de un led y que en logar de enviar el valor leído en el potenciometro se envía la distancia detectada.

ISR (USART_RX_vect)

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

unsigned char velocidadad(unsigned char unidad)

ULTRASONICO(unsigned char valor):

                                            Esta función realiza la selección del carácter correspondiente a las unidades, decenas y centenas capturadas por el sensor ultrasonico.

unsigned char ULTRASONICO(unsigned char valor)

MAIN:

                                         En esta función se incializan las funciones e  interrupciones con las que trabajara nuestro programa.

WHILE(1):

                                        En este ciclo se lee continuamente el la distancia medida por el sensor ultrasonico y se realiza el control del ancho de pulso del TIMER2 para controlar un motor, teniendo un ciclo de trabajo mayor cuando detecta distancias pequeñas.


LABVIEW:

                                        El programa envía tres datos de control, el primero es el estado en el que se encontrara el motor y el segundo la velocidad a la que se desplazara. El ultimo dato enciende o apaga un led.
                                 
                                            La comunicación realizada con el protocolo RS232 se configuro de la siguiente forma:


  • BAUDRATE 9600
  • DATOS 8 BITS
  • PARIDAD NONE
  • BITS DE STOP 2
  • TIMEOUT 2 SEGUNDOS
  • SIN CONTROL DE FLUJO

                            La recepción de datos se realiza mediante la conversión de de cadena a entero indicando los bits que se recibirán, los cuales para esta ocasión son 3 mas el dato de terminación de cadena, siendo presentados en un indicador gráfico y un display para conocer el valor numérico de la distancia medida por el sensor ultrasonico.


NOTA:
                            Alguna duda o recomendación puede ingresarla en los comentarios para así mejorar los programas y la explicación de los mismos, ademas si desean que se presenta algún programa coloque lo en los comentarios se hará lo posible por presentarlo. El link de los programas se deja al final para que pueda descargarlos.

PROGRAMA:

/*
 * PRACTICA_VIERNES.c
 *
 * Created: 19/03/2014 18:27:16
 *  Author: TERRAFORMARS
 */ 
/*
 * 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 <ctype.h>
#include "UARTAiNit.h"
#include "TIMER0.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},potenciometro[5]={0},vel1[3]={0};
unsigned int PERIODO=0,PERIODO_ANTERIOR=0,PERIODO_REAL=0;
unsigned char DIST=0,dist1[4]={0},DISTANCIA[4]={0},D=0;


unsigned char velocidadad(unsigned char unidad);
//ultrasonico

ISR (TIMER1_CAPT_vect){
//LEER DATO GUARDADO EN ICR1

if (i==0)//IDENTIFICACION DE LECTURA INICIAL
{
PERIODO_ANTERIOR=ICR1;
setbit(TCCR1B,ICES1);//SE CAMBIA LA CONFIGURACION DE INTERRUPCION POR UN FLANCO DE SUBIDA
setbit(TIFR1,ICF1);//SE SETA LA BANDERA DE INTERRUPCION PARA EVITAR QUE SE DISPARE NUEVAMENTE LA INTERRPCION
//DE FORMA INPREVISTA
i=1;
}
else//IDENTIFICACION DE LECTURA FINAL
{
PERIODO=ICR1;
clearbit(TCCR1B,ICES1);//SE CAMBIA LA SELECCION DE INETERRUPCION POR UN FLANCO DE BAJADA
if (PERIODO>PERIODO_ANTERIOR)//SI EL VALOR LEIDO ES SUPERIOR AL VALOR PRECEDENTE REALIZAR LA SUSTRACCION DE
{                            //FORMA NORMAL
PERIODO_REAL=PERIODO-PERIODO_ANTERIOR;
}
else                         //SI EL VALOR LEIDO ES INFERIOR AL VALOR PRECEDNTE SUMAR 65536 A LA RESTA PARA
{                            //OBTENER EL NUMERO REAL
PERIODO_REAL=65536+PERIODO-PERIODO_ANTERIOR;
}

PERIODO_REAL=(PERIODO_REAL)/58;//DISTANCIA EN CENTIMETROS
setbit(TIFR1,ICF1);//SE SETEA LA BANDERA DE INTERRUPCION POR CAPTURA PARA EVITAR QUE SE DISPARE UNA INTERRUPCION

if (PERIODO_REAL>=255)//SI EL DATO LEIDO ES MAYOR O IGUAL A 255 SE ASIGANA 255 A LA VARIABLE PERIODO_REAL
{
PERIODO_REAL=255;
}
DIST=(unsigned char)PERIODO_REAL;
i=0;
}

}


//CONFIGURAR COMPARADOR ANALOGICO
void COMPARADOR(){

//ENTRADA NEGATIVA AIN1
setbit(ADCSRB,ACME);
setbit(ADCSRA,ADEN);

//HABILITAR CAPTURA DE ENTRADA DEL COMPARADOR ANALOGICO
setbit(ACSR,ACIC);

}

//CONFIGURACION DE TIMER1
void TEMPORIZADOR(){
//CONFIGURACION DE PREESCALAMIENTO 64
clearbit(TCCR1B,CS12);
setbit(TCCR1B,CS11);
clearbit(TCCR1B,CS10);
//CONFIGURACION DE MODO DE GENERADOR DE FORMA DE ONDA
//MODO NORMAL
clearbit(TCCR1B,WGM13);
clearbit(TCCR1B,WGM12);
clearbit(TCCR1A,WGM11);
clearbit(TCCR1A,WGM10);


//FLANCO DE BAJADA DE ENTRADA DE CAPTURA
clearbit(TCCR1B,ICES1);
}



//motores 
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,PB0);
COMPAREA_FASTB(2);
clearbit(PORTD,PD4);
break;
case 3:
//MOTOR DERECHA
setbit(PORTB,PB0);
COMPAREA_FASTB(3); 
setbit(PORTD,PD4);
break;
case 2:
//MOTOR STOP
clearbit(PORTB,PB0);
velocidad=3;
break;
}
if (tempo==1||tempo==2||tempo==3)
{
//CAMBIO DE VELOCIDAD
OCR0B=velocidad;
}
//borrar();
//ENVIAR EL VALOR DE LA DISTANCIA LEIDA
for (l=0;l<3;l++)
{
TransmiteUART0(DISTANCIA[l]);
}
//ENVIAR CARACTER PARA SEPARAR DISTANCIAS MEDIDAS
TransmiteUART0(10);

}

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

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

    //VELOCIDAD
for(i=0;i<4;i++){

b[i]=a[i];
}

for (i=0;i<2;i++)
{
vel0[i]=b[i+1];
}
if (b[3]=='1'){setbit(PORTD,PD3);}
else if (b[3]=='0'){clearbit(PORTD,PD3);}

for(i=0;i<2;i++){
    vel1[i]=velocidadad(vel0[i]);
}
velocidad=16*vel1[1]+vel1[0];
     
if (velocidad==0){velocidad=4;}
if (velocidad>=253){velocidad=252;}
/////////////////////

}

unsigned char velocidadad(unsigned char unidad){

switch(unidad){

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;
case 'A':
v3=10;
break;
case 'B':
v3=11;
break;
case 'C':
v3=12;
break;
case 'D':
v3=13;
break;
case 'E':
v3=14;
break;
case 'F':
v3=15;
break;
}
return v3;
}



unsigned char ULTRASONICO(unsigned char valor){

switch(valor){

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


//MAIN

int main(void)
{
//MODO FAST PWM
setbit(TCCR2B,CS22);
setbit(TCCR2B,CS21);
setbit(TCCR2B,CS20);
TCCR2A|=(1<<WGM20);
TCCR2A|=(1<<WGM21);
TCCR2B&=~(1<<WGM22);
setbit(TCCR2A,COM2A1);
setbit(DDRB,DDB3);
setbit(DDRB,DDB1);
setbit(PORTB,PB1);
setbit(DDRD,DDD3);
    COMPARADOR();
TEMPORIZADOR();
initializeUART0(9600,0,8,2,2);
initTIMER0_FAST1();
PREESCALL(5);
COMPAREA_FASTB(2);
setbit(DDRD,DDD2);
setbit(DDRD,DDD4);
setbit(DDRD,DDD5);
clearbit(PORTD,PD4);
setbit(DDRB,DDB0);
//HABILITAR INTERRUPCION POR ENTRADA DE CAPTURA
setbit(TIMSK1,ICIE1);
setbit(UCSR0B,RXCIE0);
sei();
    while(1)
    {
  //TODO:: Please write your application code
  //INICIAR LECTURA
  setbit(PORTD,PD2);
  _delay_ms(15);
  clearbit(PORTD,PD2);
  _delay_ms(80);
  //SEPARAR CENTENAS, DECENAS Y UNIDADES

  dist1[0]=DIST/100;
  dist1[1]=(DIST-100*dist1[0])/10;
  dist1[2]=(DIST-100*dist1[0]-10*dist1[1]);
  dist1[3]=48; 
  if (DIST<=3)
  {
 DIST=3;
  } 
  else if(DIST>=252)
  {
 DIST=252;
  }
  OCR2A=255-DIST;
  for(l=0;l<3;l++){
DISTANCIA[l]=ULTRASONICO(dist1[l]);

  }


    }

}




VÍDEO:



IMÁGENES:

PROGRAMA EN ATMEL STUDIO:


SIMULACIÓN EN ISIS PROTEUS:


PANEL FRONTAL DE LABVIEW:


DIAGRAMA DE BLOQUES DE LABVIEW:


SIMULACIÓN EN LABVIEW:




LINK:

MICROCONTROLADOR:
https://mega.co.nz/#!4k0RBRaQ!3TsDdXf8647Q0oDEYQsoNVpNEd1-FKSA-iZqLzDjJp0

LABVIEW:
https://mega.co.nz/#!slNFVTiT!HKLXTBAlcg8rhfmdEIs2PvyLM4TDjzmt8pKHyzbLnCs




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