Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Contenido
Aspectos generales ....................................................................................................................... 2
Materiales ..................................................................................................................................... 2
Diseño e Implementación Física.................................................................................................... 5
Programación ................................................................................................................................ 9
2018-2019
1
Aspectos generales
Este proyecto de fin de carrera consiste en la programación y construcción de un pequeño robot
móvil autónomo basado en una tarjeta basado en un ARM. A lo largo del proyecto explicaremos
los diferentes requisitos tanto de software como de hardware necesarios para la realización del
proyecto, el diseño mismo del robot, las herramientas y el entorno utilizados, el desarrollo de la
programación y el hardware y para el funcionamiento del robot.
El robot que vamos a construir es un pequeño robot móvil que evita los obstáculos. A través de
unos sensores infrarrojos, detectará la distancia a los objetos que tiene frente a sí, además de
sensores ópticos de reflexión para determinar la distancia recorrida por el robot. Cuando se
acerque a una determinada distancia, el procesador enviara una señal hacia los motores para
que realicen el giro y así evitar el obstáculo.
Objetivos
Materiales
1. MICROCONTROLADOR [1]
Tarjeta ARM
Raspberry Pi es un ordenador de placa única (SBC) de bajo coste, desarrollado en Reino
Unido por la Fundación Raspberry Pi (Universidad de Cambridge), con el objetivo de
estimular la enseñanza de ciencias de la computación en las escuelas. Aunque
desarrollado en 2006, su lanzamiento en el mercado fue sido en febrero de 2012.
GPIO
El GPIO es el elemento más importante en las prácticas, puesto que permitirá conectar
la Raspberry Pi a distintos elementos hardware como, por ejemplo, sensores (de
ultrasonidos, infrarrojos), control de leds, motores, switches, etc.
2
Fig. GPIO Tarjeta Raspberry PI 2.
La librería WiringPi permite utilizar todos los pines del GPIO. La nomenclatura de los
pines que se suele utilizar es la BCM_GPIO o la numeración de WiringPi. En la siguiente
tabla puede observar la correspondencia entre los 40 pines del conector.
Stick Wifi que se conecta directamente a un puerto USB. Es compatible tanto con
Raspberry Pi como con Beagle Bone y es soportado de forma nativa tanto por la
distribución Angstrom como Raspbian sin recompilar el kernel.
3
3. ACTUADOR
Servomotor
Este servo motor estándar de alto torque incluye engranajes metálicos para un torque
de 12,5 Kg./cm. Puede girar de manera continua (no tiene bloqueo de giro),
consiguiendo 360 grados.
Fig. Servomotor.
Características
• Giro continuo (no tiene tope de giro) 360 grados.
• Voltaje: 4,8 V - 7,2 V DC max. (se recomienda usar 5V a 6V).
• Velocidad promedio: 60 grados en 0,20 seg. (a 4,8 V), 60 grados en 0,16 seg. (a
6,0V).
• Tipo de conector: JR
• Torque: 4,8V: 8,5 kg/cm. 6V: 12,5 kg-cm.
• Tamaño mm: (L x W x H) 40,7 x 19,7 x 42,9 mm.
4. ELEMENTOS ADICIONALES
Rueda omnidireccional
De pivote o Rotatoria Sujeta a la superficie con una estructura que tiene un eje en su
centro, anclado a la rueda que puede girar libremente.
4
Diseño e Implementación Física
Para construir el robot móvil lo primero considera las dimensiones de diseño de un chasis en el
que se instalara los componentes necesarios para su funcionamiento. Por este motivo se
determinó dimensiones próximas a las establecidas en el guion, se colocó una placa base que
alberga la batería de 10000mAh para alimentar toda la electrónica y sobre esta un segundo nivel
donde, reposara la tarjera Raspberry Pi, además se colocaran las diversas piezas que requiere el
robot.
1.- Para implementar el chasis se seleccionó madera de cedro por ser ligera y blanda, se realizó
cortes con las dimensiones establecidas para el chasis a partir del diseño previo y ensamblarlo,
con el chasis montado se procedió a instalar los servomotores.
2.- Instalados los servomotores se coloca la rueda loca, su ubicación conforme al diseño se
establece en la parte inferior del chasis, la misma que permitirá que el vehículo móvil pueda
desplazarse en diversas direcciones, deberá ajustarse de manera que el vehículo se encuentre
nivelado con respecto a la superficie en la que va a desplazarse, de está manera, manteniendo
su centro de masa y el auto equilibrado.
5
Fig. Colocación rueda loca
6
Fig. Vista frontal y plantilla para encoder
En la imagen se aprecia los sensores infrarrojos en su parte frontal y las plantillas para el
encoder, mientras que la colocación de los sensores ópticos se construyó un sistema mecánico
que permita manipular la altura (h), la separación entre rueda – sensor (d) y ángulo de
proyección del haz incidente (r) sobre la plantilla para encoder.
7
Electrónica Implementada
SECCIÓN II
En las pruebas realizadas con este circuito se comprobó que el sensor responde digitalmente, es
decir, 1 y 0 a la distancia máxima de 10mm, además el CNY70 proporciona un voltaje vs la
distancia al objeto que refleja la luz.
8
Programación
Diagrama de flujo
Datos requeridos
//Se realiza la declaración de las variables globales y se las inicializa, así como se ejecuta wiringPi
y supone que el programa de llamada usará el esquema de numeración de pin wiringPi y a su
vez la ubicación física de pines Broadcom GPIO.
int main() {
int i,a=4;
int wi,wd;
int vdl=0,vil=0;
int L,vm;
float lw=22.0,b=11.5;
wiringPiSetup();
// Por consola se indica la distancia a desplazar y el ángulo de giro mediante los datos obtenidos
inicialmente de la mecánica del vehículo.
printf("Introduzca la distancia en cm que desea avanzar:\n");
scanf("%d",&L);
vm=(int)((float)L*16.0/lw);
printf("Se necesita girar %d pasos para llegar\n",vm);
9
// Se crea un subproceso dentro de su programa principal que se ejecuta al mismo tiempo y que
transmite las variables entre ellos de manera segura tanto para tiempo de giro de la rueda
izquierda y derecha.
piThreadCreate(der); //Función hilo tiempo rueda derecha
piThreadCreate(izq); //Función hilo tiempo rueda derecha
// Se crea dos pines PWM controlado por software. El rango de PWM establecido para el tiempo
de trabajo son 10ms, indicando cuando el pin se encuentra apagado en 0 y 100 completamente
encendido.
softPwmCreate(25, 0,100); //izq
softPwmCreate(28, 0,100); //der
// Se verifica que el valor esté dentro del rango y se actualiza el valor de PWM en el pin dado
de acuerdo a la velocidad asignada para trabajar en los servomotores.
softPwmWrite(25, wi);//izq
softPwmWrite(28, wd);//der
printf("i=%d\n",i);
i=i+1;
// Se procede a sincronizar la actualización de variables de los subprocesos creados y que se
ejecutando en el programa. Se asigno un identificador 0 para el subproceso de la rueda derecha
y 1 para el subproceso de la rueda izquierda, de esta forma se detendrá hasta que el primer
subproceso que ingreso quede desbloqueado.
piLock (0); vdl=vd;
piUnlock (0);
piLock (1); vil=vi;
piUnlock (1);
printf("vdl=%d vil=%d\n",vdl,vil);
delay(100);
softPwmWrite(25, 0);//izq
softPwmWrite(28, 0);//der
//Para estimar la distancia que ha recorrido el robot móvil se va considerar los pulsos registrados
por cada función implementada para cada encoder PI_THREAD (der) y PI_THREAD (izq)
considerando un umbral de lectura de 381, es decir que si la variable de lectura X1>381 se
considera un nivel alto mientras que si X1<381 se establece un nivel bajo, además la lectura del
sensor se lo realiza por el canal de lectura 100 para el sensor de la derecha y 101 para el sensor
de la izquierda, incluyendo un lazo de tipo FOR para sincronizar la actualización de las variables
de los subprocesos que se encuentran en ejecución y determinar cuántos pulsos se han
receptado en el proceso de lectura.
PI_THREAD (der)
{
int x1=222;
10
int c1=0,c0=0;
x1 = analogRead (100) ;
if(x1<381){
c0=0;
}
if(x1>381){
c0=1;
}else{
}
for (;;)
{
x1 = analogRead (100) ;
if(x1<281){
c1=0;
if(c1!=c0){
piLock (0);
vd=vd+1;
//printf("x1=%d vd=%d\n",x1,vd);
piUnlock (0);
}
}else{
if(x1>381){
c1=1;
if(c1!=c0){
piLock (0);
vd=vd+1;
//printf("x1=%d vd=%d\n",x1,vd);
piUnlock (0);
}
}else{
c1=c0;
}
}
c0=c1;
delay(10);
}
}
PI_THREAD (izq)
{
int x1=222;
int c1=0,c0=0;
x1 = analogRead (101) ;
if(x1<381){
c0=0;
}
if(x1>381){
c0=1;
}else{
}
for (;;)
{
x1 = analogRead (101) ;
if(x1<281){
c1=0;
if(c1!=c0){
piLock (1);
vi=vi+1;
//printf("x1=%d vi=%d\n",x1,vi);
piUnlock (1);
}
}else{
if(x1>381){
c1=1;
11
if(c1!=c0){
piLock (1);
vi=vi+1;
//printf("x1=%d vi=%d\n",x1,vi);
piUnlock (1);
}
}else{
c1=c0;
}
}
c0=c1;
delay(10);
}
}
//Se realiza la declaración de las variables y se inicializa con los datos de construcción, como
condiciones iniciales se solicita por consola la distancia a recorrer y en base a los datos
proporcionados se calculara la distancia, usando los datos recibidos por las funciones de los
encoders.
int main() {
int i,a=4;
int wi,wd;
int vdl=0,vil=0;
int L,vm;
float lw=22.0,b=11.5;
wiringPiSetup();
mcp3004Setup (100,0);
printf("Introduzca la distancia en cm que desea avanzar:\n");
scanf("%d",&L);
vm=(int)((float)L*16.0/lw);
printf("Se nesita girar %d pasos para llegar\n",vm);
piThreadCreate(der);
piThreadCreate(izq);
softPwmWrite(25, wi);//izq
softPwmWrite(28, wd);//der
printf("i=%d\n",i);
i=i+1;
piLock (0);
vdl=vd;
piUnlock (0);
piLock (1);
vil=vi;
piUnlock (1);
printf("vdl=%d vil=%d\n",vdl,vil);
delay(100);
}
softPwmWrite(25, 0);//izq
softPwmWrite(28, 0);//der
12
Giro del robot
//Como condiciones iniciales se solicita por consola el ángulo en grados que se requiere girar, el
ángulo ingresado se compara para condicionar el giro de las ruedas para ángulos positivos o
ángulos negativos, además se calcula el ángulo por lo datos proporcionados inicialmente y a
partir de los pasos calculados se activan los hilos, mientras se compara en un lazo WHILE se
controla el giro de las ruedas en función del PWM asignado.
vm=(int)(((float)L*(M_PI/180.0)*b)*16.0/lw);
printf("Se necesita girar %d pasos para girar %d grados\n",vm,L);
piLock (0);
vd=0;
vdl=vd;
piUnlock (0);
piLock (1);
vi=0;
vil=vi;
piUnlock (1);
softPwmWrite(25, wi);//izq
softPwmWrite(28, wd);//der
printf("i=%d\n",i);
i=i+1;
piLock (0);
vdl=vd;
piUnlock (0);
piLock (1);
vil=vi;
piUnlock (1);
printf("vdl=%d vil=%d\n",vdl,vil);
delay(100);
}
//printf("i=%d x1=%d\n",i,x1);
return 0;
}
//Para estimar la distancia que ha recorrido el robot móvil se va considerar los pulsos registrados
por cada función implementada para cada encoder PI_THREAD (der) y PI_THREAD (izq)
considerando un umbral de lectura de 381, es decir que si la variable de lectura X1>381 se
considera un nivel alto mientras que si X1<381 se establece un nivel bajo, además la lectura del
sensor se lo realiza por el canal de lectura 100 para el sensor de la derecha y 101 para el sensor
de la izquierda, incluyendo un lazo de tipo FOR para sincronizar la actualización de las variables
de los subprocesos que se encuentran en ejecución y determinar cuántos pulsos se han
receptado en el proceso de lectura.
13
Para el uso del sensor infrarrojo se procedió a realizar la caracterización, la cual se extrapolo en
un rango de 4 a 40cm, creando un fichero con los valores obtenidos medidos manualmente con
el rango establecido en intervalos de 1cm.
#include "mcp3004.h"
int main() {
int x1,i;
FILE *d;
wiringPiSetup();
//wiringPiSetupGpio();
d=fopen("datos","w+");
mcp3004Setup (100,0);
for(i=0;i<10;i++){
x1 = analogRead (100) ;
printf("i=%d voltaje=%d\n",i,x1);
fprintf(d,"%d %d\n",i,x1);
getchar();
}
return 0;
}
Extrapolados los datos se genera un conjunto de valores igual a L = 731, los mismos que se
asignaran proporcionalmente en función de la distancia que sea detectada por el sensor
infrarrojo, como condiciones de fiabilidad se consideró valores superiores a los calculados se
asignara a la variable de medida m=0, de igual forma si está por debajo de los 4cm del rango
establecido.
if(x>801){m=0.0;
}else{
if(x<71){
if(x<10){
m=0.0;
}
m=40.0;
}else{
m=L[x-71];
}
} return m;
}
14
Para el control de distancia del sensor se inicializaron los parámetros para encoders y
posicionamiento, de esta forma se condiciona el inicio de coordenadas y orientación a usar.
Usando las funciones hilos y la librería mide para la lectura del sensor infrarrojo, controlamos el
posicionamiento en base a la distancia de detección, empezamos indicado por consola la
distancia que se desea avanzar, el algoritmo enviara una advertencia al detecta un objeto a una
distancia menor a 40cm,se detiene por 150ms, después avanza mientras se actualiza
continuamente la distancia detectada por el sensor hasta establecerse frente al objeto a una
distancia menor a 25cm sin embargo si el objeto ya no es detectado el vehículo continuara su
trayectoria, de lo contrario se detiene.
if(x1f<39.0 || x2f<39.0){
printf("Me choco!!\n");
softPwmWrite(25, 0);//izq
softPwmWrite(28, 0);//der
delay(150);
g=1;
while(g==1){
softPwmWrite(25, wi);//izq
softPwmWrite(28, wd);//der
x1=analogRead (102) ;
x1f=mide(x1);
x2=analogRead (103) ;
x2f=mide(x2);
while(x1f>25.0 || x2f>25.0){
printf("vdl=%d vil=%d izq=%f der=%f \n",vdl,vil,x1f,x2f);
delay(50);
x1=analogRead (102) ;
x1f=mide(x1);
x2=analogRead (103) ;
x2f=mide(x2);
}
softPwmWrite(25, 0);//izq
softPwmWrite(28, 0);//der
delay(150);
if(x2f>x1f){
wig=15+a;
//wdg=15+a;
wdg=0;
}else{
//wig=15-a;
wig=0;
wdg=15-a;
}
Esto se realiza para (x1f>25.0 || x2f>25.0) y (x1f<25.0 || x2f<25.0) logrando detenerse frente al
objeto o avanzar sin problema en el caso de que el objeto ya no se encuentre presente.
15