Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

20/12/2012 #1


Problema con interrupciones ATmega16
Bueno muchachos mi problema es basicamente el siguiente:

Estoy haciendo una banda transportadora con un motor Bipolar(conectado a un L293D y al micro) la cual debe girar tanto para izquierda como para derecha, yo pense en usar interrupciones osea que al momento de pulsar un pulsador (valga la redundancia) gira para la derecha y si pulso el otro gira a la izquierda(El motor gira mientras el pulsador este presionado)

Mi problema es que al momento de accionar el pulsador, el motor solo alcanza a dar 1 paso ya sea a la derecha o a la izquiera, mejor dicho no hace el giro completo. Quiero saber si hay una funcion la cual me garantize que un bucle se cumple siempre y cuando el pulsador este presionado u otra solucion que me permita que el motor gire. (intente generando retardos despues del llamado de la funcion duque() y nada :( )

Código HTML:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

void duque(void);  //Funcion para girar DERECHA
void duque1(void); //Funcion para girar IZQUIERDA

int main(void)
{
	DDRC=0xFF;
	MCUCR=(1<<ISC01)|(1<<ISC00)|(1<<ISC11)|(1<<ISC10); //Flanco de subida para INT0 e INT1 
	GICR=(1<<INT0)|(1<<INT1); //Habilito las interrupciones
 	sei(); 
    while(1);
}   
	
ISR(INT0_vect)
{
	duque();	//Llamo a la funcion de girar a la derecha
	GIFR=(1<<INTF0);
}

ISR(INT1_vect)	
{
	duque1();	 //Llamo a la funcion de girar a la izq
	GIFR=(1<<INTF1);	
}
	
void duque(void)  // Girar derecha
{
	PORTC=0b00001011;
	_delay_ms(5);
	PORTC=0b00010011;
	_delay_ms(5);
	PORTC=0b00010101;
	_delay_ms(5);
	PORTC=0b00001101;;
	_delay_ms(5);
}

void duque1(void) //Girar izquierda
{
	PORTC=0b00001011;
	_delay_ms(5);
	PORTC=0b00001101;
	_delay_ms(5);
	PORTC=0b00010101;
	_delay_ms(5);
	PORTC=0b00010011;
	_delay_ms(5);
}			
	
Gracias de antemano
20/12/2012 #2

Avatar de cosmefulanito04

A ver, ¿te parece bien llamar a una función desde una rutina de interrupción y si encima esa función tiene delays?

¿Que deberías hacer? usar un flag y obviamente tener muy en cuenta los posibles rebotes, para lo cual te recomiendo que una vez que se produce una interrupción, anularla momentáneamente hasta terminar con la función duque.
20/12/2012 #3


Amigo ya probe lo de los retardos antes de la funcion duque y nada sigue igual :(.

Y estaba pensando en la segunda opcion pero no se como anular la interrupcion como si hubiera una parada, amigo sera que puede ser mas especifico y si es posible un ejemplo
20/12/2012 #4

Avatar de cosmefulanito04

duke1226 dijo: Ver Mensaje
Amigo ya probe lo de los retardos antes de la funcion duque y nada sigue igual :(.
No se que modificación hiciste, sería bueno que lo subas.

duke1226 dijo: Ver Mensaje
Y estaba pensando en la segunda opcion pero no se como anular la interrupcion como si hubiera una parada, amigo sera que puede ser mas especifico y si es posible un ejemplo
Probá con algo así:

Código PHP:
....
unsigned char flag_externa0=0;
....
int main(void)
{
    
DDRC=0xFF
    
MCUCR=(1<<ISC01)|(1<<ISC00)|(1<<ISC11)|(1<<ISC10); //Flanco de subida para INT0 e INT1 // No lo verifiqué, habría que leer hoja de datos, pero me imagino que está bien
    
GICR=(1<<INT0)|(1<<INT1); //Habilito las interrupciones
     
sei(); 
    while(
1)
    {
     if(
flag_externa0)
        {
            
flag_externa0=0;
            
duque();
            
GICR|=(1<<INT0); //Habilito nuevamente la interrupción externa 0
        
}
    }
}  

ISR(INT0_vect)
{
    
flag_externa0=1;    //Cambio el estado del flag solamente!!! 
    
GICR&=~(1<<INT0); //Dehabilito la interrupción externa 0
}
... 
Eso sería un anti-rebote muuuuuuy básico, faltaría realizar un chequeo de verificación de que realmente se activó el pulsador y descartar un posible ruido, pero para probar rápido te sirve.
20/12/2012 #5


Amigo copie y pegue su codigo y mire como reacciona:

La vdd no se me ocurre que pueda estar pasando, con respecto a lo de los retardos
simplemente genere un retardo de 200ms antes de llamar la funcion duque dentro de la interrupcion.

Amigo gracias por interesarse en ayudarme
21/12/2012 #6

Avatar de cosmefulanito04

No puedo simular el L293D, debe ser que tengo una versión vieja del proteus.

Para descartar la interrupción, probá con este código bien simple:

Código PHP:
int main(void

    
DDRC=0xFF;  
   
    while(
1
    { 
            
_delay_ms(2000); //Espero 2 seg. y hago girar el motor 
            
duque();             
    } 

Fijate si el motor gira bien, en caso de no hacerlo, puede ser un problema en la secuencia de pasos.
22/12/2012 #7

Avatar de Saint_

Hola duke1226
Te comento que tienes dos problemas.
1.- el retardo que haces para cada paso del motor es muy pequeño.
2.- el cableado del motor no es el correcto o visto de otro modo la secuencia no es correcta.
Espero que con esto se solucionen tus problemas.
PD. mientras se mantenga el pulsador presionado solo dara 4 pasos y lugo se quedara estatico, en tu programa se tiene que ir oprimiendo el pulsador periodicamente para que el motor gire

Un saludo.
Archivos Adjuntos
Tipo de Archivo: rar ej_WinAvr.rar (45,9 KB (Kilobytes), 4 visitas)
22/12/2012 #8


Amigo lo que yo creo que pasa es que como configuraste el microcontrolador como flanco de subida, debes pulsar varias veces el botón para lograr el giro, pienso yo que sería mejor si configuraras el micro para niveles lógicos a cero.
Yo haría esto

Código:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

void duque(void);  //Funcion para girar DERECHA
void duque1(void); //Funcion para girar IZQUIERDA

int main(void)
{
    PORTD=(1<<PORTD2)|(1<<PORTD3) // Activar las resistencias de pull-up
        DDRC=0xFF;
    MCUCR=(0<<ISC01)|(0<<ISC00)|(0<<ISC11)|(0<<ISC10); //Nivel en bajo para INT0 e INT1 
    GICR=(1<<INT0)|(1<<INT1); //Habilito las interrupciones
     sei(); 
    while(1);
}   
    
ISR(INT0_vect)
{
    duque();    //Llamo a la funcion de girar a la derecha
    GIFR=(1<<INTF0);
}

ISR(INT1_vect)    
{
    duque1();     //Llamo a la funcion de girar a la izq
    GIFR=(1<<INTF1);    
}
    
void duque(void)  // Girar derecha
{
    PORTC=0b00001011;
    _delay_ms(5);
    PORTC=0b00010011;
    _delay_ms(5);
    PORTC=0b00010101;
    _delay_ms(5);
    PORTC=0b00001101;;
    _delay_ms(5);
}

void duque1(void) //Girar izquierda
{
    PORTC=0b00001011;
    _delay_ms(5);
    PORTC=0b00001101;
    _delay_ms(5);
    PORTC=0b00010101;
    _delay_ms(5);
    PORTC=0b00010011;
    _delay_ms(5);
}
Debes tener en cuenta que como ya se activaron las resistencias de pull-up, no es necesario colocar fue del micro dichas resistencias, basta que coloque en el pin 3 y 4 del puerto d dos pulsadores que vayan directamente a tierra. Con eso debería funcionar XD.
22/12/2012 #9

Avatar de cosmefulanito04

No digo que este mal tú lógica jdchh, pero lo que SI está mal es llamar a una función desde una interrupción y más si esa función tiene delays!.
22/12/2012 #10


Amigo cosmefulanito04, me parece que llamar funciones y con delays para este caso en particular no tiene ningún problema, la verdad no veo porque fallaría. Igual gracias por la observación.

Amigo duke1226 ya logré lo que quería, ahí le adjunto el archivo ya compilado en el AVR Studio 5.1, no se cual tenga ud igual ahí se puede mirar el código fuente para que lo copie y pegue, ademas le adjunto la simulación en Proteus!!! Que esté bn Bendiciones!!!!!!
Archivos Adjuntos
Tipo de Archivo: rar Duque.rar (43,0 KB (Kilobytes), 4 visitas)
22/12/2012 #11

Avatar de cosmefulanito04

Así como está, sin tener en cuenta el rebote, te puede pasar esto:

1- Presionas el pulsador
2- Salta la interrupción, y va a la rutina duque
3- En medio de la rutina duque seguimos estando dentro de la rutina de interrupción.... pasa 1mS .... pasan 2mS...
4- De golpe tenés un rebote y vuelve a saltar la rutina de interrupción dentro de la misma rutina de interrupción

No importa para que aplicación sea, una rutina de interrupción tiene que ser breve y concisa.

Tené en cuenta que el flag en GIFR se borra automáticamente una vez que se ejecuta la rutina de interrupción, es decir no sería necesarío limpiarlo.
22/12/2012 #12


Si es verdad, claro que si, pero si para esta aplicación no se necesita precisión en el giro del motor simplemente los rebotes harán que el motor gire un poquito mas, solo pasaría eso.
22/12/2012 #13

Avatar de cosmefulanito04

jdchh dijo: Ver Mensaje
Si es verdad, claro que si, pero si para esta aplicación no se necesita precisión en el giro del motor simplemente los rebotes harán que el motor gire un poquito mas, solo pasaría eso.
Haciendo eso, corres el riesgo de que se llame varias veces a una función (funciones anidadas) y que te quedes sin pila, osea el uC se traba.

De todas formas, habría que leer bien la hojas de datos del uC, seguro que el uC debería evitar eso, pero siempre es bueno tener una buena costumbre a la hora de programar.
22/12/2012 #14


La verdad no creo que pase eso, entiendo lo de los rebotes pero pues no creo que se vaya a trabar. Bueno esperemos haber que dice nuestro amigo duque y bueno que le haga las determinadas correciones igual estamos para ayudarnos no? Jejejej
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.