jueves, 31 de octubre de 2013

MUESTREO DE SEÑALES

El siguiente programa tiene como objetivo mostrar una forma de realizar el muestreo de señales analógicas para sistemas de control digital, haciendo uso del timer0, interrupción por desbordamiento, el uso del ADC en modo free running, ademas de utilizar el UART para capturar los datos por medio de un programa externos como SCILAB, MATLAB o mediante hiperterminal.

DESCRIPCIÓN:

El timer realiza una interrupción por desbordamiento cada 800 microsegundos, una vez realizada entrado a la interrupción se lee el canal ADC0  y se guarda en una variable char sin signo, posteriormente se envia a través de la UART la cual esta configurada con un baud rate de 19200, sin paridad, enviando 8 bits de datos, con dos bits de stop.

El programa se compone del programa principal ademas de dos librerías para el control de la UART y el ADC los cuales agregare al final para que puedan descargarlos junto con su simulación en proteus.

Alguna duda pueden preguntar en los comentarios

Aquí les muestro el programa principal

/*
 * COMUNICATION2MEGA.c
 *
 * Created: 27/10/2013 12:31:42
 *  Author: NEBURESS.KYLL
 */
#ifndef F_CPU
#define F_CPU 8000000UL // XTAL de 8 MHz
#endif
#include <avr/io.h>
#include "InitADC.h"
#include "UARTAiNit.h"
#include <avr/interrupt.h>
#define bitclear(sfr,bit)(_SFR_BYTE(sfr)&=~(_BV(bit)))
#define bitset(sfr, bit)(_SFR_BYTE(sfr) |= (_BV(bit)))
#define togglebit(sfr,bit)(_SFR_BYTE(sfr)^=(_BV(bit)))

ISR(TIMER0_COMPA_vect){
//ADC y RS232
unsigned char n;
n=convADC();
TransmiteUART0(n);

/*LA ULTIMA PARTE ES PARA OBSERVAR EL FUNCIONAMIENTO DEL ADC SI DESEA PUEDE QUITAR ESTA PARTE*/
if (n>140) bitset(PORTB,PORTB0);
else bitclear(PORTB,PORTB0);
}

void TEMPORIZADOR(){
//PREESCALER DEL TIMER0 A 64
bitclear(TCCR0B,CS02);
bitset(TCCR0B,CS01);
bitset(TCCR0B,CS00);
//DESCONECTAR OC0A
bitclear(TCCR0A,COM0A1);
bitclear(TCCR0A,COM0A0);
//MODO CTC
bitclear(TCCR0B,WGM02);
bitset(TCCR0A,WGM01);
bitclear(TCCR0A,WGM00);
OCR0A=99;
}

void INTERRUPCION(){

bitset(TIMSK0,OCIE0A);
sei();
}

int main(void)
{

bitset(DDRB,DDB0);
TEMPORIZADOR();
INTERRUPCION();
initializeUART0(19200,0,8,2,2);
canalADC(0);
initADC(2,1,5);

    while(1)
    {
        //TODO:: Please write your application code



    }
}


Posteriormente publicare el programa donde podrán observar los datos obtenidos mediante el software scilab.

Les agrego el link de un archivo que hace mención sobre consideraciones que se deben tomar a la hora de seleccionar un capacitor bypass, considero que es de gran ayuda que lo lean debido a su importancia en el desarrollo de practicas donde se deben de compensar ruido y descompensaciones  dentro de los circuitos que son fallos frecuentes dentro de la ingeniería.

LINK CAPACITORES BYPASS

http://www.intersil.com/content/dam/Intersil/documents/an13/an1325.pdf

LINK PROGRAMA

https://mega.co.nz/#!41MHnKzT!EfPiuwr67CZeioVq5VBgMXbYJXA4aOQSJeHCbORGwcg





miércoles, 30 de octubre de 2013

CONTROL DE SERVOMOTOR CON TIMER1


A continuación el siguiente programa mostrara una manera sencilla de controlar un servomotor con ayuda de un potenciometro y el uso de los timers 0 y 1.

DESCRIPCIÓN:

El timer0 realizara una interrupción cada 32,7 ms aproximadamente para lo cual se utilizo el timer en modo normal con lo cual realizara la lectura del canal 0 del ADC y el resultado de la conversión la almacenara en OCR1A con lo que el servo motor cambiara de posición así como su velocidad. El timer1 esta configurado para que el pin PB1 controle al servomotor proporcionando una frecuencia de 50Hz y un ancho de pulso variable determinado por el potenciometro.

Al final agregare el link para que puedan descargar el programa y su simulación.

/*
 * servo_timer1.c
 *
 * Created: 30/10/2013 14:23:13
 *  Author: NEBURESS.KYLL
 */


#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 8000000UL // XTAL de 8 MHz
#endif
#include <avr/interrupt.h>
#define bitclear(sfr,bit) (_SFR_BYTE(sfr)&=~(_BV(bit)))
#define bitset(sfr,bit) (_SFR_BYTE(sfr) |= (_BV(bit)))
#define togglebit(sfr,bit) (_SFR_BYTE(sfr)^=(_BV(bit)))

unsigned char SERVO_VEL(){

//LEER
bitset(ADCSRA,ADSC);
while(!(ADCSRA&&(1<<ADIF))){}
return ADCH;
}
//interrupción cada 32.7ms
ISR(TIMER0_OVF_vect)
{
//MUEVE MOTOR
    OCR1A=SERVO_VEL();
}
//inicializacion del timer0
void initimer0(){
//PREESCALAMIENTO 1024
bitset(TCCR0B,CS02);
bitclear(TCCR0B,CS01);
bitset(TCCR0B,CS00);
//MODO NORMAL
bitclear(TCCR0B,WGM02);
bitclear(TCCR0A,WGM01);
bitclear(TCCR0A,WGM00);

TCNT0=0;
}
//habilitación de la interrupción del timer0 en modo normal
void interrupcion(){

bitset(TIMSK0,TOIE0);
sei();
}


//habilitación de fast pwm para control de servomotor
void PWM(){
//SALIDA NO INVERTIDA FAST PWM
bitset(TCCR1A,COM1A1);
//FAST PWM
bitset(TCCR1B,WGM13);
bitset(TCCR1B,WGM12);
bitset(TCCR1A,WGM11);
//PREESCALER 64
bitset(TCCR1B,CS11);
bitset(TCCR1B,CS10);
ICR1=2499;
}
//habilitación de canal 0 del ADC
void INITADC(){
//FUENTE DE VOLTAJE
bitclear(ADMUX,REFS1);
bitset(ADMUX,REFS0);
//CANAL 0
bitclear(ADMUX,MUX3);
bitclear(ADMUX,MUX2);
bitclear(ADMUX,MUX1);
bitclear(ADMUX,MUX0);
//JUSTIFICADO A LA DERECHA
bitset(ADMUX,ADLAR);
//PREESCALER DE 64
bitset(ADCSRA,ADPS2);
bitset(ADCSRA,ADPS1);
//HABILITAR ADC
bitset(ADCSRA,ADEN);
}

int main(void)
{
bitset(DDRB,DDB1);
interrupcion();
initimer0();
INITADC();
PWM();

    while(1)
    {
   
    }
}

LINK

https://mega.co.nz/#!818nmTRC!dfNNvToziWGWHdZaeFjG4AhruecWmCZxs2PDdyVcDDQ

TIMER0

A continuación se hará mención del uso de una parte importante de los micro controladores, y es el uso de los timers, en este caso del timer0 en modo CTC.

La razón de presentar este ejemplo es por su gran utilidad al realizar operaciones debido a que hace uso de la interrupción de comparación con el registro OCR0A con lo cual el código dentro de la interrupción se ejecuta independientemente del resto.

EXPLICACIÓN:

El código realiza una interrupción cada 1 mili segundo y realiza la operación de cambiar el estado lógico de la salida PB0, que en este caso es un led que conmuta su estado cada vez que se genera la interrupción.


Al finalizar agregare el link para que puedan descargar la simulación y el programa


/*
 * TIMER_0.c
 *
 * Created: 22/09/2013 11:57:06
 *  Author: NEBURESS.KYLL
 */


#include <avr/io.h>
#include <avr/interrupt.h>
#define clearbit(sfr,bit)(_SFR_BYTE(sfr)&=~(_BV(bit)))
#define setbit(sfr, bit)(_SFR_BYTE(sfr) |= (_BV(bit)))
#define togglebit(sfr,bit)(_SFR_BYTE(sfr)^=(_BV(bit)))

ISR(TIMER0_COMPA_vect){
//Se ejecuta cada 1ms
togglebit(PORTB,PB0);

}
void TEMPORIZADOR(){
//PREESCALER DEL TIMER0 A 64
clearbit(TCCR0B,CS02);
setbit(TCCR0B,CS01);
setbit(TCCR0B,CS00);
//DESCONECTAR OC0A
clearbit(TCCR0A,COM0A1);
clearbit(TCCR0A,COM0A0);
//MODO CTC
clearbit(TCCR0B,WGM02);
setbit(TCCR0A,WGM01);
clearbit(TCCR0A,WGM00);
OCR0A=124;
}
//habilitación de la interrupción por coincidencia
void INTERRUPCION(){

setbit(TIMSK0,OCIE0A);
sei();
}

int main(void)
{
   
TEMPORIZADOR();
INTERRUPCION();
setbit(DDRB,DDB0);
setbit(PORTB,PB0);

    while(1)
    {
        //TODO:: Please write your application code

    }
}

LINK

https://mega.co.nz/#!818nmTRC!dfNNvToziWGWHdZaeFjG4AhruecWmCZxs2PDdyVcDDQ


ADC E INTERRUPCIONES


En el uso de microcontroladores es común realizar para diversas practicas en ingeniería el poder tomar datos del exterior y con ellos realizar operaciones para controlar diversos sistemas principalmente discretos debido a la tendencia actual hacia el uso de la tecnología.

Para este caso se hizo el uso del microcontrolador ATMEGA48

El siguiente programa realiza un muestreo del canal ADC0 y muestra el resultado en el puerto B el resultado de la conversión se ha justificado a la izquierda para una resolución de 8 bits los cuales son mas que suficientes para este ejemplo, ademas de usar las interrupciones INT0 e INT1 para cambiar el estado de dos leds que cambiaran de estado según la configuración que se le de a los bits de EICRA de nuestro microcontrolador, en este caso INT1 hará cambiar a PD5 de estado con cualquier cambio de estado e INT0 cambiara de estado a PD4 con un flanco de bajada.

El programa se subdividió en funciones para que hacerlo mas legible, ademas de que se añadieron las siguientes macros para una mejor comprensión del funcionamiento del código:

#define bitclear(sfr,bit)(_SFR_BYTE(sfr)&=~(_BV(bit)))
#define bitset(sfr, bit)(_SFR_BYTE(sfr) |= (_BV(bit)))
#define togglebit(sfr,bit)(_SFR_BYTE(sfr)^=(_BV(bit)))

A continuación se muestra el código  y la simulacion en PROTEUS 7.7
Si tienen alguna duda con mucho les  gusto responderé.


/*
 * ADCandINTERRUPT.c
 *
 * Created: 28/09/2013 14:06:51
 *  Author: NEBURESS.KYLL
 */


#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define bitclear(sfr,bit)(_SFR_BYTE(sfr)&=~(_BV(bit)))
#define bitset(sfr, bit)(_SFR_BYTE(sfr) |= (_BV(bit)))
#define togglebit(sfr,bit)(_SFR_BYTE(sfr)^=(_BV(bit)))

ISR(INT0_vect){

togglebit(PORTD,PD4);
_delay_ms(300);

}

ISR(INT1_vect){

togglebit(PORTD,PD5);
_delay_ms(300);

}
//configuración de las interrupciones
void INTERRUPCIONES(){

//HABILITAR INTERRUPCIONES
bitset(EIMSK,INT0);
bitset(EIMSK,INT1);

//INT1 CUALQUIER CAMBIO LOGICO
bitclear(EICRA,ISC11);
bitset(EICRA,ISC10);
//INT0 FLANCO DE BAJADA
bitset(EICRA,ISC01);
bitclear(EICRA,ISC00);
//habilitación de interrupción general
sei();
}
//configuración del ADC
void iniADC(){
//VOLTAJE DE REFERENCIA AVCC
bitclear(ADMUX,REFS1);
bitset(ADMUX,REFS0);
//JUSTIFICACION A LA DERECHA
bitset(ADMUX,ADLAR);
//SELECCION DE CANAL
bitclear(ADMUX,MUX3);
bitclear(ADMUX,MUX2);
bitclear(ADMUX,MUX1);
bitclear(ADMUX,MUX0);
//PREESCALAMIENTO 128 F_CPU/128=f_cpuADC
bitset(ADCSRA,ADPS2);
bitset(ADCSRA,ADPS1);
bitset(ADCSRA,ADPS0);
//HABILITAR ADC
bitset(ADCSRA,ADEN);
}

//declaración de salidas
void salidas()
{
//SALIDA DEL ADC
bitset(DDRB,DDB0);
bitset(DDRB,DDB1);
bitset(DDRB,DDB2);
bitset(DDRB,DDB3);
bitset(DDRB,DDB4);
bitset(DDRB,DDB5);
bitset(DDRB,DDB6);
bitset(DDRB,DDB7);
//SALIDAS DE LAS INTERRUPCIONES
bitset(DDRD,DDD4);
bitset(DDRD,DDD5);

}

int main(void)
{
INTERRUPCIONES();
iniADC();
salidas();
    while(1)
    {
        //TODO:: Please write your application code
bitset(ADCSRA,ADSC);
while((ADCSRA&&(1<<ADIF))==0){}
PORTB=ADCH;
    }
}