domingo, 31 de agosto de 2014

USO DE MODULO ADC CON ATTINY85

                      A continuación se presentara un programa simple del uso del modulo ADC en microcontroladores tinyAVR en concreto a la serie Attinyx5, esto con el fin de demostrar su funcionamiento y compatibilidad con los microcontroladores megaAVR. Esto se hará utilizando la librería InitADC.h que ha sido de utilidad en programas realizados con ayuda del microcontrolador Atmega48.

DESCRIPCIÓN:

                                  En primer lugar se configurar la velocidad de reloj del CPU esto con el fin de saber de antemano cual sera nuestra frecuencia de reloj en un principio, evitando así dificultades al realizar programas que requieran conocer la frecuencia de reloj precisa. 

#ifndef F_CPU
#define F_CPU 8000000UL // XTAL de 8 MHz
#endif

Se introduce la librería del modulo ADC y las macros para el control de los bits de registro.

#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))

                                   Declaramos la variable donde se guardara e contenido de la lectura de nuestro ADC, el cual utilizara el pin PB2 para realizar la lectura. En este caso se utilizara el voltaje Vcc como referencia conectado a AREF.

//CONFIGURAR ADC
initADC(2,1,5);         //configuración de modulo ADC..(refrencia Vcc en AREF,justificado, prees. 32 )
canalADC(1);           //pin PB2 como canal de entrada
SALIDAS
setbit(DDRB,DDB4);
setbit(DDRB,DDB3);

WHILE(1):

                                Primeramente se lee el canal seleccionado y se guarda su valor en la variable analógico tipo unsigned char, para posteriormente encender y/o apagar los leds que se encuentran conectados en PB3 y PB4 con forme se incrementa o decrementa el valor de la señal en PB2.

analogico=convADC();
if (analogico>=0&&analogico<=63)
{
clearbit(PORTB,PB4);
clearbit(PORTB,PB3);
}
else if (analogico>=64&&analogico<=127)
{
clearbit(PORTB,PB4);
setbit(PORTB,PB3);
}
else if (analogico>=128&&analogico<=191)
{
setbit(PORTB,PB4);
clearbit(PORTB,PB3);
}
else if (analogico>=192&&analogico<=255)
{
setbit(PORTB,PB4);
setbit(PORTB,PB3);
}


NOTA:

                           Para mas información sobre el uso de la librería, recomiendo observar los programas anteriores, recomiendo la entrada ADC y salida binaria con int1, alguna duda o sugerencia puede dejarla en los comentarios contestare sus solicitudes en cuanto pueda, ademas dejare el programa al final para que puedan descargarlo.

PROGRAMA:

/*
 * ADC_ATTINY.c
 *
 * Created: 31/08/2014 15:52:58
 *  Author: TERRAFORMARS
 */ 


#ifndef F_CPU
#define F_CPU 8000000UL // XTAL de 8 MHz
#endif
#include <avr/io.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 analogico;

int main(void)
{
//CONFIGURAR ADC
initADC(2,1,5);         //configuración de modulo ADC..(refrencia Vcc en AREF,justificado, prees. 32 )
canalADC(1);           //pin PB2 como canal de entrada
SALIDAS
setbit(DDRB,DDB4);
setbit(DDRB,DDB3);
while(1)
{
//TODO:: Please write your application code
analogico=convADC();
if (analogico>=0&&analogico<=63)
{
clearbit(PORTB,PB4);
clearbit(PORTB,PB3);
}
else if (analogico>=64&&analogico<=127)
{
clearbit(PORTB,PB4);
setbit(PORTB,PB3);
}
else if (analogico>=128&&analogico<=191)
{
setbit(PORTB,PB4);
clearbit(PORTB,PB3);
}
else if (analogico>=192&&analogico<=255)
{
setbit(PORTB,PB4);
setbit(PORTB,PB3);
}
//termina else
}
}

IMÁGENES:

EJECUCIÓN EN ATMEL STUDIO


SIMULACION EN PROTEUS



FUNCIONAMIENTO







LINK:

https://mega.co.nz/#!RklDzZrA!SXuRPqgMMzijhCsrvvTAv6FcI_kj7joTQ3xCaqseQoY




jueves, 17 de abril de 2014

CONFIGURACION DE MICROCONTROLADOR CON CRYSTAL 20 MHZ Y USART

                        A continuación se presentara un programa básico de comunicación entre un microcontrolador AVR, en específico un ATMEGA48 y una computadora con el fin de mostrar una aplicación sencilla utilizando un cristal externo de 20 MHz para utilizar un baud rate superior al que se utiliza con el resonador interno de 8 MHz.


DESCRIPCIÓN:

                   Lo primero que se describirá será la configuración del reloj con el que trabajara nuestro microcontrolador, posteriormente se describirá el circuito y el programa, para finalizar se mostraran imágenes del funcionamiento.

CONFIGURACIÓN DE FUSES:

                   Primeramente se decide los parámetros de funcionamiento con las que funcionara nuestro microcontrolador.

FUSE HIGH BYTE
·         External reset
·         debugWIRE enable
·         Enable serial program and
data downloading
·         Watchdog timer always on
·         EEPROM memory is
preserved through the chip
erase.
·         Brown-out detector trigger
level.

FUSE LOW BYTE
·         Divide clock by 8
·         Clock output
·         Select start-up time
·         Select clock source

                      Para la configuración de fuse high se configura como DC con lo que queda de la siguiente manera:

·         1: External reset
·         1: debugWIRE enable
·         0: Enable serial program and
data downloading(programed)
·         1: Watchdog timer always on
·         1: EEPROM memory is
preserved through the chip
erase.
·         100: Brown-out detector trigger
level.(4.3V typ).

                        Para la configuración de fuse low se determinó como D7:

·         1: Divide clock by 8.(programed)
·         1: Clock output.
·         01:Select start-up time
·         1001: Select clock source

                           Con esta configuración podrá utilizarse el cristal externo de 20 MHz con un bod level de 4.3V, sin preescalamiento, sin salida de reloj, con un retraso de inicio de 14 CK.

CIRCUITO:
                           El circuito se conforma de dos partes principales, el microcontrolador y el MAX232. El microcontrolador realiza la toma de decisiones de acuerdo a los datos recibidos permitiendo con esto cambiar el estado de dos leds conectado a PB1 y PB0 dependiendo del dato enviado por la computadora.
                            La parte que se desea destacar es la conexión del cristal de 20 MHz con dos capacitores de 22 pF para estabilizar la frecuencia, este cristal se conectara en PB6 y PB7.


MICROCONTROLADOR:

                            En este caso primeramente se define la frecuencia de reloj como 20 MHz y el baudrate con la que en realidad trabajara nuestro microcontrolador, en este caso será de 115200 en el programa en circuito físico y 38400 en simulación esto es ya que el componente COMPIM solo admite hasta 57600. De no definirse se tomara por defecto una velocidad de reloj de 20 MHz y un baud rate de 38400, esto estará definido en la librería que establecerá la comunicación.


#define F_CPU 20000000UL
#define BAUD 115200

                            
                              En seguida se agregara nuestra librería para realizar la comunicación.

#include "UART0_setbaud.h"

                            A continuación se agrega la cabecera de interrupciones, las macros para el control de los registros y una variable.

#include <avr/interrupt.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 volatile dato;

ISR(USART_RX_vect):

                              Dentro de la rutina de servicio de interrupción se tomara la decisión mediante funciones if la acción que se realizara.

  dato=RECIBIR();

                                 Dentro del primer if se cambiara el estado en que se encuentra el pin PB0 esto si se ha ingresado los valores 3, 6 o 9 mediante el teclado. En el segundo if se cambia el estado actual del pin PB1 si se ingresan los caracteres 1, 5 u 8.

  if(dato=='3'||dato=='6'||dato=='9'){
           bittoggle(PORTB,PB0);
  }else if(dato=='1'||dato=='5'||dato=='8'){
           bittoggle(PORTB,PB1);
  }

                               Para finalizar se reenvía el numero recibido para que el usuario pueda confirmar el funcionamiento del circuito.  

 TRANSMITIR(dato);


INT MAIN:

                        Dentro de la función main se configura a PB0 y PB1 como salidas y también se configura el registro USART0 con lo siguiente:
·         Sin paridad
·         Dos bits de stop
·         8 bist de datos.

setbit(DDRB,DDB0);
setbit(DDRB,DDB1);
UART0(NONE,2,8);


                                 Se configura el bit de interrupción para la recepción de datos.

  setbit(UCSR0B,RXCIE0);
  sei();



NOTA:
                             Alguna duda o aclaración pueden ingresarla en los comentarios, al final agregare el link del programa y la simulación.




PROGRAMA:

/*
 * ECHO.c
 *
 * Created: 17/04/2014 15:00:12
 *  Author: TERRAFORMARS
 */


#include <avr/io.h>
#define F_CPU 20000000UL
#define BAUD 115200
#include "UART0_setbaud.h"
#include <avr/interrupt.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 volatile dato;

ISR(USART_RX_vect){
 
  dato=RECIBIR();
 
  if(dato=='3'||dato=='6'||dato=='9'){
           bittoggle(PORTB,PB0);
          
  }else if(dato=='1'||dato=='5'||dato=='8'){
           bittoggle(PORTB,PB1);
          
  }
 
  TRANSMITIR(dato);
}

int main(void)
{
  setbit(DDRB,DDB0);
  setbit(DDRB,DDB1);
  UART0(NONE,2,8);
 
  setbit(UCSR0B,RXCIE0);
  sei();
 
    while(1)
    {
        //TODO:: Please write your application code
          
    }
}



IMÁGENES:

EJECUCIÓN DE PROGRAMA EN PROTOBOARD:









CONFIGURACIÓN DE FUSES PARA UTILIZAR CRISTAL DE 20 MHZ.








CONEXIÓN DE CRISTAL:

CIRCUITO EN ISIS PROTEUS:


EJECUCIÓN DE PROGRAMA CON TERA TERM:





PROGRAMA EN ATMEL STUDIO:

                                     

LINK

https://mega.co.nz/#!c9sVxQQY!QZw4H0xpTWB_2VbolgRX7aydC9KP3_rU_Taf94j5Q2c

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