Está en la página 1de 7

Informe de laboratorio N 3

Laboratorio 3 Microcontrolador (MCU): Conversin Anlogo-Digital (Octubre 2012)


Germn F. Crdenas y Christopher A. Flores, Ingeniera Civil Biomdica, DIE Profesor: Miguel E. Figueroa Ayudante: Enrique I. Germany

Resumen Se implementar en el laboratorio la conversin digital de los voltajes generados por ngulos de un acelermetro, cuyo proceasamiento se realizar en un microcontrolador ATmega64. Dichos ngulos se visualizarn a travs de 4 displays 7 segmentos nodo comn. Se trabajar en cuatro modos: El primero representar el rango en que se encuentran los tres ngulos simultneamente, mientras que en los otros tres, se podr visulaizar el valor de cado uno. Adems 3 motores servo, darn informacin del ngulo entregado por el acelermetro

II. OBJETIVOS -Programar un MCU Atmel ATmega64 en lenguaje C -Familiriarizarse con la utilizacin de Timers, para generar interrupciones peridicas -Familiriarizarse con la utilizacin de ondas PWM, para controlar la posicin angular de un servomotor -Desplegar la informacin en los visores de 7 segmentos, utilizando barrido

III. COMPONENTES Y EQUIPOS Palabras claves acelermetro, PWM Atmega64, diplay 7 segmentos, - Microcontrolador Atmel ATmega 64 - Cable alimentacin microcontrolador - Protoboard - 1 Push-button N.A - 10 Cable JTAG -4 transistores PNP -4 resistencias 1 [k] -Cable USB - 4 display 7 segmentos nodo comn -Acelermetro ADXL335 -3 potencimetros 1 K -3 servomotores - Cables -Alicates -Multmero -Ordenador -Software AVR Studio -Software AVR Programmer

I. INTRODUCCIN

n microcontrolador es un dispositivo programable. Posee una Unidad Central de Procesamiento (CPU), memoria y perifricos de entrada/salida. El MCU utililizar en el laboratorio es el Atmel ATmega 64, que posee las siguientes caractersticas: Reloj de hasta 16 [MHz], 64 [Kb] de flash de programa, 2 [Kb] de EEPROM de datos, 4 [Kb] de RAM, registros generales (32) y especializados, entre otros, pudiendo ser programado en lenguaje C, assembly (bajo nivel) o Basic. Una interrupcin es un llamado a procedimiento que afecta el actual estado de trabajo del MCU para ejecutar una nueva funcin. En el laboratorio, se utilizarn interrupciones de trmino del proceso de conversin anlogo-digital para desplegar en pantalla el valor (voltaje) ingresado al MCU por un acelermetro. Adems, se utilizarn interrupciones peridicas por timmer, para todos los delays. A continuacin se muestran los resultados obtenidos en el laboratorio.

IV. MATERIALES YMTODO -Simular programa Assembly en Proteus -Montar en protoboard displays correspondientes y el push botton -Cargar en MCU el programa -Encender el MCU y verificar funcionamiento

Informe de laboratorio N 3 V. DESARROLLO A.1 Solucin propuesta El sistema constar con cuatro estados que sern intercambiados por la accin de un botn. El sistema comenzar en el primer modo, donde se podr visualizar en 4 displays el rango del ngulo correspondiente a cada entrada del conversor. Para ello, se har uso de una estrucutra (lenguaje C) que almacena los rangos en hexadecimal. Los dems modos entregarn informacin del valor del ngulo en forma individual para cada entrada. Para su conversin, se utilizar una fmula que entregar directamente el valor del ngulo, dependiendo del voltaje suministrado por el acelermetro. Dos interrupciones afectarn al programa: Trmino de conversin y timmers (delays). Finalmente, tres motores servo, entregarn informacin fsica de los ngulos suministrados por el acelermetro. En primera instancia, se trabajarn con potencimetros, una vez que el circuito funcione correctamente, se proceder a reemplazarlos por el acelermetro. Se muestra un esquema general de funcionamiento:

Se definen los prototipos de las funciones, para luego desarrolarlas al trmino del loop principal, para tener una mejor organizacin del cdigo. Adems se definen vectores que almacenan los valores decimales u de rangos, que permiten la conversin de los voltaje suminsitrados por el acelermetro. //=========================================== ==================== void init_boton (void); //Prototipo inicia boton uint8_t procesa_boton (void); //Prototipo prcesamiento boton void init_display (void); //Prototipo inicia display void display (uint8_t bcd1, uint8_t bcd0); //Prototipo display void init_conversor(void); //Prototipo inicia conversor void modos (void); //Prototipo modos void display2(uint8_t bcd2); //Protoipo display modo1, visorA void display1(uint8_t bcd1); //Protoipo display modo1, visorC void display0(uint8_t bcd0); //Protoipo display modo1, visorD uint8_t promedio1(uint8_t vector[256]); //Prototipo promedio const uint8_t BCD_7seg[] = { (Tabla) 0xC0, // 0 0xF9, // 1 0xA4, // 2 0xB0, // 3 0x99, // 4 0x92, // 5 0x82, // 6 0xF8, // 7 0x80, // 8 0x90, // 9 0x88, // A 0x83, // B 0xC6, // C 0xA1, // D 0x86, // E 0x8E // F }; //Estructura almacena digitos

Fig.1 Esquema funcionamiento programa

A.2 Cdigo Se definen las libreras a utilizar //=========================================== ==================== #include <avr/io.h> //Libreria AVR #define F_CPU 8000000UL //Frecuencia micro #define REBOTE 2 #define ESPERA 10 #include <util/delay.h> //Librea timmer #include <avr/interrupt.h> //Librera interrupciones #include <math.h> //Librera funciones matemticas

const uint8_t BCD_MODO1[] = { 0x00, 0x01, 0x23, 0x63, 0x77, 0x7f, 0xff, 0xf7, 0xe3,

Informe de laboratorio N 3 0xa3, 0x81, 0x80 }; //=========================================== ==================== uint8_t i; uint8_t contador = 1; Esta seccin de cdigo es anterior al loop principal del programa y se ejecuta una sola vez. Aqu se inicializan los botones, el conversor y los displays. Adems se activan las interrupciones. int main(void) { init_display(); //Display configurado init_boton(); //Boton configurado init_conversor(); //Conversor configurado sei(); //Interrupciones activadas //INCIALIZACION DISPLAY void init_display (void) { DDRA = 0xff; //Puerto A es salida DDRC = 0xff; //Puerto C es salida DDRD = 0xff; //Puerto D es salida }

En esta seccin de cdigo, se inicializa el conversor, configurando el puerto F como entrada //INCIALIZACION CONVERSOR void init_conversor(void) { DDRF = 0x00; //Puerto F es entrada conversor ADCSRB = 0x00; } //LECTURA BOTON uint8_t procesa_boton(void) { static uint8_t boton = 0x00; boton <<=1; boton |= (PINB & 0x01); boton &= 0x03; if (boton == 0x02) contador = contador +1; else contador = contador; if (contador==5) { contador = 1; } } //MUESTRA DISPLAY MODOS 2,3 Y 4 void display (uint8_t bcd1, uint8_t bcd0) { PORTA = BCD_7seg[bcd1]; PORTC = BCD_7seg[bcd0]; } //MUESTRA DISPLAY MOD01, VISOR A void display2(uint8_t bcd2) { PORTA = BCD_MODO1[bcd2]; } //MUESTRA DISPLAY MOD01, VISOR C void display1(uint8_t bcd1) { PORTC = BCD_MODO1[bcd1]; } //MUESTRA DISPLAY MOD01, VISOR D void display0(uint8_t bcd0) { PORTD = BCD_MODO1[bcd0]; }

Esta seccin de cdigo corresponde al loop principal. Se lee el botn, para detectar si fue pulsado o no. Para el primer caso, se incrementa un contador, que est incializado en 1, de esta forma, el programa, comienza en el modo 1. Luego, el programa retorna al loop principal, para acceder a los distintos modos., segn el contador. while(1) { //Loop [f(0) = 1/x]

procesa_boton(); //Llama a botn _delay_ms(REBOTE); //Espera 5 ms antirrebote modos(); _delay_ms(ESPERA); //Espera 10 ms conversion } } //=========================================== ========================================= En esta seccin de cdigo, se inicializa el botn, configurando el puerto B como entrada //INCIALIZACION BOTON void init_boton (void) { DDRB = 0x00; //Puerto B es entrada PORTB = 0xff; //Activa pull ups } En esta seccin de cdigo, se inicializan los displays, configurando el puerto A, C y D como salida. Sin embargo, esto ser modificado para el barrido (slo puerto A).

Informe de laboratorio N 3 En esta seccin de cdigo se selecciona el modo segn el contador. //SELECCIN MODOS Y CONVERSOR void modos (void) { if (contador == 1) { //modo1 return promedio; }

Al trmino de cada conversin se llama a la funcin mostrar en displays y luego vuelve al estado anterior. //INTERRUPCIN FIN CONVERSION ISR(ADC_vect) { uint8_t angle = asin((ADCH-127.5)/127.5); uint8_t temporal = angle; uint8_t digit0 = (temporal & 0x0F); // Obtener los 4 bits menos significativos de la conversin uint8_t digit1 = (temporal >> 4) & 0x0F; // Obtener los 4 bits mas significativos de la conversin uint8_t buffer[128]; for(i=0;i<128;i++) { buffer[i] = ADCH; } uint8_t tmp = promedio1(buffer); if(tmp>=0 && tmp <21) tmp = 0; if(tmp>=21 && tmp <42) tmp = 1; if(tmp>=42 && tmp <63) tmp = 2; if(tmp>=63 && tmp <84) tmp = 3; if(tmp>=84 && tmp <105) tmp = 4; if(tmp>=105 && tmp <126) tmp = 5; if(tmp>=126 && tmp <147) tmp = 6; if(tmp>=147 && tmp <168) tmp = 7; if(tmp>=168 && tmp <189) tmp = 8; if(tmp>=189 && tmp <210) tmp = 9; if(tmp>=210 && tmp <231) tmp = 10; if(tmp>=231 && tmp <=255) tmp = 11; if (contador==1) //MODO 1 { if(ADMUX == 0b01100000) //canal1 en modo1 { display0(tmp);

ADMUX = 0b01100000; ADCSRA = 0b11011111; _delay_ms(ESPERA); ADMUX = 0b01100001; ADCSRA = 0b11011111; _delay_ms(ESPERA); ADMUX = 0b01100010; ADCSRA = 0b11011111; _delay_ms(ESPERA); } if (contador == 2) //modo2 { ADMUX = 0b01100000; ADCSRA = 0b11011111; } if (contador == 3) //modo3 { ADMUX = 0b01100001; ADCSRA = 0b11011111; } if (contador == 4) //modo4 { ADMUX = 0b01100010; ADCSRA = 0b11011111; } } La funcin promedio, tiene como argumento el buffer de datos que es llenado por el ADCH y retorna el promedio de dichos valores. //PROMEDIO MODO 1 uint8_t promedio1(uint8_t vector[]) { uint16_t suma=0; uint8_t promedio; for (i=0;i<128;i++) { suma = vector[i]+suma; } promedio = suma/128;

Informe de laboratorio N 3 } if(ADMUX == 0b01100001) //canal2 en modo1 { display1(tmp); } if(ADMUX == 0b01100010) //canal3 en modo1 { display2(tmp); } } if (contador>1 && contador<=4) //MODO 2, 3 y 4 { display(digit1, digit0); // Desplegar dgitos en los displays } } void init_displays( void ) { DDRC = 0xFF; // Puerto C es salida. Diplay ms significativo DDRA = 0xFF; // Puerto A es salida. Diplay menos significativo }

void displayDigits( uint8_t bcd1, uint8_t bcd0 ) { PORTA = BCD_7seg[bcd1]; //Busca en estructura BCD PORTC = BCD_7seg[bcd0]; //Busca en estrucutra BCD }

void incDigits( uint8_t *pbcd1, uint8_t *pbcd0) { if( *pbcd0 != 9 ) // Si dgito menos significativo no ha llegado a 9 (mximo) { (*pbcd0)++; // Incrementar normalmente } else // Dgito mas significativo lleg a 9 (mximo) { (*pbcd0) = 0; // volverlo a 0 // Realizar lo mismo, pero con el dgito mas significativo if (*pbcd1 != 9) { (*pbcd1)++; } else (*pbcd1) = 0; } } void init_boton (void) { DDRG = 0x00; // Puerto G es entrada botn PORTG = 0xFF; // Pull-ups activos }

A.3 Cdigos de prueba

Cdigo hecho en clases despliega en display BCD, tras la accin de un push botton #include <avr/io.h> //Librera AVR #define F_CPU 8000000UL //Frecuencia MCU #include <util/delay.h> //Librera timmer #define DELAY 5 //Delay antirrebote //Crear tabla de conversin //Estructura BCD const uint8_t BCD_7seg[] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E };

uint8_t proc_boton( void ) //Procesa boton { // Inicializar variable (solo una vez): Botn no presionado (estado anterior) static uint8_t boton = 0x01;

// Realizar desplazamiento a la izquierda // Estado anterior del botn queda almacenado en el segundo bit de "boton" boton <<= 1;

Informe de laboratorio N 3 // Leer bit 0 del puerto G y hacer un OR con la variable "boton" // Almacena estado actual del botn en primer bit de la variable "boton" boton |= (PING & 0x01); // Descartar los 6 bits mas significativos (solo los 2 menos significativos interesan) boton &= 0x03; // Retornar 1 solo si botn no estaba presionado, y ahor lo est (1b...10) if( boton == 0x02 ) return 1; // Retornar 0 en otro caso; Botn no presionado, o ya lo estaba return 0; } #define PW_MIN 500 // ancho de pulso mnimo es 500us con div. por 8 #define PW_MAX 2000 // ancho de pulso mximo es 2ms con div. por 8 int main(void) { TCCR0 = 0b00000100; // FOC0 = 0; WGM01:0 = 00 (normal); COM01:0 = 00 (OC0 desconectado); // CS02:1 = 100 (f/64)--> 8us/tic, perodo 2.048ms TIMSK = 0b00000001; // OCIE0 = 0; TOIE0 = 1; habilitar interr. por overflow DDRB |= _BV(5) | _BV(6) | _BV(7); OC1C (PB5, PV6, PB7) salidas OCR1A = PW_MIN; OCR1B = PW_MIN; OCR1C = PW_MIN; ICR1 = TOP; TCCR1A = 0b10101010; TCCR1B = 0b00011010; TCCR1C = 0; DDRF = 0x00; conectores servo) sei(); while (1) { } return 1; } ISR(TIMER0_OVF_vect) { static uint8_t contador = 0; contador++; if (contador > (50/2.048)) { contador = 0; ADMUX = 0b01100000; // REFS1:0 = 01: ref. es AVCC; ADLAR = 1: ajuste izquierda; Canal 0 seleccionado ADCSRA = 0b11001111; // ADEN=1; ADC habilitado, ADSC=1: iniciar conversin, } } ISR(ADC_vect) { uint32_t angulo = PW_MIN + ((uint32_t)ADCH*(PW_MAX-PW_MIN))/255; if ((ADMUX & 0x03) == 0) { OCR1A = angulo; ADMUX = 0b01100001; // REFS1:0 = 01: ref. es AVCC; ADLAR = 1: ajuste izquierda; Canal 0 seleccionado ADCSRA = 0b11001111; // ADEN=1; ADC habilitado, ADSC=1: iniciar conversin,

// OC1A, OC1B,

int main(void) { uint8_t bcd1 = 0, bcd0 = 0; init_displays(); //Inicializa display init_boton(); //Inicializa boton displayDigits( bcd1, bcd0 ); // Desplegar digitos por primera vez while( 1 ) { if( proc_boton() ) // Si se ha presionado el botn { // Incrememntar cuenta incDigits( &bcd1, &bcd0 ); // Desplegar nueva cuenta displayDigits( bcd1, bcd0 ); } // Esperar (antirebote) _delay_ms( DELAY ); } return 1; } Cdigo hecho acciona un motor sevo, dependiendo del valor ingresado por conversor

// Puerta F es entrada (ADC y

#include <avr/io.h> #include <avr/interrupt.h> #define TOP 20000 // perodo es de 20ms con un divisor por 8

Informe de laboratorio N 3 } else if ((ADMUX & 0x03) == 1) { OCR1B = angulo; ADMUX = 0b01100010; // REFS1:0 = 01: ref. es AVCC; ADLAR = 1: ajuste izquierda; Canal 0 seleccionado ADCSRA = 0b11001111; // ADEN=1; ADC habilitado, ADSC=1: iniciar conversin, } else if ((ADMUX & 0x03) == 2) { OCR1C = angulo; } } VI. CONCLUSIN

Los microcontroladores (MCU) son de gran utilidad a la hora de implementar circuitos digitales o analgicos, previo uso de conversores A/D. Su fundamento se basa en el estudio del lenguaje a utilizar, sea ste el C, assembly, Basic, entre otros. La diferencia radica en la cercana (nivel) con el microcontrolador, lo que se traducir en el grado de control. En el caso del lenguaje Assembly se tiene un mayor control bit a bit de los registros a utilizar, lo que logra un aprovechamiento eficiente de los recursos del MCU. Sin embargo,el lenguaje C, permite una mayor fluidez de cdigo, ya que muchas funciones ya estn implementadas (timmers).

A.4 Implementacin de circuito VII. REFERENCIAS El circuito a implementar consiste en 4 displays conectados en paralelo al puerto A del microcontrolador, cuya activacin ser mediante barrido. Para ello, se utilizarn 4 transistores PNP, cuyas bases sern activadas por l puerto C. Adems un push button, conectado en el puerto B, controlar los cambios de modo. Finalmente, 3 motores servo, entregarn informacin del acelermetro conectado en el puerto F. [1] Laboratorio de microcontroladores: Gua de laboratorio N 3, Universidad de Concepcin, Departamento de Ingeniera Elctrica, 2011, pp 1-3

Fig.2 Circuito a implementar en laboratorio