Control de motor por PWM timer 0 en AVR-GCC y control de sentido de giro usando interrupciones externas en ATmega32U4
Página 1 de 1.
Control de motor por PWM timer 0 en AVR-GCC y control de sentido de giro usando interrupciones externas en ATmega32U4
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
maigke- Asiduo del Foro
- Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 46
Localización : Mexico
Temas similares
» Ejemplo de Control de Un Servo Motor PIC16F690
» CONTROL PID DE UN MOTOR DC CON MICROCONTROLADOR CON INGRESO DEL SETPOINT POR teclado
» Control por DTMF
» Control de Temperatura+Comunicacion USB con 18F4550
» Control servo por USB Pinguino + PyGTK
» CONTROL PID DE UN MOTOR DC CON MICROCONTROLADOR CON INGRESO DEL SETPOINT POR teclado
» Control por DTMF
» Control de Temperatura+Comunicacion USB con 18F4550
» Control servo por USB Pinguino + PyGTK
Página 1 de 1.
Permisos de este foro:
No puedes responder a temas en este foro.