Programa un coche Arduino con Inteligencia Artificial

El Machine Learning nos permitirá utilizar Redes Neuronales para que un coche Arduino conduzca sólo evitando obstáculos.

En el artículo anterior, creamos una red neuronal desde cero en Python. En este artículo mejoraremos esa red y copiaremos sus pesos a una red con propagación hacia adelante en Arduino que permitirá que el coche robot conduzca sólo sin chocar.

La Nueva Red Neuronal

Por simplificar el modelo de aprendizaje, en el post anterior teníamos una red de tres capas con 2 neuronas de entrada 3 ocultas y 2 de salida: giro y dirección. Para este ejercicio haremos que la red neuronal tenga 4 salidas: una para cada motor. Además las salidas serán entre 0 y 1 (apagar o encender motor). También cambiaremos las entradas para que todas comprendan valores entre -1 y 1 y sean acordes a nuestra función tangente hiperbólica. Aquí vemos los cambios en esta tabla:

Entrada:
Sensor Distancia
Entrada:
Posición Obstáculo
Salida:
Motor 1
Salida:
Motor 2
Salida:
Motor 3
Salida:
Motor 4
-101001
-111001
-1-11001
0-11010
010101
001001
110110
1-10110
100110

Siendo el valor de los motores 1 y 0:

AcciónMotor 1Motor 2Motor 3Motor 4
Avanzar1001
Retroceder0110
Giro Derecha0101
Giro Izquierda1010

Para instanciar nuestra red ahora usaremos este código:

Aquí podemos ver el código Python Completo modificado de la Jupyter Notebook. Y también vemos la gráfica del coste, que disminuye a medida que se entrena tras 40.000 iteraciones.

¿¿No es impresionante cómo con apenas 9 datos de entrada podemos enseñar a un robot a conducir??

El coche Arduino

En mi caso es un coche Arduino Elegoo Uno V3 de 4 motores. Si eres Maker, te resultará fácil construir el tuyo o puede que ya tengas uno en casa para programarlo. El coche puede ser cualquier otro, de hecho podría ser de 2 motores y modificando apenas la red funcionaría. En caso de querer construirlo tu mismo explicaré brevemente los requerimientos:

Necesitaremos:

  • Una placa Arduino Uno y una placa de expansión de IO
    • o puede ser una placa Arduino Mega
  • El controlador de motor L298N
  • 4 motores DC (o podrían ser 2) y sus ruedas
  • Servo Motor SG90
  • Sensor Ultrasónico
  • Baterias para alimentar los motores (y la placa obviamente!)
  • Chasis para el coche
  • Cables!

Circuito del coche

No entraré en detalle, ya que va más allá de este tutorial (si a muchos lectores les interesa, podría ampliar el artículo en el futuro) pero básicamente tenemos el siguiente circuito (ignorar el bluetooth y los sensores infrarrojos):

Montar el coche

Utilizaremos un Servo en la parte delantera del coche que moverá al sensor de distancia de izquierda a derecha, a modo de radar, para detectar obstáculos.

Más allá de eso… es un coche! pondremos las 4 ruedas y las placas Arduino encima del chasis. (El objetivo de este artículo es enseñar a programar una red neuronal en la IDE de Arduino)

Este es el video tutorial oficial de ensamblaje de Elegoo de este coche.

Así nos quedará montado… ta taáan:

 

Copiar la red neuronal

Una vez obtenida la red neuronal Python, haremos copiar y pegar de la matriz de pesos en el código Arduino (reemplazaremos las lineas 23 y 24):

Copiamos los pesos que obtenemos en la Jupyter Notebook de nuestra red neuronal en el código Arduino, reemplazando las variables por los nuevos valores.

El código Arduino

El código Arduino controlará el servo motor con el sensor de distancia que se moverá de izquierda a derecha y nos proveerá las entradas de la red: Distancia y Dirección(ó giro).

El resto, lo hará la red neuronal! En realidad, la red ya “aprendió” (en Python) es decir, sólo hará multiplicaciones y sumas de los pesos para obtener salidas. Realizará el camino forward propagation. Y las salidas controlarán directamente los 4 motores.

Hay código adicional para darle ciclos de tiempo a las ruedas a moverse (variable accionEnCurso) y dar más o menos potencia a los motores al cambiar de dirección. Son relativamente pocas líneas de código y logramos que la red neuronal conduzca el coche!

Nota: Para el movimiento del Servo motor se utiliza una librería “Servo” estándard.

Aquí vemos el código Arduino completo. Tal vez la parte más interesante sea la función conducir().

El Coche en Acción!

Conecta tu coche, sube el código y ¡pruébalo!

Veamos un video del coche funcionando con su propia inteligencia artificial en el planeta tierra.

Conclusión

Aplicamos Machine Learning y sus redes neuronales a un objeto del mundo real y vimos cómo funciona, haciendo que el coche evite obstáculos y tome las decisiones por sí mismo, sin haberle dado instrucciones ni código explícito.

Puedes leer aquí sobre Redes Neuronales a lo largo de la historia

Mejoras a Futuro

Tengamos en cuenta que estamos teniendo como entradas los datos proporcionados por un sólo sensor de distancia y un servo motor que nos indica si está a izquierda o derecha. Podríamos tener más sensores de distancia, infrarrojos, medir velocidad, luz, sonido… en fin. Si tuviéramos que programar “manualmente” ese algoritmo, tendría una complejidad enorme y sería muy difícil de mantener o modificar. En cambio, hacer que una red neuronal aprenda sería muy sencillo. Tan sólo agregaríamos features (columnas) a nuestro código  y volveríamos a entrenar nuevamente la red. Voila!. Copiar y pegar los pesos obtenidos en Arduino, y nuestro coche tendría la inteligencia de manejarse por sí mismo nuevamente.

Suscripción al Blog

Puedes suscribirte al Blog y ser el primero en recibir los artículos cada 15 días.

Puedes hacer más ejercicios de Aprendizaje Automático en Python  en nuestra categoría d Ejercicios paso a paso

Recursos

 

15 Replies to “Programa un coche Arduino con Inteligencia Artificial”

  1. Hola, muchas gracias por el interesante artículo y la cantidad de detalle que aportas, pero perdona mi ignorancia. Acabo de iniciarme en estos temas. Lo que no acabo de entender es por qué utilizas una red neuronal y no un sistema de reglas simples tipo if pasa esto then esto

    1. Hola Pedro, gracias por leer el blog y comentar. Pues justamente de eso se trata: de no tener que indicar la instrucciones una por una. El Aprendizaje automático evita que el programador tenga que dictar todas las condiciones “if” y hace que el algoritmo seleccionado tome las decisiones (sean predicciones o clasificacion, etc). Imagina que además de escribir el código par controlar las ruedas del coche y evitar obstáculos, tuviéramos que controlar más sensores: de velocidad, posición, luz, sonido, etc. Eso serían cada vez más y más lineas de código a programar “a mano” y difíciles de mantener en el futuro, y propensas a bugs. En cambio con una -o varias- redes neuronales, podemos hacer que el coche aprenda sólo a controlarse y ajustar su comportamiento, en base a las entrada que obtiene de los sensores.

      1. ok, entendido Na8, gracias por tu respuesta.

        Otra duda más. ¿Por qué programas tu propia red neuronal en lugar de utilizar un módulo como scikit-learn?

        Entiendo que es más un ejercicio que otra cosa porque el resultado debería ser similar si utilizamos scikit-learn

        1. Si exacto, es más que nada para explicar cómo funciona internamente una red neuronal y el backpropagation. En la práctica conviene utilizar -por ejemplo- keras y tesorflow (de Google). Si aún no leíste, puedes ver este artículo anterior a modo ilustrativo:Una sencilla red Neuronal con Keras
          Nuevamente gracias por comentar! Espero que sigas leyendo los nuevos artículos!

  2. Hola, yo tengo el Elegoo V1 y le subí tu programación pero el carro no anda hacia adelante, solo hacia un lado cuando detecta un obstáculo a cierta distancia, que me recomendarías o que solución me darías?

    1. Hola Cristian, gracias por escribirme! Mira, deberías probar variando algunos de los parámetros. PERO casi apostaría que debes aumentar el valor de SPEED que está en 100, prueba con 150 ó 200. Esto es para darle más fuerza, y desconozco si la versión V1 tiene distintas potencias en los motores.

  3. Buenas tardes Cristian, me pasa igual que al compañero anterior. Estoy trasteando e intentando entender el programa,, pero al cargarlo al coche, no avanza por sí solo. Al acercarle obstáculos sí que se mueve, pero por sí solo, no empieza a andar. ¿Habría que modificar algún parámetro de la función conducir? Tengo el V2, ¿podrías ayudarnos? Gracias y enhorabuena por tu gran trabajo, es muy interesante.

    1. Hola Jose, fíjate si puedes modificar el valor de la variable SPEED como le indicaba a Cristian.
      En mi código tiene un valor de 100, pero prueba a darle un valor mayor, (el valor puede ir de 0 a 255).
      Prueba por ejemplo con 200, para comprobar que avanza.
      Si lo haces te pido que escribas luego y me informes si se arregla o no. Gracias!, saludos

      1. Hola Juan Ignacio, acabo de probar con 200 y hace lo mismo pero más rápido. Esquiva bien el obstáculo pero es el obstáculo el que yo muevo hacia el coche, sólo me falta que sea el coche el que avance hacia adelante. Creo que el valor de 100 está bien, debe ser otro parámetro… seguiré investigando. Si sospechas de otra parte que pueda modificar, por favor, avísame. Gracias por tu ayuda!!

        1. Jose, Una pregunta por confirmar: Entiendo que el coche está parado sin moverse, pero que si le acercas un obstáculo, reacciona y hace la maniobra de esquivar.
          ¿Puedes levantar en el aire el coche y confirmar que las ruedas no giran?
          ¿o es que giran en direcciones opuestas y por eso queda frenado?

          1. Hola de nuevo Juan. Acabo de levantarlo del suelo y las ruedas están paradas cuando no hay obstáculo. No se produce contradicción entre ellas al empujar, de hecho, se gira muy rápido al acercar rápido un obstáculo. Cuando lo acerco a los obstáculos o le acerco la mano, se ponen a girar las ruedas de un lado o las del otro y esquiva correctamente, es decir, no llego a poder tocarlo porque se gira o da la vuelta (lento o rápido). Lo que no hace es girar las cuatro ruedas en el mismo sentido y avanzar de frente en línea recta, sólo giran para esquivar el obstáculo (le acerco la mano, lo levanto del suelo y acerco a la pared…) las cuatro ruedas están paradas y para esquivar, giran de un lado haciendo un giro de 90 o 180 grados, por decirlo así. Es como si le faltara tener una velocidad lineal constante de los cuatro motores, que sumada a las velocidad extra (de los motores de un lado o del otro) que le aporta la maniobra de esquivar, y le permitiría hacer el giro a la vez que avanza. Tengo la programación un poco oxidada y me cuesta entender el código, disculpa mi ignorancia y gracias de nuevo por tu tiempo.

  4. Hola, muchas gracias por todos los interesantes artículos y la cantidad de detalle que aportas, la verdad que gracias a vos, todo es mas comprendible me estoy iniciando en estos temas y tengo una duda ahi dice “Una placa Arduino Uno y una placa de expansión de IO o puede ser una placa Arduino Mega” se puede solamente con la placa arduino uno, o necesito la de la expansión si o si. Saludos.

    1. Te contesto rápido (y luego si puedo investigo más a fondo).
      Mi respuesta rápida es que para hacer un coche-robot similar al de mi ejemplo necesitas:
      *controlador para los motores L298N = 6 IO (4PWM y 2 digital)
      *servomotor = 1 IO (PWM)
      *sensor ultrasonico = 2 IO (analógicas)

      Por lo tanto necesitarías 9 IO: 5PWM, 2 digital y 2 analógicas (además de la energía positivo/negativo).

      La placa Arduino Uno tiene 14 IO (6PWM) y 6 Analogicas Por lo tanto te debería alcanzar.

      El pack que yo compré trae sensor de línea, bluetooth, control infrarrojos, por lo que necesita más IO, por eso la placa de expansión

Leave a Reply