Control de motor por PWM timer 0 en AVR-GCC y control de sentido de giro usando interrupciones externas en ATmega32U4

Ver el tema anterior Ver el tema siguiente Ir abajo

Control de motor por PWM timer 0 en AVR-GCC y control de sentido de giro usando interrupciones externas en ATmega32U4

Mensaje por maigke el Dom 30 Mar 2014 - 20:39

Very Happy  Very Happy  Very Happy  Very Happy  Very Happy 
Bien quiero hacer un pequeño aporte de este lado de AVR, el siguiente código muestra como controlar la velocidad de un motor de corriente directa a través del circuito L293 usando PWM, el compilador usado es AVR-GCC, con el IDE CodeBlocks, sobre una caja Manjaro Linux 0.8.9 x64, para descargar el .hex generado se usa la aplicación EasyDFU. a Continuación el código fuente:
Código:
/*
 *
*/
#define F_CPU 8000000L

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <clk.h>
#include <timer0/timer0.h>



#define start 0
#define pstart PORTB
#define stop 1
#define pstop PORTB
#define Vplus 4
#define pVplus PORTD
#define Vminus 6
#define pVminus PORTD

typedef enum {FALSE, TRUE} boolean ;
boolean Derecha = TRUE;
unsigned char velocidad=0;

ISR(INT0_vect)
{
    Derecha = FALSE;
}


ISR(INT1_vect)
{
    Derecha = TRUE;
}


void M_adelante(unsigned char pwm);
void M_reversa(unsigned char pwm);
void motor_init(void);
void setVelocidad(void);
void board_init(void);


int main(void)
{

    // Insert code
    _init_Teensyduino_internal_();
    delay_ms(100);
    velocidad = 0;
    motor_init();
    board_init();

    while(1)
    {
        if((bit_is_clear(pstart,start) && bit_is_set(pstop,stop))== TRUE)
        {
            while(bit_is_set(pstop,stop))
            {
                while(Derecha == FALSE && bit_is_set(pstop,stop))
                {
                    setVelocidad();
                }
                while(Derecha == TRUE && bit_is_set(pstop,stop))
                {
                    setVelocidad();
                }
            }
        }
    }

    return 0;
}

void M_adelante(unsigned char pwm)
{
    OCR0A = 0;
    OCR0B = pwm;
}

void M_reversa(unsigned char pwm)
{
    OCR0A = pwm;
    OCR0B = 0;
}

void motor_init()
{
    //Configure para salida PWM Inversa
    //Ajuste OCxx en Comparacion, limpia el timer en sobreflujo
    //Contador desde 0 hasta 255
    //Ciclo de reloj 8MHz Prescalamiento = 1
    timer0_setup(3,1,3,3);

    //inicializa todos los PWM al 0% de ciclo de trabajo
    OCR0A = OCR0B = 0;

    //Ajusta los pines PWM como salidas digitales
    DDRD |= (1<<DDD0);
    DDRB |= (1<<DDB7);
}

void setVelocidad(void)
{
    if(bit_is_clear(pVplus,Vplus) == TRUE)
    {
        delay_ms(20);
        velocidad++;
    }
    if(bit_is_clear(pVminus,Vminus)== TRUE)
    {
        delay_ms(20);
        velocidad--;
    }
}

void board_init(void)
{
    DDRB &= ~(1<<PB0);
    DDRB &= ~(1<<PB1);
    DDRD &= ~(1<<PD4);
    DDRD &= ~(1<<PD6);
    DDRD &= ~(1<<PD1);
    DDRD &= ~(1<<PD2);

    //Habilitando las pullups
    PORTB |= (1<<PB0); //start
    PORTB |= (1<<PB1); //stop
    PORTD |= (1<<PD4); //Vplus
    PORTD |= (1<<PD6); //Vminus
    PORTD |= (1<<PD1); //Derecha
    PORTD |= (1<<PD2); //Izquierda

}

Las librerías utilizadas son las siguientes

Libreria para ajustes del prescalamiento del reloj de sistema
Código:
#ifndef CLK_H
#define CLK_H
/**
@defgroup atmega32u4_clk Prescaler_Macros
@code #include <clk.h> @endcode

@brief Macros para definir la frecuencia de oscilacion del reloj
principal
*/

/*@{*/

/**
 *  @name  Definitions for MCU Clock Frequency
 *  Adapt the MCU clock frequency in Hz to your target.
 *  Revisa las paginas 37-39
 */


#define F_CPU 8000000L  /**< Macro para definir la FCPU a usar*/

#if F_CPU == 16000000L
#define ADC_PRESCALER 0x07  /**<Factor de division 128  F_ADC = 125kHz*/
#define CPU_PRESCALER 0x00
#elif F_CPU == 8000000L
#define ADC_PRESCALER 0x06  /**<Factor de division 64   F_ADC = 125kHz*/
#define CPU_PRESCALER 0x01
#elif F_CPU == 4000000L
#define ADC_PRESCALER 0x05  /**<Factor de division 32*/
#define CPU_PRESCALER 0x02
#elif F_CPU == 2000000L
#define ADC_PRESCALER 0x04  /**<Factor de division 16*/
#define CPU_PRESCALER 0x03
#elif F_CPU == 1000000L
#define ADC_PRESCALER 0x03  /**<Factor de division 8*/
#define CPU_PRESCALER 0x04
#else
#error "Teensyduino only supports 16, 8, 4, 2, 1 MHz.  Please edit boards.txt"
#endif


/**
 *  @name Functions
 */


/**
 @brief    Funcion para inicializar los tiempos en el ATMega32U4
 @param    none
 @return   none
*/

void _init_Teensyduino_internal_(void);

void delay_ms(unsigned int time_ms);

/*@}*/
#endif  //end clk.h


El fuente del archivo
Código:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "clk.h"


void _init_Teensyduino_internal_(void)
{

        cli();
        CLKPR = 0x80;
        _delay_us(10);
        CLKPR = CPU_PRESCALER;
}

void delay_ms(unsigned int time_ms)
{
    unsigned int i;
    for(i=0; i<time_ms; i++)
        _delay_ms(1);
}

Las librerias para la configuración del timer 0

Código:
/**
@code #include <timer0.h> @endcode

@brief
Rutina para la configuración del timer 0 de 8 bits
Este temporizador cuenta con 8 modos de operación clasificados en 4 grupos

* Normal                                        modo{0}
* CTC (limpia a la captura)                     modo{2}
* Fast PWM                                      modo{3,7}
* PWM de Fase Correcta                          modo{1,5}
*
*/

#ifndef TIMER0_H_INCLUDED
#define TIMER0_H_INCLUDED

/**
 *  @name  Definicion para la variable byte
 *  para usar en lugar de unsigned char
 */
#define byte uint8_t /**< definición del tipo de dato byte */


/**
 *  @name Functions
 */

/**
 @brief    Ajusta los valores del temporizador 0 para sus diferentes modo y activacion
           de las terminales externas de comparación
 @param    mode Se refiere uno de los siete modos de operacion del timer
 @param    prescale Se refiere al valor de ṕrescalamiento para el temporizador
 @param    outmode_A Se refiere al comportamiento que pueden tener los bits de comparacion
           del modulo A
 @param    outmode_B Se refiere al comportamiento que pueden tener los bits de comparacion
            del modulo B
 @return   none
*/
void timer0_setup(byte mode, int prescale, byte outmode_A, byte outmode_B);

#endif // TIMER0_H_INCLUDED

y el fuente para la libreria de configuración del timer0
Código:
#include <avr/io.h>
#include "timer0.h"

void timer0_setup(byte mode, int prescale, byte outmode_A, byte outmode_B)
{
    mode&=7;
    outmode_A&=3;
    outmode_B&=3;
    byte clock_mode = 0;

    switch(prescale)
    {
        case 1: clock_mode = 1; break;
        case 8: clock_mode = 2; break;
        case 64: clock_mode = 3; break;
        case 256: clock_mode = 4; break;
        case 1024: clock_mode = 5; break;
        default:
            if(prescale < 0)
                clock_mode = 7;
    }

    TCCR0A = (outmode_A << 6) | \
             (outmode_B << 4) | \
             (mode & 0x03);
    TCCR0B = ((mode & 0x04)<<1) | (clock_mode);
}

El circuito queda definido de la siguiente manera



Saludos desde México
avatar
maigke
Asiduo del Foro
Asiduo del Foro

Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 39
Localización : Mexico

Volver arriba Ir abajo

Ver el tema anterior Ver el tema siguiente Volver arriba

- Temas similares

 
Permisos de este foro:
No puedes responder a temas en este foro.