Controlando un Auto Robot con micro:bit y Kitronik: De lo Básico a lo Avanzado

En este post, relataré cómo desarrollé un proyecto en el que controlamos un auto robot utilizando la placa micro:bit y el Kitronik Motor Driver, desde la programación básica hasta el control avanzado mediante el acelerómetro de la micro:bit.

Si bien comenzamos utilizando botones para mover el auto, eventualmente pasamos a un sistema de control más intuitivo, basado en los movimientos del controlador.

Además, abordamos cómo configurar encendido y apagado, múltiples velocidades, y giros durante el movimiento.

1. ¿Qué es la micro:bit y el Kitronik Motor Driver?

La micro:bit es una pequeña placa programable desarrollada por la BBC micro:bit Foundation, diseñada para enseñar a niños y adultos conceptos de programación y electrónica. Es increíblemente versátil, y se puede programar para realizar diversas tareas, desde encender LEDs hasta controlar robots.

Por su parte, la Kitronik Motor Driver es una placa que permite controlar motores de corriente continua (DC) con la micro:bit, lo que la hace ideal para proyectos de robots como el que estamos desarrollando. Más detalles sobre la placa Kitronik se pueden encontrar en su página oficial.

2. Primeros Pasos: Programación Básica con Botones

Materiales

  • Dos micro:bit: una para el controlador y otra para montar sobre el auto robot en la placa de expansión.
  • La placa de expansión Kitronik Compact Motor Driver S/C: 5698 V1.0
  • Un «chasis» (a mejorar) de auto con dos motores DC.
  • Una fuente de energía para la placa controladora (dos pilas 1,5V) y otra para el dispositivo del auto (4 pilas 1,5V).
  • Ruedas

Esquema del dispositvo

Programando en MakeCode

Para empezar, puedes programar la micro:bit usando Microsoft MakeCode, un editor visual que facilita la creación de programas arrastrando bloques de código. Es ideal para principiantes y permite ver rápidamente cómo los cambios en el código afectan el comportamiento de la micro:bit.

Para utilizar los bloques que controlan los motores se debe agregar al proyecto de MakeCode la extensión Kitronik Motor Driver Board.

En el primer paso, programamos los botones A y B de la micro:bit para mover el auto hacia adelante y hacia atrás respectivamente, y programamos la combinación de ambos botones (A+B) para detener el auto.

// Cuando se presiona el botón A
input.onButtonPressed(Button.A, function () {
    // Enciende el motor 1 en dirección hacia adelante con una velocidad de 50
    Kitronik_Motor_Driver.motorOn(Kitronik_Motor_Driver.Motors.Motor1, Kitronik_Motor_Driver.MotorDirection.Forward, 50)
    
    // Enciende el motor 2 en dirección hacia adelante con una velocidad de 50
    Kitronik_Motor_Driver.motorOn(Kitronik_Motor_Driver.Motors.Motor2, Kitronik_Motor_Driver.MotorDirection.Forward, 50)
})

// Cuando se presiona el botón B
input.onButtonPressed(Button.B, function () {
    // Enciende el motor 1 en dirección hacia atrás (reversa) con una velocidad de 50
    Kitronik_Motor_Driver.motorOn(Kitronik_Motor_Driver.Motors.Motor1, Kitronik_Motor_Driver.MotorDirection.Reverse, 50)
    
    // Enciende el motor 2 en dirección hacia atrás (reversa) con una velocidad de 50
    Kitronik_Motor_Driver.motorOn(Kitronik_Motor_Driver.Motors.Motor2, Kitronik_Motor_Driver.MotorDirection.Reverse, 50)
})

// Cuando se presionan los botones A y B al mismo tiempo
input.onButtonPressed(Button.AB, function () {
    // Apaga el motor 1
    Kitronik_Motor_Driver.motorOff(Kitronik_Motor_Driver.Motors.Motor1)
    
    // Apaga el motor 2
    Kitronik_Motor_Driver.motorOff(Kitronik_Motor_Driver.Motors.Motor2)
})

Explicación:
Botón A: Hace que el auto avance al encender ambos motores en la dirección «Forward» con una velocidad de 50.
Botón B: Hace que el auto retroceda al encender ambos motores en la dirección «Reverse» con una velocidad de 50.
Botón A+B: Detiene el auto al apagar ambos motores

Resultados:

Este primer paso permitió que el auto avanzara al presionar el botón A, retrocediera con B y se detuviera con A+B.

3. Control Remoto con otra micro:bit

Objetivo:

En la siguiente etapa, añadimos una segunda micro:bit para que actuara como control remoto mediante el uso de la funcionalidad de radio de la micro:bit. De esta manera, podíamos enviar comandos desde una micro:bit (la controladora) a otra (en el auto).

Código para el control remoto:

// Configura el grupo de radio para la comunicación. El grupo 1 es como un canal que 
// permite que las micro:bits se comuniquen solo con otras que estén en el mismo grupo.
radio.setGroup(1)

// Cuando se presiona el botón A
input.onButtonPressed(Button.A, function () {
    // Envía el mensaje "forward" (avanzar) a través de la radio a otra micro:bit que 
    // esté escuchando en el mismo grupo.
    radio.sendString("forward")
})

// Cuando se presiona el botón B
input.onButtonPressed(Button.B, function () {
    // Envía el mensaje "reverse" (retroceder) a través de la radio.
    radio.sendString("reverse")
})

// Cuando se presionan los botones A y B al mismo tiempo
input.onButtonPressed(Button.AB, function () {
    // Envía el mensaje "stop" (detener) a través de la radio.
    radio.sendString("stop")
})

Explicación:

  • radio.setGroup(1): Configura el grupo de radio a 1, lo que significa que la microenviará y recibirá mensajes de otras microque estén en el mismo grupo (canal).
  • Botón A: Cuando se presiona, envía el mensaje "forward" por radio, indicando a otra microque avance.
  • Botón B: Al presionarlo, se envía el mensaje "reverse", indicando que el auto debe retroceder.
  • Botón A+B: Envia el mensaje "stop" para detener el movimiento.

Código de la micro:bit en el auto:

// Evento que se ejecuta cuando la micro:bit recibe un mensaje de tipo string a través de la radio.
radio.onReceivedString(function (receivedString) {
    
    // Si el mensaje recibido es "forward" (avanzar)
    if (receivedString == "forward") {
        // Enciende el motor 1 en dirección hacia adelante con una velocidad de 50.
        Kitronik_Motor_Driver.motorOn(Kitronik_Motor_Driver.Motors.Motor1, Kitronik_Motor_Driver.MotorDirection.Forward, 50)
        // Enciende el motor 2 en dirección hacia adelante con una velocidad de 50.
        Kitronik_Motor_Driver.motorOn(Kitronik_Motor_Driver.Motors.Motor2, Kitronik_Motor_Driver.MotorDirection.Forward, 50)
    
    // Si el mensaje recibido es "reverse" (retroceder)
    } else if (receivedString == "reverse") {
        // Enciende el motor 1 en dirección hacia atrás con una velocidad de 50.
        Kitronik_Motor_Driver.motorOn(Kitronik_Motor_Driver.Motors.Motor1, Kitronik_Motor_Driver.MotorDirection.Reverse, 50)
        // Enciende el motor 2 en dirección hacia atrás con una velocidad de 50.
        Kitronik_Motor_Driver.motorOn(Kitronik_Motor_Driver.Motors.Motor2, Kitronik_Motor_Driver.MotorDirection.Reverse, 50)
    
    // Si el mensaje recibido es "stop" (detener)
    } else if (receivedString == "stop") {
        // Apaga el motor 1.
        Kitronik_Motor_Driver.motorOff(Kitronik_Motor_Driver.Motors.Motor1)
        // Apaga el motor 2.
        Kitronik_Motor_Driver.motorOff(Kitronik_Motor_Driver.Motors.Motor2)
    }
})

Explicación:

  • radio.onReceivedString: Este evento se activa cuando la microrecibe un mensaje de tipo string a través del radio.
  • Comprobación de los mensajes recibidos:
    • Si el mensaje es "forward", enciende ambos motores hacia adelante con velocidad de 50.
    • Si el mensaje es "reverse", enciende ambos motores en reversa con velocidad de 50.
    • Si el mensaje es "stop", apaga ambos motores, deteniendo el auto.

Este código convierte la micro:bit en un receptor de radio que controla el movimiento del auto robot en función de los mensajes recibidos (avanzar, retroceder o detener).

Resultados:

Este código permitió controlar el auto a distancia, usando una segunda micro:bit como control remoto.

4. Añadiendo Control de Velocidad

Objetivo:

Agregamos la capacidad de cambiar entre tres velocidades, controladas por el botón A. Presionando A una vez, el auto avanzaría lentamente, dos veces lo haría a velocidad media, y tres veces a velocidad máxima.

Código:

// Inicializa la variable 'velocidad' en 0, que será usada para controlar la velocidad del auto.
let velocidad = 0

// Evento que se ejecuta cuando se presiona el botón A.
input.onButtonPressed(Button.A, function () {
    // Incrementa el valor de la variable 'velocidad' en 1.
    velocidad += 1
    
    // Si la velocidad es mayor a 3, se reinicia a 1 para crear un ciclo de tres velocidades.
    if (velocidad > 3) {
        velocidad = 1
    }
    
    // Si 'velocidad' es 1, envía un valor de velocidad de 30% a través de la radio.
    if (velocidad == 1) {
        radio.sendValue("speed", 30)
    
    // Si 'velocidad' es 2, envía un valor de velocidad de 60% a través de la radio.
    } else if (velocidad == 2) {
        radio.sendValue("speed", 60)
    
    // Si 'velocidad' es 3, envía un valor de velocidad de 100% a través de la radio.
    } else if (velocidad == 3) {
        radio.sendValue("speed", 100)
    }
})

Explicación:

  • let velocidad = 0: Se crea una variable velocidad que almacenará los niveles de velocidad.
  • input.onButtonPressed(Button.A, function () {...}): Define qué sucede cuando se presiona el botón A.
  • velocidad += 1: Cada vez que se presiona el botón A, se aumenta la variable velocidad en 1.
  • if (velocidad > 3) { velocidad = 1 }: Si la velocidad supera 3, se reinicia a 1, lo que crea un ciclo entre tres velocidades.
  • radio.sendValue("speed", ...): Dependiendo del valor de velocidad, se envía un valor específico de velocidad (30, 60 o 100) por radio a la microreceptora, que ajustará la velocidad del auto.

Este código controla la velocidad del auto en tres niveles (30%, 60%, 100%) según cuántas veces se presiona el botón A, y luego envía el valor a otra micro:bit encargada de recibirlo y controlar el auto.

Código en el auto para ajustar la velocidad:

// Evento que se ejecuta cuando se recibe un valor a través de la radio.
radio.onReceivedValue(function (name, value) {
    
    // Si el nombre del valor recibido es "speed", se ajusta la velocidad de los motores.
    if (name == "speed") {
        
        // Enciende el Motor1 en la dirección hacia adelante con la potencia especificada por 'value'.
        Kitronik_Motor_Driver.motorOn(Kitronik_Motor_Driver.Motors.Motor1, Kitronik_Motor_Driver.MotorDirection.Forward, value)
        
        // Enciende el Motor2 en la dirección hacia adelante con la potencia especificada por 'value'.
        Kitronik_Motor_Driver.motorOn(Kitronik_Motor_Driver.Motors.Motor2, Kitronik_Motor_Driver.MotorDirection.Forward, value)
    }
})

Explicación:

  • radio.onReceivedValue(function (name, value) {...}): Define qué hacer cuando la microrecibe un valor por radio. Los valores enviados contienen un nombre (name) y un valor numérico (value).
  • if (name == "speed") {...}: Comprueba si el nombre del valor recibido es "speed", lo que significa que se envió una actualización de la velocidad.
  • Kitronik_Motor_Driver.motorOn(Kitronik_Motor_Driver.Motors.Motor1, Kitronik_Motor_Driver.MotorDirection.Forward, value): Enciende el Motor1 hacia adelante con la velocidad especificada por value. Este value es el número enviado por la microemisora, representando la velocidad (30, 60, o 100, por ejemplo).
  • Kitronik_Motor_Driver.motorOn(Kitronik_Motor_Driver.Motors.Motor2, Kitronik_Motor_Driver.MotorDirection.Forward, value): Hace lo mismo para el Motor2, ajustando su velocidad a la misma que la del Motor1.

En resumen, este código recibe una señal por radio con un valor que representa la velocidad y ajusta ambos motores del auto a esa velocidad, dirigiéndolos hacia adelante.

Comentarios finales

Sin dudas que hay muchas cosas por mejorar, por ejemplo el chasis del auto, la manera en la que van aseguradas sobre él la caja de las pilas y las placas. Se podría montar la placa controladora sobre un guante… lo que imagines.