MiniSumo AESSBot 2012

Preparado el primer robot del AESSBot 2012, un minisumo (hecho muy deprisa y corriendo) basado en el kit de Fingertech Robotics que ha facilitado enormemente la tarea de comenzar en la prueba, y que esperemos que almenos llegue a homologar y participar en los combates contra otros robots.

Debido al poco tiempo que hemos tenido para preparar el robot hemos hecho lo primero que ha salido.. La idea ha sido colocar los sensores lo más bajo posibles para detectar a los robots más pequeños, como sensor según nos han recomendado varios participantes de las pruebas de sumo (gracias) hemos elegido dos GP2Y0D340K, que se encargan de detectar al oponentes a larga distancia, y un GP2Y0D310K (sensor central) que detecta al oponente a una distancia más corta, ambos modelos son sensores digitales que sólo nos indican si hay un objeto delante.

Junto a los sensores de suelo que venían con el robot estos son todos los sensores que lleva el robot, para integrarlos en el robot se han hecho un par de pcbs, un pcb que lleva los sensores para detectar al oponente y donde se conectan los sensores de suelo delanteros, y otro pcb para acoplar cada sensor de suelo al robot, se pueden ver en las imagenes (el esquema de los sensores es el recomendado en su datasheet).

En la imagen se puede ver que hay dos baterías, una de 7.4 V para alimentar a los motores y otra de 3.7 V como la que llevamos en los robots velocistas, para alimentar al microcontrolador y sensores del robot.

Con esta placa de sensores se pretende detectar hacia donde se mueve el oponente, de tal forma que si lo perdemos mirando cuál ha sido el último sensor que lo ha detectado podemos saber hacia que lado ir a buscarlo. Si el oponente está muy cerca los sensores pueden dar una lectura falsa, los sensores de larga distancia darán esa lectura falsa antes que el sensor central de corta distancia, también con este sensor sabemos cuando el robot está más cerca, llevar sensores de varias distancias nos da más opciones en la programación a la hora de solucionar los problemas que puedan surgir en el combate.

Los robots de sumo además de los sensores delanteros suelen llevar sensores en los lados y detrás para detectar al oponente, en este robot no hemos tenido tiempo de incluirlos.

En el vídeo un ejemplo del funcionamiento de los sensores, el robot sigue a la caja y cuando el sensor central detecta que está cerca avanza, cuando los sensores de suelo ven la línea negra el robot retrocede.

Los sensores van muy bajos y por lo tanto es posible que se lleven los primeros golpes, por lo que hay que protegerlos, sin herramientas para trabajar los materiales que estos robots requieren lo único que he puesto es un trozo de aluminio, esperemos que sea suficiente..

Para tener el robot completo falta la placa de la electrónica que lea los sensores y controle los motores, para controlar los motores un puente en H de Pololu que tenía de otro robot conectando dos motores a cada canal, es más que suficiente para estos motores tan pequeños.

En esta placa del puente pinchamos otra con un ATmega328p, pcb, que se va a encargar de leer los sensores del robot y establecer el sentido de giro y velocidad de los motores.

La placa incluye un dc-dc de Pololu para subir la tensión de la lipo de 3.7V a los 5V que necesitan los sensores y el microcontrolador para trabajar, en este caso un poco más ya que también he añadido un regulador disipativo para proteger la electrónica, no sea que se toque el ajuste del dc-dc dando éste más de 5V y quememos la electrónica (sensores, micro y puente en H), la electrónica es cara y la diferencia de consumo no la vamos a notar ya que la capacidad de la lipo es más que suficiente para muchos combates, se va a descargar antes la batería de los motores.

Un pulsador para comenzar el combate, conector de sensores, conector al puente en H y unos pocos leds para ayudar a la programación, lo primero que ha salido =)

Un diseño muy sencillo de robot con el que comenzar en la prueba, 474 gramos y es que el lastre ayuda bastante a alcanzar los 500 gramos necesarios para maximizar nuestra fuerza de empuje.

En cuanto a la programación del robot lo que ha dado tiempo a hacer esta tarde y así se queda, y es que la pista de velocistas salió el viernes pasado y aún nos queda programarlos… un programa simple de girar y moverse para detectar al oponente a una velocidad baja, y cuando el sensor central de corta distancia lo detecta poner el pwm al máximo.

Pues éste es nuestro primer intento de minisumo que esperemos homologue y tenga sus primeros combates en el AESSBot 2012.

Adjunto el código del segundo vídeo hecho esta tarde (probablemente lleno de errores =) ) y que va a llevar el robot a falta de cambiar los sensores de línea.

//MiniSumo
#define F_CPU 16000000UL	
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
 
//Motores
 
#define INA1 PORTB2
#define INB1 PORTB1
#define PWM1 PORTD5
#define PWM2 PORTD6
#define INB2 PORTD7
#define INA2 PORTB0
 
//Leds
 
#define LEDY PORTC5
#define LEDR PORTC4
#define LEDV PORTC3
#define LEDA PORTC2
 
//Entradas
 
#define PULSADOR PORTC0
#define SENSORST PORTC1
#define SENSORSD PORTD0
#define SENSORSI PORTD4
#define SENSORI PORTD3
#define SENSORC PORTD2
#define SENSORD PORTD1
 
//Funciones
 
void inicializar_micro(void);
void motor_derecho(char movimiento, unsigned char velocidad);
void motor_izquierdo(char movimiento, unsigned char velocidad);
 
//Variables
unsigned char velocidada = 255; 
unsigned char velocidadg = 190; 
unsigned char velocidad = 127;
unsigned char velocidad_avance = 100;
unsigned char velocidadl = 64;
volatile unsigned char retroceder = 0;
volatile unsigned char ultimo_sensor = 0;
 
int main( void ) 
{
 
	char pulsador = 1;
	char sentido = 0;
	static int tiempo = 0;
 
	inicializar_micro();
 
	PORTC |= (1<<LEDR);
	while(pulsador != 0 )
	{
		pulsador = PINC & (1<<PULSADOR);
	}
 
	PORTC &= ~(1<<LEDR);
	_delay_ms(500);
	_delay_ms(500);
	PORTC |= (1<<LEDR);
	_delay_ms(500);
	_delay_ms(500);
	PORTC &= ~(1<<LEDR);
	_delay_ms(500);
	_delay_ms(500);
	PORTC |= (1<<LEDR);
	_delay_ms(500);
	_delay_ms(500);
	PORTC &= ~(1<<LEDR);
	_delay_ms(500);
	_delay_ms(500);
 
	sei(); //Habilitar interrupciones globales.
 
	motor_derecho(0,255);
	motor_izquierdo(0,255);
 
	while ( 1 ) 
	{
 
		if(retroceder == 1)
		{
			PORTC &= ~(1<<LEDY);
			PORTC &= ~(1<<LEDV);
			PORTC &= ~(1<<LEDR);
			motor_derecho(2,velocidad);
			motor_izquierdo(2,velocidad);
			tiempo = 0;
 
			_delay_ms(500);
			retroceder = 0;
 
			PORTC |= (1<<LEDA);			
		}
 
 
		else if((PIND & (1<<SENSORC)) == 0) //sensore central
		{
			motor_derecho(1,velocidada);
			motor_izquierdo(1,velocidada);
			PORTC |= (1<<LEDR);
			PORTC &= ~(1<<LEDV);
			PORTC &= ~(1<<LEDY);
			PORTC &= ~(1<<LEDA);
			tiempo = 0;
//			_delay_ms(300);
		}
 
		else
		{
			PORTC &= ~(1<<LEDA);
 
			if( ( (PIND & (1<<SENSORI)) == 0) &&  ((PIND & (1<<SENSORD)) == 0) )
			{
				motor_derecho(1,velocidad);
				motor_izquierdo(1,velocidad);
				PORTC |= (1<<LEDV);
				PORTC |= (1<<LEDY);
				PORTC &= ~(1<<LEDR);
				tiempo = 0;
			}
 
 
			else if(((PIND & (1<<SENSORI)) == 0) && ((PIND & (1<<SENSORD)) != 0) )
			{
				motor_derecho(1,velocidadg);
				motor_izquierdo(1,velocidadl);
				sentido = 1;
 
				PORTC |= (1<<LEDV);
				PORTC &= ~(1<<LEDR);
				PORTC &= ~(1<<LEDY);
				tiempo = 0;
			}
 
			else if( ( (PIND & (1<<SENSORI)) != 0) &&  ((PIND & (1<<SENSORD)) == 0) )
			{
				motor_derecho(1,velocidadg);
				motor_izquierdo(1,velocidadl);
				sentido = 0;
				PORTC |= (1<<LEDY);
				PORTC &= ~(1<<LEDR);
				PORTC &= ~(1<<LEDV);
				tiempo = 0;
			}
			else
			{
				PORTC |= (1<<LEDY);
				PORTC &= ~(1<<LEDV);
				PORTC &= ~(1<<LEDR);
				PORTC |= (1<<LEDA);
 
				if(tiempo < 900)
				{
					if(sentido == 1)
					{
						motor_derecho(1,velocidad);
		  	 			motor_izquierdo(2,velocidad);
					}
					else
					{
						motor_derecho(2,velocidad);
		  	 			motor_izquierdo(1,velocidad);
					}
					tiempo++;
				}
				else
				{
						motor_derecho(1,velocidad_avance);
		  	 			motor_izquierdo(1,velocidad_avance);
				}
			}
		}
 
		_delay_ms(3);
	}
	return 0;
}
 
 
void inicializar_micro(void)
{
	DDRC = 0x3C;  //0011 1100
	PORTC = 0x00; //0000 0000
	DDRB = 0x07;  //0000 0111
	PORTB = 0x00;
	DDRD = 0xE0;  //1110 0000
	PORTD = 0x00;
 
	//Configurar PWM timer0
	TCCR0A = 0xA3; //1010 0011
	TCCR0B = 0x02; //0000 0010
	OCR0A = 0;
	OCR0B = 0;
 
	//Interrupciones
	PCICR |= (1<<PCIE1); // Interrupción sensor trasero suelo
    PCMSK1 |= (1<<PCINT9); //Habilitar pin
 
	PCICR |= (1<<PCIE2); // Interrupción sensore delantero suelo
    PCMSK2 |= (1<<PCINT16); //Habilitar pines
	PCMSK2 |= (1<<PCINT20);
}
 
void motor_derecho(char movimiento, unsigned char velocidad)
{
	OCR0B = velocidad;
	switch(movimiento)
	{
		case 0:
		{
			PORTB &= ~(1<<INA1);
			PORTB &= ~(1<<INB1);
		}
		break;
 
		case 1:
		{
			PORTB |= (1<<INA1);
			PORTB &= ~(1<<INB1);
		}
		break;
 
		case 2:
		{
			PORTB &= ~(1<<INA1);
			PORTB |= (1<<INB1);
		}
		break;
 
		default:break;
	}
}
void motor_izquierdo(char movimiento, unsigned char velocidad)
{
	OCR0A = velocidad;
	switch(movimiento)
	{
		case 0:
		{
			PORTB &= ~(1<<INA2);
			PORTD &= ~(1<<INB2);
		}
		break;
 
		case 1:
		{
			PORTB |= (1<<INA2);
			PORTD &= ~(1<<INB2);
		}
		break;
 
		case 2:
		{
			PORTB &= ~(1<<INA2);
			PORTD |= (1<<INB2);
		}
		break;
 
		default:break;
	}
}
 
ISR(PCINT1_vect) //Trasero
{
	if((PINC & (1<<SENSORST)) != 0) //cambiar a línea blanca
	{
//		motor_derecho(1,velocidad);
//		motor_izquierdo(1,velocidad);
//		_delay_ms(200);
 
		if(ultimo_sensor == 0) //Derecho
		{
			motor_derecho(1,velocidadg);
			motor_izquierdo(1,velocidadl);
			_delay_ms(200);	
			motor_derecho(0,255);
			motor_izquierdo(0,255);			
		}
 
		else if(ultimo_sensor == 1) //Izquierdo
		{
			motor_derecho(1,velocidadl);
			motor_izquierdo(1,velocidadg);
			_delay_ms(200);	
			motor_derecho(0,255);
			motor_izquierdo(0,255);			
		}
	}
 
	PCIFR  |=(1<<PCIF1); //Limpiamos el flag de interrupción.
}
 
ISR(PCINT2_vect) //Delantero 
{
//	if(((PIND & (1<<SENSORSD)) != 0) || ( (PIND & (1<<SENSORSI)) != 0))
//	{
//		retroceder = 1;
//	}
 
	if((PIND & (1<<SENSORSD)) != 0)	//cambiar a línea blanca
	{
		retroceder = 1;
		ultimo_sensor = 0;
	}
	else if((PIND & (1<<SENSORSI)) != 0) //cambiar a línea blanca
	{
		retroceder = 1;
		ultimo_sensor = 1;
	}
 
	PCIFR  |=(1<<PCIF2); //Limpiamos el flag de interrupción.
}
Visitas :21336
Both comments and pings are currently closed.

9 Responses to “MiniSumo AESSBot 2012”

  1. Gremio says:

    Tiene una pinta exelente JMN, enhorabuena por el curro y el resultado :)

  2. sento says:

    Magnifico, un trabajo increíble!

  3. salvachuan says:

    Gran trabajo y muy rápido.
    Suerte en la AESSBot.

  4. JMN says:

    Gracias por los comentarios :)

  5. JMN says:

    Error en el código, en el while(1), último else if, cuando está activo el sensor derecho y ninguno más:

    else if( ( (PIND &…
    {
    motor_derecho(1,velocidadl);
    motor_izquierdo(1,velocidadg);

    Ahora sigue los objetos mejor.

  6. Zxi says:

    ¿Qué es mejor utilizar sensores infrarrojos o ultrasónicos para la detección del oponente?

    • JMN says:

      Hola, por lo general la mayoría de la gente usa sensores ópticos, detectan si el objeto está delante, los de ultrasonido tienen un ángulo de detección bastante amplio, y también dan muchos problemas de ruido/falsos positivos.

  7. ilsita90 says:

    se ve muy bueno pero me gustaria ver si tienen un diagrama del circuito electronico para simularlo

    • JMN says:

      Hola, pues no subí el esquema a la página y no lo he guardado ya que es muy sencillito, se puede sacar facilmente desde el pcb y las imagenes.

Subscribe to RSS Feed Follow me on Twitter!