L298N y Atmega16

Hola, estoy aprendiendo microcontroladores con el atmega16 y tengo que construir un sumo que funciona con sensores digitales.
El problema es que la simulación los motores funcionan en Proteus tal cual lo esperado en el código que hice en Microchip Studio.
A la hora del montaje revisé el L298N con un Arduino UNO y respondió perfectamente (al menos con esto de los motores que es lo que más me interesa resolver primero), el Atmega16 es detectado sin problemas por el software AVRDUDE instalado en mi laptop, he revisado las conexiones muchísimas veces, pero el resultado que tengo es infructífero. Así que quería saber que consideraciones se deben tomar en cuenta en el montaje para los proyectos del Atmega16.

Adjunto el código y la simulación en un archivo .rar por si alguien me puede ayudar, ¡Muchas gracias!

PD: igual pongo también aquí el código por si algo:
C:
#include <avr/io.h>
#include <util/delay.h>
#include "lcd/lcd.h"
#include <stdlib.h>
#include <avr/interrupt.h>
#define F_CPU 16000000L

volatile uint16_t overflow_count = 0; // Variable para contar desbordamientos

int main(void)
{
    atmega_init();
    lcd_init(LCD_DISP_ON);
    char str[16];
    overline_set(); //Definición del comportamiento de INT1 e INT2
    Timer0_Init(); // Inicializar Timer0
    sei();// Habilitar interrupciones globales
    PORTA|= (1<<PA0);
    _delay_ms(5000);
    while(1){
        status_LCD();
        if (!(PINA & (1 << PA0)) && !(PINA & (1 << PA1)) && (PINA & (1 << PA3)) && (PINA & (1 << PA4))) //No detección en ningún lado
        {
            on_guard(); // Si se cumple la condición, establecer en cero los pines A5, A6, A7, B0 y B1. Luego empezará a buscar
            lcd_clrscr();
            lcd_puts("Guard Routine");
            _delay_ms(1000);
            lcd_clrscr();
        }
        else
        {
            if ((PINA & (1<<PA2)))//Detección trasera
            {
                to_B();
            }
            else
            {
                if((PINA & (1<<PA1)))//Detección frontal
                {
                    to_F();
                    lcd_clrscr();
                    lcd_puts("Front Routine");
                    _delay_ms(1000);
                    lcd_clrscr();
                }
                else
                {
                    if((PINA & ~(1<<PA3)))//Detección izq
                    {
                        to_L();
                    }
                }
            }
        }
    }
    return 0;
}

void Timer0_Init() {
    TCCR0 |= (1 << CS02) | (1 << CS00); // Prescaler de 1024
    TIMSK |= (1 << TOIE0); // Habilitar la interrupción de desbordamiento de Timer/Counter0
   
}

void on_guard(void){
    //Teniendo en cuenta que PA6 Y PB1 ya están en 0 lógico entonces:
    stop_wheels();
    PORTA |= (1 << PA7); //Pongo 1 lógico en el ENABLE y en PA7
    PORTA &= ~(1 << PA6);//Pongo 0 lógico en PA6. No entiendo porqué se pone AND, se supone que eso reescribe todo PORTA
    PORTB |= (1 << PB3); //Pongo 1 lógico en PB0
    PORTB &= ~(1 << PB1);//Pongo 0 lógico en PB1. No entiendo porqué se pone AND, se supone que eso reescribe todo PORTB
    PORTA |= (1 << PA5); //Activa el enable
}

void to_B(void) //To back side
{
    stop_wheels();
    PORTA |= (1 << PA6); //Pongo 1 lógico en el ENABLE y en PA7
    PORTA &= ~(1 << PA7);//Pongo 0 lógico en PA6. No entiendo porqué se pone AND, se supone que eso reescribe todo PORTA
    PORTB |= (1 << PB1); //Pongo 1 lógico en PB0
    PORTB &= ~(1 << PB3);//Pongo 0 lógico en PB1. No entiendo porqué se pone AND, se supone que eso reescribe todo PORTB
   
    PORTA |= (1 << PA5); //Activa el enable
}

void to_F(void) //To front side
{
    stop_wheels();
   
    PORTA |= (1 << PA6); //Pongo 1 lógico en el ENABLE y en PA7
    PORTA &= ~(1 << PA7);//Pongo 0 lógico en PA6. No entiendo porqué se pone AND, se supone que eso reescribe todo PORTA
    PORTB |= (1 << PB3); //Pongo 1 lógico en PB0
    PORTB &= ~(1 << PB1);//Pongo 0 lógico en PB1. No entiendo porqué se pone AND, se supone que eso reescribe todo PORTB
   
    PORTA |= (1 << PA5); //Activa el enable
}

void to_L(void) //To left side
{
    stop_wheels();
    PORTA |= (1 << PA7); //Pongo 1 lógico en el ENABLE y en PA7
    PORTA &= ~(1 << PA6);//Pongo 0 lógico en PA6. No entiendo porqué se pone AND, se supone que eso reescribe todo PORTA
    PORTB |= (1 << PB3); //Pongo 1 lógico en PB0
    PORTB &= ~(1 << PB1);//Pongo 0 lógico en PB1. No entiendo porqué se pone AND, se supone que eso reescribe todo PORTB
   
    PORTA |= (1 << PA5); //Activa el enable
}

void to_R(void)
{
    stop_wheels();
    PORTA |= (1 << PA6); //Pongo 1 lógico en el ENABLE y en PA7
    PORTA &= ~(1 << PA7);//Pongo 0 lógico en PA6. No entiendo porqué se pone AND, se supone que eso reescribe todo PORTA
    PORTB |= (1 << PB1); //Pongo 1 lógico en PB0
    PORTB &= ~(1 << PB3);//Pongo 0 lógico en PB1. No entiendo porqué se pone AND, se supone que eso reescribe todo PORTB
   
    PORTA |= (1 << PA5); //Activa el enable
   
   
}
void stop_wheels(void)// stop, duh
{
    PORTA &= (~(1 << PA6) | ~(1 << PA7));
    PORTB &= (~(1 << PB1) | ~(1 << PB3));
    _delay_ms(300);
}

void atmega_init(void)//Inicialización de todos los puertos del Atmega
{
    //PA1, PA2, PA3, PA4 son Sensores IR. PA5 es el ENABLE de un par de motores, y PA6,PA7 el control de estos.
    DDRA &= ~( (1 << DDA1) | (1 << DDA2) | (1 << DDA3) | (1 << DDA4) ); // Configurar pines A1, A2, A3 y A4 como entradas (poner en 0 lógico)
    DDRA |= ( (1 << DDA0) | (1 << DDA5) | (1 << DDA6) | (1 << DDA7) ); // Configurar pines A5, A6 y A7 como salidas (poner en 1 lógico). El pin A0 es el led intermitente
   
    DDRB&=~(1<<DDB2); //PB2-INT2 sensor IR UNDER BACK. PB1 y PB3 es control del segundo par de motores, donde PA5=ENABLES.
    DDRB |= ((1 << DDB1) | (1 << DDB3));
   
    DDRD|=(0<<DDD3); //Pone como entrada a PD3, y todo lo demás del Port D lo deja tal cual estaba. Esto es para evitar darle fallas al trabajo de la LCD

    PORTA |= (1 << PA5); // Establecer en "1" lógico (Habilitar motores)
}

void overline_set(void) //Configuración de los registros para INT1 e INT2
{
    //El INT1 se ejecuta al encender el uC. Tal vez debo cambiar el comportamiento a "Rising edge", como el INT2
    MCUCR=(0<<ISC11) & (1<<ISC10); // Definiendo comportamiento de la INT1 como "Any logical change interruption" usando el comando 01 en ISC11 e ISC10 respectivamente
    GICR |= (1 << INT1) |(1 << INT2) ; //Habilitar int externas, Al poner 1<<INT2 ya se está habilitando como "rising edge change", es decir la INT2 se va a ejecutar cuando detecte un 1 logico.
}

void status_LCD(void) //Rutina del LCD
{
    lcd_gotoxy(0,0);
    lcd_puts("S1:");
   
    lcd_gotoxy(5,0);
    lcd_puts("S2:");
   
    lcd_gotoxy(10,0);
    lcd_puts("S3:");
   
    lcd_gotoxy(0,1);
    lcd_puts("S4:");
   
    lcd_gotoxy(5,1);
    lcd_puts("S5:");
   
    lcd_gotoxy(10,1);
    lcd_puts("S6:");
   
    if(PINA & (1<<PA1)){
        lcd_gotoxy(3,0);
        lcd_puts("1");
    }
    else{
        lcd_gotoxy(3,0);
        lcd_puts("0");
    }
   
    if(PINA & (1<<PA2)){
        lcd_gotoxy(8,0);
        lcd_puts("1");
    }
    else{
        lcd_gotoxy(8,0);
        lcd_puts("0");
    }
   
    if(PINA & (1<<PA3)){
        lcd_gotoxy(13,0);
        lcd_puts("1");
    }
    else{
        lcd_gotoxy(13,0);
        lcd_puts("0");
    }
   
    if(PINA & (1<<PA4)){
        lcd_gotoxy(3,1);
        lcd_puts("1");
    }
    else{
        lcd_gotoxy(3,1);
        lcd_puts("0");
    }
   
    if(PINB & (1<<PB2))
    {
        lcd_gotoxy(8,1);
        lcd_puts("1");
    }
    else{
        lcd_gotoxy(8,1);
        lcd_puts("0");
    }
   
    if(PIND & (1<<PD3)){
        lcd_gotoxy(13,1);
        lcd_puts("1");
    }
    else{
        lcd_gotoxy(13,1);
        lcd_puts("0");
    }
}

ISR(INT1_vect) //Rutina de interrupción INT1:detección del Sensor S6 (Under Front)
{
    lcd_clrscr();
    lcd_puts("UnderFront Routine");
    _delay_ms(1000);
    lcd_clrscr();
    }
   
ISR(INT2_vect) //Rutina de interrupción INT2:detección del Sensor S5 (Under Back)
{
    lcd_clrscr();
    lcd_puts("UnderBack Routine");
    _delay_ms(1000);
    lcd_clrscr();
    }
   
ISR(TIMER0_OVF_vect) //Rutina de interrupción TIMER0: Led intermitente
{
    overflow_count++; // Incrementar contador de desbordamientos
    if (overflow_count >= 78125) {
        PORTA ^= (1 << PA0);
        // Realizar acciones cuando se alcanzan los 78125 desbordamientos (aproximadamente 5 segundos
    }
}
 

Adjuntos

  • robot simulación y codigo.rar
    77.9 KB · Visitas: 3
Al parecer, debes tener un problema con la configuración de fuses.
Ve a la página de AVR Fuse Calculator y selecciona la configuración que requieras conforme al tipo de oscilador que se use.
En el AVRDUDESS los puedes configurar, pero con mucho cuidado porque lo puedes bloquear.
Si lo bloqueas, necesitarás un programador de alto voltaje para recuperarlo, o con algún circuito que lo haga.
 
Atrás
Arriba