Introduction: Red Neuronal En SparkFun SAMD21 (Arduino Zero)

About: Músico, matemático, computación, ciencia... insolente y subversivo, pero siempre propositivo

El cerebro humano puede ser descrito como una red biológica de neuronas. Estas neuronas forman una gran red de conexiones, y cada neurona recibe entradas de varias otras neuronas, basado en esas entradas se activa la neurona y emite una señal hacia otras neuronas o músculos efectores.

Esa misma idea se puede aplicar para hacer que un robot, a través de un algoritmo, aprenda en tiempo real. Esta idea fue propuesta por McCulloch & Pitts en 1943 (acá el artículo original), y también mas tarde de manera muy similar por Alan Turing. La base de esa idea se le conoce como perceptrón, que se puede decir es la red neuronal más simple, y la unidad fundamental de construcción de una red neuronal. Un perceptrón es un algoritmo para lo que se le conoce como aprendizaje mecánico (inteligencia artificial aplicada al aprendizaje de máquinas). Fue inventado en 1957 por Frank Rosenblatt, y aunque fue inventado para ser algo físico, se implementó a nivel de software, que es lo que vamos a hacer en este instructable.

Más adelante explicaré que es un perceptrón y como pasamos de la idea a una porción de código para hacer un robot que aprenda. Lo importante es que mediante el preceptrón programaremos un algoritmo de aprendizaje mecánico, y la técnica de aprendizaje se llama aprendizaje reforzado, es decir, se dará un "premio" cuando hace algo bien, o un castigo cuando algo hace más, y un mecanismo para corregir y almacenar esa información.

En este instructable aprenderemos a construir un robot, que mediante una red neuronal, aprende a coordinar sus motores para dirigirse y seguir la luz. Utilizamos el SAMD21, que tiene suficiente memoria y velocidad de procesador para poder hacerlo en tiempo real.

Step 1: Materiales

Ocupamos:

  1. SparkFun SAMD21 Mini (en Costa Rica lo encuentran en CrCibernética)
  2. Headears para el SAMD21
  3. Mini breadboard
  4. 2 x Fotoresistores
  5. 2 x Resistencias de 10k Ohmn
  6. 2 x servos pequeños de rotación contínua MG90D
  7. Jumper cables

Step 2: Soldar Headers

Colocar el SAMD21 Mini en un breadboard con los headers acomodados como se muestra en la foto. Soldar uno a uno con mucho couidado, de forma que las soldaduras se vean como volcanes plateados. Acá hay un buen instructable que enseña a soldar

Step 3: Conexiones

Los fotoresistores se conecta haciendo un divisor de voltaje. Como se muestra en la foto, se conecta el foto resistor de forma que un lado va directo a "VCC" en el SAMD21, y la otra va a una resistencia de 10k Ohmn, y también a la entrada analógica "A0" (y A1 para el otro fotoresitor). En la foto se ve con cable verde y azul. La resistencia a su vez está conectada a "GND". Para tener un sensor a cada lado, conectamos los fotoresistores como se muestra en la foto.

Los servo motores, el cable café se conecta a "GND", y el rojo a "Vin". El cable de señal lo conectamos a los pines 6 y 8, como se muestra en la foto (cables blanco y amarillo para servo izquierdo y derecho)

Para la caja con baterías, le agregamos un poco de soldadura a las puntas, el cable rojo lo conectamos a "Vin" en el SAMD21 y el negro a "GND"

Los cables de los servo motores, como son largos, los amarramos con una gaza de plástico.

Step 4: Chasis Y Ruedas

Acá están los archivos de impresión de el chasis y las ruedas. La baterías las pego al chasis con gazas plásticas. A las ruedas, para que tengan mayor tracción, le agregué unas puntas de plástico termo encogible (cuidado de no calentar mucho pues se pueden derretir las ruedas).

Si quieren modifica el diseño, también está disponible en TinkerCad

Step 5: Perceptrón

Como se ve en la imágen, hay tres componentes principales de un perceptrón.

  1. Las entradas,
  2. la función de suma (con el símbolo sigma)
  3. función de activación.

Entradas

Cada entrada x1, x2,... se multiplica por un peso w, y estas se suma tal que: w0(t) = x1*w1+x2*w2+...+xn*wn. Entonces sum, es la suma de cada entrada multiplicada por un peso w.

Función de activación

La función de activación out(t), es una función que toma como valor sum, y entonces, Da como resultado -1 si w0(t) es menor que 0 Da como resultado +1 si w0(t) es mayor o igual a 0.

Step 6: Aprendizaje

El algoritmo de aprendizaje consiste en calcular correctamente los pesos w para obtener el en out(t), que se considera correcto.

En este proyecto en particular tenemos dos entradas que provienen de dos sensores de luz, fotoresistor 1 y fotoresistor 2, que están conectados como se ve en la foto. Digamos entonces que son x1 y x2, respectivamente. A esto hay que agregarle una tercera x3 entrada que dejamos que siempre sea 1 (se conoce como bias), para evitar sumas 0.

Los valores de entrada de los fotoresistores van de 0 a 1023. Entonces, w0(t)=x1*w1 + x2*w2 + x3*w3 La función de activación out(t) hará que el resultado sea -1 o +1.

Noten que se utiliza t para indicar una iteración, pues estos cálculos se realizan una vez por cada loop del procesador.

Ahora bien, digamos que +1 indica a un servo motor moverse hacia adelante y -1 moverse hacia a atrás. Para corregir el movimiento calculamos el error de la siguiente manera, error(t) = deseado(t) - out(t).

Por último, con este error corregimos los pesos w, nuevo w = w + error * x * c donde c, es una constante entre 0 y 1, de aprendizaje, que se ajusta para determinar que tan rápido debe aprender (si es muy rápido a veces nunca se estabiliza). Para cada motor utilizaremos un perceptrón que toma como entrada los dos sensores de luz. Los detalles del código están en el siguiente paso.

Step 7: Código

Acá se encuentra el código completo. El perceptrón fue creado como un objeto en C++. Al revisar en el código encontrarán en el loop principal el algoritmo:

  1. Lee la información de los fotoresistores
  2. Los asigna a las entradas de cada perceptrón (dos perceptrones)
  3. Calcula el movimiento a realizar utilizando feedForward()
  4. Realiza el movimientoEvalua con respecto al deseado, utilizando una función eval(), que indica si el movimiento fue correcto
  5. Se utiliza esa evaluación para la función train() que re-calcula los pesos. La función eval() lo que hace es decir que si el sensor derecho es mas alto que el izquierdo, entonces el motor debería moverse hacia ese sensor, y así de forma recíproca para el otro motor.

Para cargar el código, conecten el SAMD21, y sigan los pasos indicados en la página de SparkFun. Primero presionen "upload" en el ArduinoIDE. La primera vez va a hacer que la luz amarilla del SAMD21 se encienda, eso india que el "bootloade" está listo. Luego presionen una segunda vez (se prende un led verde) y eso carga el código (nota: a veces tengo que presionar upload varias veces hasta que finalmente lo sube).

Step 8: Funcionando

El robot debería aprender en más o menos 30 segundos. Pueden modificar en el código la constante c, que es la que determina que tan rápido puede aprender, pero cuidado, si lo hacen aprender demasiado rápido, puede que comience a oscilar entre diferentes valores, y nunca se estabilicen los pesos. Valores muy pequeños de esa constante, hacen que el robot sea muy lento y no aprenda nunca a coordinar sus motores con los sensores.

Con este robot, pueden probar otro tipo de sensores, sin hace casi que ningún cambio al código.

Acá también se aplica la misma idea, pero con el micro-controlador Edison

Gracias a CrCibernetica.com por facilitar el SAMD21 de SparkFun.

Estos contendidos son creados por www.funcosratica.org para fines educativos