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




domingo, 9 de marzo de 2014

RELOJ CON MICROCONTROLADOR AVR

                          El siguiente programa a realizar se trata sobre la implementación de un reloj mostrado en displays de siete segmentos de cátodo común donde ademas de mostrar hora, minutos y segundos se agrego la capacidad de cambiar horas y minutos con ayuda de las interrupciones INT0 e INT1. Ademas de todo esto se agrego un botón el cual dependiendo su estado (HIGH o LOW), incrementa o decrementa  las horas y minutos cada vez que se cambien con las interrupciones correspondientes.

DESCRIPCIÓN:

                            Se comenzara ha explicar el programa en el orden en el que se encuentra dando a mencionar primero lo que realizan las interrupciones y después se explicará lo que realizan las funciones y el programa principal.


ISR(INT0_vect):

                           Cada vez que se genera una interrupción esta rutina realiza el incremento/decremento de horas dependiendo del estado del pin PB7 el cual determina lo que realizará la función, ademas identifica si el valor de la variable horas es igual a cero no decrementa su valor.

if (bit_is_clear(PINB,PINB7))
{
if (horas>0){ horas--; }
else
{
    horas++;
if (horas==24){ horas=0; }
}

ISR(INT1_vect):

                           Cada vez que se genera una interrupción esta rutina realiza el incremento/decremento de minutos dependiendo del estado del pin PB7 el cual determina lo que realizará la función, ademas identifica si el valor de la variable minutos es igual a cero no decrementa su valor.

ISR(INT1_vect){
if (bit_is_clear(PINB,PINB7))
{
if (minutos>0){ minutos--; }
}
else
{
minutos++;
if (minutos==60){ minutos=0; horas++; }
}
}

ISR(TIMER1_COMPA_vect):

                            En la siguiente sección del programa se realiza el incremento de las variables segundos, minutos y horas cada vez que surge una interrupción debido a la comparación del registro OCRIA y el registro TCNT1 lo cual sucede cada 1 segundo.

TCNT1=0; 
segundos++;

                             Cada vez que la interrupción sucede se reinicia el registro TCNT1 para que vuelva a contar. En seguida se incrementa la variable segundos y se pregunta con las funciones if el valor de dicha variable, si su valor es de 60 entonces se incrementa la variable minutos y se limpia segundos.

if (segundos==60)
{
minutos++;
segundos=0;
}

                             Cuando el valor de la variable minutos es igual a 60 se incrementa el valor de horas y se limpia el contenido de minutos.

if (minutos==60)
{
    horas++;
minutos=0;
 
}

                           Para finalizar se pregunta si la variable horas es igual a 24 de ser así se le asigna el valor 0.

if (horas==24)
{
horas=0;
}

INTERRUPCIÓN_CAMBIO:

                           Esta función habilita las interrupciones INT0 e INT1 del registro EIMSK, configurando la interrupción en flanco de bajada con los bits ISC11 e ISC01 del registro EICRA, ademas habilita las resistencias de pull-up y limpia las banderas de interrupción para que no se disparen de forma aleatoria.

setbit(PORTD,PD3);
setbit(PORTD,PD2);

//FLANCO DE BAJADA DE LA INTERRUPCION
setbit(EICRA,ISC01); 
setbit(EICRA,ISC11);
//PINES DE CAMBIO HORA Y MINUTO
setbit(EIMSK,INT1);
setbit(EIMSK,INT0);
setbit(EIFR,INTF0);
setbit(EIFR,INTF1);

TEMPORIZADOR:

                            Esta función configura el TIMER1 en modo CTC en particular el modo 4 con los bits WGM13:10, del registro TCCR1A. Se selecciono un preescalamiento de 256 con los bits CS12:10 del registro TCCR1B y se le asigno el valor 31249 al registro OCR1A para que la interrupción surja cada 1 segundo. Para finalizar se habilito la interrupción por comparación.

//MODO CTC WGM13:0 = 4
clearbit(TCCR1A,WGM13);
setbit(TCCR1A,WGM12);
clearbit(TCCR1A,WGM11);
clearbit(TCCR1A,WGM10);
//PREESCALER
setbit(TCCR1B,CS12);
clearbit(TCCR1B,CS11);
clearbit(TCCR1B,CS10);
//COMPARACION CADA 1 SEGUNDO
OCR1A=31249;
    setbit(TIMSK1,OCIE1A);

UNIDADES_DECENAS:

                                En esta sección se separan las unidades y decenas correspondientes de las variables segundos, minutos y horas. Son guardadas en nuevas variables que serán utilizadas para presentar los datos en los displays de siete segmentos.

dec_seg=segundos/10;
uni_seg=segundos-10*dec_seg;
dec_min=minutos/10;
uni_min=minutos-10*dec_min;
dec_hor=horas/10;
uni_hor=horas-10*dec_hor;

MAIN:

                                    Se declara el pin PB7 como entrada y se habilita su resistencia del pull-up, se realiza la configuración de INT0 e INT1 y del TIMER1 y las salidas que serán conectadas a los dispalys y se habilita la interrupción global.                        

clearbit(DDRB,DDB7);
setbit(PORTB,PB7);
INTERRUPCION_CAMBIO();
initDisplay();
temporizador();
sei();

WHILE(1):

                                    Este bucle realiza la presentación de las horas, minutos y segundos mediante lo siguiente:


  • Se determina el valor de las unidades y decenas de los segundo, minutos y horas con la función UNIDADES_DECENAS();                        
  • Primero coloca en HIGH el bit que se encontraba en LOW para no ser presentado en el display conectado en ese pin.
  • Se determina el valor que se presentara en el display correspondiente.
  • Se pone en LOW el pin conectado a ese display para visualizar su contenido.
  • Espera 2 milisegundos.
  • realiza lo mismo hasta presentar las dec_hor donde volverá a inicio del bucle.



UNIDADES_DECENAS();
//UNIDADES SEGUNDOS
setbit(Pdisp_6,disp_6);
salida_7seg(uni_seg);
clearbit(Pdisp_1,disp_1);
_delay_ms(retencion);
//DECENAS SEGUNDOS
setbit(Pdisp_1,disp_1);
salida_7seg(dec_seg);
clearbit(Pdisp_2,disp_2);
_delay_ms(retencion);
//UNIDADES MINUTOS
setbit(Pdisp_2,disp_2);
salida_7seg(uni_min);
clearbit(Pdisp_3,disp_3);
_delay_ms(retencion);
//DECENAS MINUTOS
setbit(Pdisp_3,disp_3);
salida_7seg(dec_min);
clearbit(Pdisp_4,disp_4);
_delay_ms(retencion);
//UNIDADES HORAS
setbit(Pdisp_4,disp_4);
salida_7seg(uni_hor);
clearbit(Pdisp_5,disp_5);
_delay_ms(retencion);
//DECENAS HORAS
setbit(Pdisp_5,disp_5);
salida_7seg(dec_hor);
clearbit(Pdisp_6,disp_6);
_delay_ms(retencion);

NOTA: 

                         Al final se colocara el link del programa y su simulación en proteus para que puedan descargarlo. Alguna duda o sugerencia puede ingresarla en los comentarios para que podamos realizar programas de su interés.

PROGRAMA:

/*
 * RELOJ.c
 *
 * Created: 09/03/2014 17:40:37
 *  Author: TERRAFORMARS
 */ 


#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 8000000UL // XTAL de 8 MHz
#endif
#include <avr/interrupt.h>
#include "7_segmentos.h"
#include <util/delay.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))
#define retencion 2

unsigned char segundos=0,minutos=0,horas=0,uni_seg,uni_min,uni_hor,dec_seg,dec_min,dec_hor;

ISR(INT0_vect){
if (bit_is_clear(PINB,PINB7))
{
if (horas>0){ horas--; }

else
{
   horas++;
if (horas==24){ horas=0; }
}

}
ISR(INT1_vect){
if (bit_is_clear(PINB,PINB7))
{
if (minutos>0){ minutos--; }
}
else
{
minutos++;
if (minutos==60){ minutos=0; horas++; }
}
}


ISR(TIMER1_COMPA_vect){
TCNT1=0; 
segundos++;
if (segundos==60)
{
minutos++;
segundos=0;
}

if (minutos==60)
{
   horas++;
minutos=0;
 
}

if (horas==24)
{
horas=0;

}

}

void INTERRUPCION_CAMBIO(){
setbit(PORTD,PD3);
setbit(PORTD,PD2);

//FLANCO DE BAJADA DE LA INTERRUPCION
setbit(EICRA,ISC01); 
setbit(EICRA,ISC11);
//PINES DE CAMBIO HORA Y MINUTO
setbit(EIMSK,INT1);
setbit(EIMSK,INT0);
setbit(EIFR,INTF0);
setbit(EIFR,INTF1);

}
//CONFIGURACION DE TIMER1
void temporizador(){
//MODO CTC WGM13:0 = 4
clearbit(TCCR1A,WGM13);
setbit(TCCR1A,WGM12);
clearbit(TCCR1A,WGM11);
clearbit(TCCR1A,WGM10);

//PREESCALER
setbit(TCCR1B,CS12);
clearbit(TCCR1B,CS11);
clearbit(TCCR1B,CS10);
//COMPARACION CADA 1 SEGUNDO
OCR1A=31249;
    setbit(TIMSK1,OCIE1A);
};

void UNIDADES_DECENAS(){
dec_seg=segundos/10;
uni_seg=segundos-10*dec_seg;

dec_min=minutos/10;
uni_min=minutos-10*dec_min;

dec_hor=horas/10;
uni_hor=horas-10*dec_hor;

}

int main(void)
{
clearbit(DDRB,DDB7);
setbit(PORTB,PB7);
INTERRUPCION_CAMBIO();
initDisplay();
temporizador();
sei();

    while(1)
    {
        //TODO:: Please write your application code 
UNIDADES_DECENAS();
//UNIDADES SEGUNDOS
setbit(Pdisp_6,disp_6);
salida_7seg(uni_seg);
clearbit(Pdisp_1,disp_1);
_delay_ms(retencion);
//DECENAS SEGUNDOS
setbit(Pdisp_1,disp_1);
salida_7seg(dec_seg);
clearbit(Pdisp_2,disp_2);
_delay_ms(retencion);
//UNIDADES MINUTOS
setbit(Pdisp_2,disp_2);
salida_7seg(uni_min);
clearbit(Pdisp_3,disp_3);
_delay_ms(retencion);
//DECENAS MINUTOS
setbit(Pdisp_3,disp_3);
salida_7seg(dec_min);
clearbit(Pdisp_4,disp_4);
_delay_ms(retencion);
//UNIDADES HORAS
setbit(Pdisp_4,disp_4);
salida_7seg(uni_hor);
clearbit(Pdisp_5,disp_5);
_delay_ms(retencion);
//DECENAS HORAS
setbit(Pdisp_5,disp_5);
salida_7seg(dec_hor);
clearbit(Pdisp_6,disp_6);
_delay_ms(retencion);

    }
}


VÍDEO:




IMÁGENES:

SIMULACIÓN EN ISIS PROTEUS:


PROGRAMA EN ATMEL STUDIO:


LINK:

https://mega.co.nz/#!V4kClC5Q!B5Q-CudJuH_Qr-dFyc-kOLpBPidvTYJimHP4SINOcIE