Proyectos con microcontroladores atmel

A la hora de encarar proyectos con microcontroladores atmel, lo primero que pensamos es en usar arduino, donde el corazón de dicha plataforma es un atmega32, pero supongamos que por algún motivo tenemos que utilizar otro microcontrolador y nos vemos obligados a descartar la utilización de arduino.

En ese caso deberíamos ir a las hojas de datos del fabricante del microprocesador que vamos a utilizar y armarnos nuestra propia placa programadora. Para este proyecto utilizamos el atmega16 de atmel.

Robot buscador de salida

Este proyecto  fue presentado en la cátedra de técnicas digitales 3 en la universidad de la matanza, en la cursada nos enseñaron a programar los microcontroladores atmel en c++ y tuvimos vía libre para desarrollar cualquier proyecto que tengamos ganas de hacer, al final de la cursada resulto esto.

Especificación técnica

Sin tomar en cuenta el microprocesador, el robot consiste en tres bloques funcionales, cada uno de estos cumple una función específica

  • Chasis
  • Sensor ultrasonido
  • Mini Servo
  • Puente H

El robot se encuentra en estado de “Free Running”(estado de avance, ambos motores girando hacia adelante), hasta que el sensor de ultrasonido detecte un obstáculo en frente (25 cm), una vez que se detecte un obstáculo por delante, los motores de detendrán.

Luego de detenidos los motores entrara en juego el Servo, que tiene adherido un sensor de ultra sonido US-100 de manera que al girar este también lo haga el sensor de ultrasonido.

De esta manea al detectar un obstáculo y luego de frenar los motores, el servo girar hacia los laterales el US (primero izquierda luego derecha), luego de terminado este proceso, el micro controlador evaluara que dirección es la más conveniente para el escape, considerando como más conveniente la dirección en la cual tenga un obstáculo más lejano.

En el caso de no detectar “Libertad” en ninguno de los laterales, el robot procederá el escape marcha atrás.

Control Sensor ultrasonido us-100

En el siguiente link (ver us-100) explicamos en detalle como funciona este sensor, igualmente para no ir y venir de un articulo a otro comentamos un resumen de su funcionamiento.

Este sensor cuenta con 4 pines.

  • Vcc (5 volt)
  • Trigger
  • Echo
  • Gnd (0 volt)

Para iniciar la medición se deUSbe activar el sensor enviando un pulso de 10ms al pin2 (Trigger), luego de finalizado este tiempo, por el pin3(echo) se enviara un estado alto al micro controlador que significa que la medición ha comenzado, la medición terminara cuando el mismo Pin ingrese un nivel bajo.

 

 

 

 

Al inicio de la medición disparamos el Timer/Counter configurando el Prescaler en $01(0b0000001)

fbus = fclock/1

Grafico sensor de ultrasonido US-100

Registro TCCR1B del microcontrolador ATMEGA16

¿Cómo calculo la distancia al objeto con el ultrasonido?

La velocidad del sonido es 34300cm/s, la frecuencia de clock utilizada es de 1Mhz lo que es equivalente a un periodo T de 0,976ms, el tiempo que tarda el sonido en recorrer 2cm (1cm de ida y 1cm de vuelta) será 2cm/34300cms = 0,0583ms.

Por lo tanto si el contador del timer cuenta 58,3(redondeamos en 58) la distancia medida corresponde a 1cm, de esta manera llegamos a la conclusión que el cálculo de la distancia medida será la calculada a partir de la siguiente formula.

Distancia = 1/(58*Fclock)

Control Movimiento del Servomotor

El servo cuenta con tres cables

  • Rojo – Vcc
  • Negro – Gnd
  • Blanco – Datos

El control de posición angular del servo se realiza mediante modulación por ancho de pulso(PWM), la frecuencia de trabajo del servo utilizado en el proyecto es de 50Hz.

El periodo de la señal que debemos enviar al servo debe ser de 20ms, la hoja de datos del mismo nos suministra la siguiente información.

Señal para posicionamiento a 180 grados (izquierda)

Modulacion PWM para servomotor giro 180

Ton = tiempo en alto de la señal
Toff =  tiempo en bajo de la señal
Periodo = Ton+Toff = 20ms

 

Para lograr un posicionamiento a 180 grados debemos enviar una señal con un ton = 0.3ms y un toff=19.7ms.
Una vez que el servo alcanzo la posición deseada dejamos de enviar la señal.

Señal para posicionamiento a 0 grados (derecha)

Servo posicionamiento a cero grados

Ton = tiempo en alto de la señal
Toff =  tiempo en bajo de la señal
Periodo = Ton+Toff = 20ms

 

 

Para lograr un posicionamiento a 180 grados debemos enviar una señal con un ton = 2.3ms y un toff=17.7ms.
Cualquier señal que enviemos con un Ton comprendido entre estos dos valores nos posicionar en un angulo equivalente.

Control de los motores con el l293b

Este solo integrado nos permite controlar dos motores en simultaneo. los terminales del Motor M1 conectados a los Pines 3 y 6 y los terminales del motor M2 a los terminales 11 y 14, como se ilustra en la figura.
El pin 16 corresponde a la alimentación propia del integrado, 5V, el Pin 16 deberá estar conectado a  la tensión que alimentara los motores, puede variar en el rango de (5 a 36) V. (ver mas)

Servomotor l293b tabla de verdad

Los terminales 2 y 7 del puente H están conectados a los pines 6 y 7 del puerto D del microprocesador, los terminales 10 y 15 están conectados a los pines 5 y 4 del ATMEL, de esta manera podemos controlar el giro de cada uno de los motores modificando los pines 4,5,6,7.

Tabla de verdad control de motores L293B

Diagrama en bloque

Presentamos el diagrama en bloque, como tienen que estar conectados cada uno de sus componentes para que luego al cargar el software funcione como tiene que funcionar.

Diagrama en Bloque

Software

Compartimos las lineas de código con las que programamos el micro, utilizamos el programador de AVR para flashear la memoria pero se puede utilizar cualquier programador.

#define F_CPU 1000000UL// 1 MHz
#include <avr/io.h>
#include <avr/interrupt.h>
#include "C:\WinAVR-20100110\avr\include\util\delay.h"


//Definiciones
#define FOSC 1000000     // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
#define BIT0		0x01
#define BIT1		0x02
#define BIT2		0x04
#define BIT3		0x08
#define BIT4		0x10
#define BIT5		0x20
#define BIT6		0x40
#define BIT7		0x80
#define START_CLK   0x0A    //Inicializar el reloj con 1:8 de preescalador / Modo CTC
#define START_CLK_N 0x01    //Inicializar el reloj con 1:8 de preescalador
#define STOP_CLK    0x08    //Parar el timer


//Variables globales
long int Obstaculo;
long int LecturaUS1;
long int LecturaUS2;
long int LecturaUS3;
long int DistanciaDeteccion = 25;

int PosServo=0;  //Posicion del servo(Ojos)


//----------------------------DECLARACION DE FUNCIONES-------------------------
//Configuracion de puertos
void setup_Puertos(void)
{
	 DDRA =  0b00001110;
	 PORTA = 0b00000100;
	 DDRD =  0b11111111;
	 PORTD = 0b00000000;
 }
//(US)Funcion para inicializar el timer
void TIMER_init(void){               
	TCCR1A = 0x00;        //Activar modo CTC
	TCCR1B = 0x08;        //Limpiar el dato de OC1A/OC1B
}
//(US)Funcion para mandar el pulso al trigger del ultrasonico
void US_trigger(void){  
	PORTA = (0b00000010);
	_delay_us(10);
	PORTA = (0b00000000);
}

 

//(US)Funcion para leer el dato del ultrasonico
unsigned int US_echo(void){
	unsigned int iLecturaUS; 
	while(!(PINA&0x01));        //Esperar a que en el PB0 entre un nivel alto (inicio de medicion)
	TCNT1 = 0x00;               //Limpiar el timer, dejarlo en cero
	TCCR1B = START_CLK_N;       //Inicializar el reloj con 1:8 de preescalador
	while((PINA&0x01));         //Esperar a que en el PB0 entre un nivel bajo (final de medicion)
	TCCR1B = STOP_CLK;          //Parar el timer
	iLecturaUS = TCNT1/58;      //Leer el valor del registro y dividirlo entre 58 para obtener
	return(iLecturaUS);         //la medicion en cm.            
}
//(US)Funcion Para poner en ON en US
int US_Read()
{
	int iLecturaUS;
	US_trigger();            //Mandar el pulso al trigger para que el ultrasonico se active
	iLecturaUS = US_echo();  //Leer el valor medido por el ultrasonico, segun el ancho del pulso
	return iLecturaUS;
}

int US_ExisteObstaculo()
{
	int LecturaUS1 = (int)US_Read(); //Leo distancias 1
	int LecturaUS2 = (int)US_Read(); //Leo distancias 2
	int LecturaUS3 = (int)US_Read(); //Leo distancias 3
	int Obstaculo = 0;
	//Si las tres lecturas dan positivas estoy seguro que tengo un obstaculo en frente, asi evito lecturas basura			
	if(LecturaUS1 15 && DistanciaDerecha > 15) //Distancia minima que me permite el giro
				{
					if(DistanciaIzquierda>DistanciaDerecha)
					{
						PORTD = 0b01000000;//Giro a la Izquierda
						_delay_ms(500);
					}
					else
					{
						PORTD = 0b00100000;//Giro a la Derecha
					    _delay_ms(500);				
					}						
				}
				else //alguna distancia lateral es menor a 15
				{
					if(DistanciaIzquierda > 15 && (DistanciaDerecha > 10 && DistanciaDerecha < 15)) //Escapo a la izquierda { PORTD = 0b01000000;//Giro a la Izquierda _delay_ms(500); } else { if((DistanciaIzquierda > 10 && DistanciaIzquierda < 15) && DistanciaDerecha > 15) //Escapo a la derecha
						{
							PORTD = 0b00100000;//Giro a la Derecha
					    	_delay_ms(500);	
						}
						else
						{
							
							if(DistanciaIzquierda<5)
							{
								PORTD = 0b10000000;//Giro la rueda derecha para atras
								_delay_ms(500);
							}
							else
							{
								if(DistanciaDerecha<5)
								{
									PORTD = 0b00010000;//Giro la rueda izquierda para atras
									_delay_ms(500);
								}
								else
								{
									MOTORES_ReverseRunning();//Escapo marcha atras
									_delay_ms(1000);								
								}							
							}	
						}
					}	
				}	

			}
			else
			{
				//Antes de correr libremente vuelvo a validar la existencia de un obstaculos
				if(US_ExisteObstaculo() == 0)
				{
					PosServo = 0;
					MOTORES_FreeRunning();
				}
			}
			
			
    }

}


Posibles mejoras

Dentro de las posibles mejoras resaltamos dos como más importantes.

1-El robot debe tener la posibilidad de escanear una mayor cantidad de posiciones angulares, actualmente escanea solo tres ángulos 0°,90°,180°, para la toma de una decisión más acertada debería poder escanear como mínimo intervalos de 45°, de esta manera se duplicaría la información del contexto que rodea al robot.

2-El robot debe tener la posibilidad de memorizar un camino recorrido, y un escape para dicho camino, de esta manera al detectar que está recorriendo un camino que concuerda con un camino anteriormente recorrido en el cual nunca encontró salida, pueda tomar la decisión de abandonar el trayecto ya que existe una gran posibilidad quedar encerrado.

3-Agregar un sensor de US adicional en la parte trasera para no perder visión al momento de realizar una marcha atrás

 

Conclusión

Hemos podido realizar el proyecto, utilizando los conocimientos adquiridos en las clases, pudiendo de esta manera interactuar y resolver los problemas presentados de manera autodidacta, logramos controlar eficientemente los dispositivos necesarios en el proyecto (Sensores de Ultrasonido, Servomotores, Puente H). El Robot fue capaz de evadir cualquier obstáculo encontrado escaneando hacia los laterales y tomando la decisión que más le conviene.

Compartimos algunas fotos del resultado final

Robot buscador de salida

va otra de frenteRobot buscador de salida

 

Espero que les sea de utilidad.

ARTICULOS RELACIONADOS

5 comentarios sobre “Proyectos con microcontroladores atmel

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *