Los ojos de mi robota: Utilizar funciones en el Arduino IDE

Una función es un fragmento de código que realiza una tarea específica, a la que llamamos cada vez que necesitamos que se realice esta tarea.

En mi ejemplo, tengo una matriz de leds MAX7219CNG que utilizo como ojos y boca de mi robota humanoide. Entonces programé cuatro funciones:

  • Mirar para adelante: ojosdefrente()
  • Pestañear: pestaneo()
  • Mirar para la izquierda: mirar_izquierda();
  • Mirar para la derecha: mirar_derecha();

En este primer ejemplo sólo utilizaremos funciones que no devuelven ningún valor, por eso comienzan con void, igual que las ya conocidas void setup() y void loop().

Si una función va a devolver un valor, en lugar de void debe comenzar con el tipo de dato que tendrá lo que devuelva, por ejemplo int. En ese caso, la última línea de la función será return y el valor que debe devolver.

Voy a tomar como ejemplo la función “mirar_izquierda”. Comienza con void porque no devuelve ningún valor, pero entre paréntesis declara la variable tiempo. Esa variable tomará el valor que nosotros le enviemos al llamar a la función:

void mirar_izquierda(int tiempo)

Luego, entre llaves, se escriben todas las acciones de esa función. En este caso todas las líneas de código dibujan la cara mirando a la izquierda:

{ lc.setColumn (0, 7, B11100111);
lc.setColumn (0, 6, B00000000);
lc.setColumn (0, 5, B00010001);
lc.setColumn (0, 4, B00110011);
lc.setColumn (0, 3, B00000000);
lc.setColumn (0, 2, B00111100);
lc.setColumn (0, 1, B01000010);
lc.setColumn (0, 0, B00111100);

En la última línea se utiliza la variable que se pasó como parámetro, con un delay:

delay(tiempo); }

Entonces, cada vez que yo necesite que la carita mire hacia la izquierda, puedo escribir simplemente el nombre de la función, y entre paréntesis indicarle el tiempo en milisegundos:

mirar_izquierda(1000)

Aquí el código completo para la carita:

#include "LedControlMS.h"
#define NumMatrix 1 // Cuantas matrices vamos a usar
LedControl lc = LedControl(12, 11, 10, NumMatrix); // Creamos una instancia de LedControl

void setup() {
//matriz de leds
for (int i = 0; i < NumMatrix ; i++)
  {
   lc.shutdown(i, false); // Activar matrices, por si hay más de una
   lc.setIntensity(i, 0); // Poner el brillo a un valor bajo
   lc.clearDisplay(i); // Borrar todo
  }
}

void loop() {
   ojosdefrente(500); 
   mirar_derecha(1000);
   mirar_izquierda(500);
   ojosdefrente(100);
}

void ojosdefrente(int tiempo) {
   lc.setColumn (0, 7, B11100111);
   lc.setColumn (0, 6, B00000000);
   lc.setColumn (0, 5, B01000100);
   lc.setColumn (0, 4, B01100110);
   lc.setColumn (0, 3, B00000000);
   lc.setColumn (0, 2, B00000000);
   lc.setColumn (0, 1, B01000010);
   lc.setColumn (0, 0, B00111100);
   delay(tiempo);
   numeroalazar = random(100); // escribe un número aleatorio de 0 a 300 en la variable 'numAleatorio'
   Serial.println(numeroalazar);
   if (numeroalazar == 10) { pestaneo(); }
}

void pestaneo() {
   lc.setColumn (0, 7, B00000000);
   lc.setColumn (0, 6, B11100111);
   lc.setColumn (0, 5, B00000000);
   lc.setColumn (0, 4, B00000000);
   lc.setColumn (0, 3, B11101110);
   lc.setColumn (0, 2, B01000100);
   lc.setColumn (0, 1, B00000000);
   lc.setColumn (0, 0, B00111100);
   delay(100);
   lc.setColumn (0, 7, B00000000);
   lc.setColumn (0, 6, B00000000);
   lc.setColumn (0, 5, B11100111);
   lc.setColumn (0, 4, B00000000);
   lc.setColumn (0, 3, B00000000);
   lc.setColumn (0, 2, B01100110);
   lc.setColumn (0, 1, B00000000);
   lc.setColumn (0, 0, B00111100);
   delay(100);
}

void mirar_derecha(int tiempo) {
   lc.setColumn (0, 7, B11100111);
   lc.setColumn (0, 6, B00000000);
   lc.setColumn (0, 5, B10001000);
   lc.setColumn (0, 4, B11001100);
   lc.setColumn (0, 3, B00000000);
   lc.setColumn (0, 2, B00111100);
   lc.setColumn (0, 1, B01000010);
   lc.setColumn (0, 0, B00111100);
   delay(tiempo);
}


void mirar_izquierda(int tiempo) {
   lc.setColumn (0, 7, B11100111);
   lc.setColumn (0, 6, B00000000);
   lc.setColumn (0, 5, B00010001);
   lc.setColumn (0, 4, B00110011);
   lc.setColumn (0, 3, B00000000);
   lc.setColumn (0, 2, B00111100);
   lc.setColumn (0, 1, B01000010);
   lc.setColumn (0, 0, B00111100);
   delay(tiempo);
}

Gracias a Prometec por este tutorial en que me basé para el uso básico de la matriz de leds.

Para conocer más funciones de la librería que maneja la matriz de leds, este es un excelente lugar donde buscar referencias.

Matriz de led MAX7219CNG y feliz día a las mujeres en Ciencia y Tecnología

Observando detalladamente la leyenda impresa, se puede ver que la matriz que usé para este video tiene un driver MAX7219CNG

Matriz de leds MAX7219CNG

Gracias a este tutorial de Prometec, en cinco minutos pude usar mi nueva matriz de leds.

Las conexiones:

Indicador en el sensor Conexión en la placa Arduino
VCC se conecta al positivo (5v)
GND va conectado al negativo (GND)
DIN 12
CS 10
CLK 11

El código lo adapté del tutorial de Prometec, donde se incluye el código para varias matrices porque estas matrices pueden conectarse una con otra. En este caso, al tener una sola matriz sería:

#include "LedControlMS.h"
LedControl lc=LedControl(12,11,10, 1);  // Creamos una instancia de LedControl, el último parámetro es la cantidad de matrices

void setup()
   {
     lc.shutdown(0,false);    // Activar matriz número 0
     lc.setIntensity(0,0);    // Poner el brillo bajo a la matriz 0
     lc.clearDisplay(0);      // Borrar la matriz 0
   }

void loop()
   {
        lc.writeString(0,"Feliz Ada Lovelace Day");
        delay(1000);
   }

Y de paso aproveché para felicitar a las mujeres que aportan a la ciencia y la tecnología, en el día de Ada Lovelace:

 

Medir el nivel de agua con Arduino

Hoy utilicé un sensor de nivel de agua con mi nuevo arduino Mega, pero es igual para arduino Uno. La forma de conectarlo es muy sencilla, simplemente tiene tres pines:

Indicador en el sensor Conexión en la placa Arduino
+ se conecta al positivo (5v)
va conectado al negativo (GND)
S a un pin analógico. En mi ejemplo lo conecté a A0

Arduino UNOSensor de nivel de agua
Gracias a este tutorial de Prometec aprendí que alcanza con este sencillo código para ver la medición:

void setup()
   {
       Serial.begin(9600);
   }
 
void loop()
   {
       Serial.println(analogRead(A0));
   }

Utilizando el menú abrimos el monitor serial (en el menú Herramientas), y podemos ver cómo se muestra el nivel de agua:

Monitor serial

No conforme con ver en el monitor serial el resultado, conecté también un display LCM 1602. La explicación de como conectarlo es sencilla:

GND – va a GND

VCC – a 5v

SDA y SCL, en el caso del arduino Mega, va a los pines que tienen ese nombre: SDA y SCL. En el caso del arduino Uno, van a A4 / A5 (aquí, más información)

Una vez realizadas todas las conexiones, este fue el código que utilicé:

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Addr, En, Rw, Rs, d4, d5, d6, d7, backlighpin, polarity
int agua = 0;

void setup()
{
Serial.begin(9600); // para utilizar el sensor de agua
lcd.begin(16,2); // inicializa el display
lcd.backlight(); // enciende la luz del display
lcd.setCursor(0, 0); // acomoda el cursor
lcd.print("Nivel de agua: "); // escribe el texto

}
void loop()
{
lcd.clear(); // borra el contenido del display
lcd.setCursor(0, 0); // acomoda el cursor
lcd.print("Nivel de agua: "); // escribe el texto
lcd.setCursor(12, 1); // acomoda el cursor
agua = analogRead(A0); // guarda en variable valor del sensor de agua
lcd.print(agua); //Escribe en el display el valor del sensor
Serial.println(agua); //Escribe en el monitor serial el valor de agua
delay(50); // espera un poquito antes de continuar

}

Un dato: Al conectar el display, el valor devuelto por el sensor de agua se altera, no vuelve a 0 sino que queda en 8 aproximadamente.

Creando un robot humanoide – paso 1: los brazos

Hoy comencé con el armado de una robota humanoide.
Como primer paso me concentré en el armado de los brazos.
Utilicé dos motores para uno de los dos brazos, basándome en la idea de web-robotica.com

¿Cómo lo hice?
Pegando con cinta, atando con alambre, uní los motores al cuerpo (una botella vacía de lavandina), y conecté los motores de la siguiente manera:

  • Cable rojo: positivo
  • Cable marrón: negativo
  • Cable anaranado: pin pwm

Tomé el ejemplo “sweep” del Arduino IDE y lo modifiqué para tres motores, quedando así:

void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
myservo2.attach(10); // attaches the servo on pin 9 to the servo object
myservo3.attach(11); // attaches the servo on pin 9 to the servo object
}

void loop() {
for (pos = 0; pos <= 90; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(25); // waits 15ms for the servo to reach the position
}
for (pos = 0; pos <= 90; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo2.write(pos); // tell servo to go to position in variable 'pos'
delay(25); // waits 15ms for the servo to reach the position
}
for (pos = 90; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(25); // waits 15ms for the servo to reach the position
}
for (pos = 90 ; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo2.write(pos); // tell servo to go to position in variable 'pos'
delay(25); // waits 15ms for the servo to reach the position
}
for (pos = 90 ; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo3.write(pos); // tell servo to go to position in variable 'pos'
delay(25); // waits 15ms for the servo to reach the position
}
for (pos = 0; pos <= 90; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo3.write(pos); // tell servo to go to position in variable 'pos'
delay(25); // waits 15ms for the servo to reach the position
}
}

Los “ojos” son parte de una lectora de CD que desarmé para sacarle el motor.

Cómo buscar tutoriales de cada pieza de un kit Arduino

Me escribió @analiasoledadm porque no podía avanzar en sus investigaciones, al no encontrar tutoriales de las piezas exactas que venían en su kit Arduino.

¿Y cómo se hace para encontrarlos?

Cada una de las piezas del kit tiene un nombre y un modelo. Al comprar el kit seguramente estaría indicado en una lista, pero suele ocurrir que recibamos la cajita sin más y tengamos que ponernos a trabajar.

Entonces, la solución está en la misma pieza: buscar en google los códigos impresos de cada una de ellas.

Por ejemplo, voy a tomar mi display LCD, pero no uno de los comunes sino uno que vino con algo más:

Modelo del display LCD

Ahora busco el código, y encuentro “LCM 1602”

Lo busco en Google y llego a este posteo en donde se ofrecen las librerías y un ejemplo de código.

Instalo la librería descomprimiéndola en la carpeta correspondiente (en Windows es Documentos / Arduino / Library, en Linux está en la carpeta del usuario, Arduino / Libraries).

Después, en el IDE de Arduino, voy al menú y utilizo la opción para incluir una librería, confirmando que la instalé correctamente (al ver la librería nueva en la lista)

Copio y pego el código propuesto en la página, modificando un poquito el texto. ¡Funciona!

Texto en el displayNota: después encontré de qué manera encender la retroiluminación, me faltaba un jumper así que le puse un cable que conecta los dos pines:

Unir estos dos pines
Unir estos dos pines
Retroalimentación encendida
Retroalimentación encendida

Ahora no sólo le cambio el texto sino que hago alguna prueba más para ver mi texto en movimiento, utilizando un bucle:

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 

void setup() {

  lcd.begin(16,2);

  lcd.backlight();

  lcd.setCursor(0,0);

  lcd.print("Beta Weblog");

}


void loop() { 

  for (int i=15; i>0; i--)

  {

  lcd.setCursor(1,0);

  lcd.print("BETA Weblog");

  lcd.setCursor(i,1);

  lcd.print("Iris Fernandez");

  delay(300);                       

  lcd.clear();

  }

Con backlight

Sin backlight

Utilizando un sensor de Tilt en Arduino

Estoy probando los distintos componentes de mis kits. Esta vez, el sensor llamado Tilt (en inglés Tilt Switch), que consiste en un dispositivo que tiene una pelotita dentro. Cuando la pelotita está en reposo, en determinada posición, hace contacto. Cuando el sensor se inclina la pelotita deja de hacer contacto. Por eso, al sacudir el sensor se oye un sonidito.

Sensor de tilt

Gracias al blog rufian en la red, pude ver cómo se conecta y cómo se programa. Simplemente, se conecta una pata a 5 v, otra a una resistencia y de allí a GND. Y luego en la misma pata de la resistencia, conectamos un pin digital (cable blanco en la foto).

Conexiones para el sensor de tilt

El programa podría ser este (abriendo el “Monitor serial” podemos observar los mensajes):

void setup(){
pinMode(8 , INPUT);
Serial.begin(9600);
}

void loop(){
if (digitalRead(8)){
Serial.println(“El sensor está en vertical”);
}

else{
Serial.println(“El sensor cambió de posición”);
}
}

Y aquí podemos ver en el video cómo el monitor serial muestra el texto “el sensor está en vertical” o “el sensor cambió de posición”, cuando yo lo muevo:

Video en youtube

Armando un auto con motores de lectora de CD

Por suerte conseguí unas lectoras de CD/DVD para desarmarlas y reutilizar algunas piezas. En este caso, los motores. [Aquí la explicación sobre cómo desarmar una lectora de CD/DVD]

Tomé los dos motores, les agregué una tapita de botellón de agua, los conecté a una pila grande (1.5 v), y la cosa anduvo. Pero sin la suficiente fuerza como para que el auto se mueva.

Como “tercera rueda” (normalmente se usa la rueda que gira para cualquier lado, llamada normalmente “rueda loca”), en este caso es un desodorante a bolilla (supuestamente vacío, pero la verdad, nunca está vacío un desodorante a bolilla)

Autito simple con dos motores de CD/DVD
Autito simple visto desde otro ángulo

Así que finalmente reemplacé la pila por una batería de 9v, y ahora sí, mi auto anda (aunque “chueco”, por un defecto en una de las “ruedas”)

[Clic en la imagen para ver el video del autito funcionando]

Video del autito funcionando

Arduino IDE no permite elegir el puerto

Ya van varias veces que me encuentro con este problema: al ejecutar el software para programar Arduino, puedo elegir el tipo de placa pero no el puerto serial. O al descargar un programa, me dice “Permission denied on /dev/ttyACM0”
Gracias a mis alumnas <3 aprendí que casi siempre se trataba de un problema de permisos (otras veces hace falta un driver).

Si el problema es de permisos, en Windows hay que ejecutar el software como administrador.

En Linux hay que darle permisos a los puertos.

Primero una aclaración que puede extenderse leyendo este post sobre permisos: el comando ls realiza un listado, y si lo utilizamos con el parámetro -l nos muestra también los permisos.

En este post se puede leer la forma de solucionarlo en Linux:
1) Listar los nombres de puertos que tienen algo conectado, con el parámetro “-l” que muestra los permisos:

ls -l /dev | grep ACM

Si no aparece ningún resultado significa que no hay dispositivos conectados. Si hay algo, aparece algo así:

crw-rw—- 1 root dialout 166, 0 ene 19 23:40 ttyACM0

Como las letras de read y write aparecen sólo al principio, podemos ver que sólo el usuario root (el máximo administrador del sistema) puede acceder al puerto.

Vamos a agregarle permisos a ese puerto, de tal manera que cualquier usuario pueda utilizarlo:

sudo chmod 777 /dev/ttyACM0

Finalmente, este será el resultado al listar nuevamente los puertos con sus permisos:

crwxrwxrwx 1 root dialout 166, 1 ene 19 23:46 ttyACM0

Obtener el motor de una lectora de CD vieja

Hoy desarmé la primera lectora de CD, y estoy feliz con mi nuevo motorcito!!

Seguí las instrucciones de hacedores.com, aunque no sé si sabré utilizar las otras partes. Sólo me interesa el motor, por ahora.

Primero, quitar la tapa metálica:
Desatornillar la tapa
Sacar la placa

Segundo, presionar las solapitas para desprender la placa:

Desprender la placa

Tercero, continuar desarmando hasta sacar el motorcito:

Quitar todas las partes hasta encontrar el motor Motor de la lectora de CD

Le puse un papelito para poder apreciar el movimiento. Luego, conecté un cable a 5v y otro a GND. Enchufé el Arduino a la compu, y… ¡Anduvo!
Motor conectado a Arduino

También anda con una batería (aunque yo apunto a usarlo con Arduino, esta es otra opción)
Motor y batería

Hacer clic en esta imagen para ver el video del motorcito funcionando:

Video en youtube del motor funcionando

Cómo modificar la velocidad? Este será mi próximo desafío.

Programemos un juego con Arduino

Hoy armé este pequeño ejemplo como base para un jueguito.

La idea del juego final es que haya una fila de leds y otra fila de botones. Como si se tratara de uno de esos juegos donde el cocodrilo abre la boca y hay que pegarle, cada vez que se enciende una luz, hay que pulsar el botón que le corresponde.

Aquí el código para un solo led y un solo botón. Hay que modificarlo para agregarle luces y botones:

  int nroalazar = 1000;

  int puntaje;

  int pulsado = 0;

  int antespulsado = 0;

  int var;

  const int boton = 12;

 


void setup() {

  // creamos variables para el juego

  pinMode(13, OUTPUT);

  pinMode(12, INPUT);

  Serial.begin(9600);

}

 


void loop() {

  // generamos un número al azar

  nroalazar = int(random(1000));

  digitalWrite(13, HIGH);

  if (digitalRead(boton) == HIGH) { pulsado = 1; }

  else { pulsado = -1; }

  puntaje = puntaje + pulsado;

  Serial.print("Puntaje? ");

  Serial.println(pulsado);

  Serial.print("Puntaje acumulado: ");

  Serial.println(puntaje);

  delay(nroalazar);

  digitalWrite(13, LOW);

  delay(1000);

}
Para ver el puntaje en la pantalla de la computadora, debemos activar el “Monitor serial”.