arduino

1.3 Semáforo doble con cruces peatonales

Semáforo doble con cruces peatonales en Arduino

Último post sobre simulación de semáforos en Arduino. En este ejercicio veremos cómo simular el comportamiento de un semáforo doble (o dos semáforos) que tienen además un cruce peatonal.

En total vamos a usar 10 leds: 3 para el semáforo 1, 3 para el semáforo 2 y finalmente 4 para los dos cruces peatonales (verde y rojo)

El ejercicio anterior trató sobre un semáforo doble en Arduino; el presente es la “continuación” del mismo.

Continue reading…

1.2 Semáforo doble en Arduino

Semáforo doble en Arduino

Esta es la parte 2 de los ejercicios de Arduino con leds. En este caso veremos cómo simular el comportamiento de un semáforo doble con cruce.

Vamos a agregar otros 3 leds de manera que ahora sean 6; el código será muy parecido al del semáforo simple.

Nota: vamos a usar delay, si no quieres usar delay pásate por este post para que veas cómo se puede simular sin esa función.

Recuerda que anteriormente vimos cómo simular únicamente un semáforo.

Continue reading…

1.1 Semáforo simple

Semáforo en Arduino sin delay

Hace algún tiempo vimos cómo simular un semáforo con 3 leds en Arduino, en donde usamos delay. En este post veremos exactamente lo mismo, pero con una condición: no usar delay.

El enfoque que hoy veremos servirá para otros proyectos en donde no podemos usar delay, por ejemplo, en uno en donde debemos escuchar el botón presionado de un teclado pero además debemos usar el tiempo de alguna manera (en un cronómetro por poner una referencia).

Continue reading…

1.1 Semáforo simple

Semáforo simple con Arduino y LEDs

Vamos a simular un semáforo en Arduino usando 3 leds de color rojo, amarillo y verde. También vamos a usar resistencias para evitar desgastar a los mismos, y obviamente código Arduino para encenderlos y apagarlos.

Lo que repasaremos con esta práctica es:

pinMode – Para establecer si un pin será de salida o entrada

digitalWrite – Apagar o encender un LED con Arduino

Continue reading…

Juego de batalla naval con Arduino, LCD y comunicación serial

Introducción

No hace mucho me fue encargado un pequeño proyecto en donde tenía que simular el juego de una batalla naval usando un Arduino, dos módulos USB a TTL, algunos leds controlados con un 74hc595 y una LCD con el módulo I2C.

Trataré de ser lo más específico posible y no omitir ningún detalle.

Recuerda que todo esto es modificable, y con un poco de tiempo puedes adaptarlo a muchos otros escenarios. Por ejemplo, puede que no necesites los leds, o que en lugar de USB a TTL utilices Bluetooth, etcétera. Todo queda en ti.

Funcionamiento

Los barcos los ubicaría el jugador 1 (con coordenadas) e irían apareciendo sobre la LCD. Cada que se ubicaba uno de estos, se encendía un led indicando que el barco “estaba vivo”. Después, el jugador 2 trataba de darles sin ver la pantalla, usando al igual que el jugador 1, la comunicación serial.

Si le daba a un barco, el led que indicaba su estado se apagaba. Pero por ejemplo, para los que ocupan muchos espacios (es decir, los barcos grandes como submarinos, portaaviones, etcétera) se les tenía que destruir por completo para que su led se apagase.

El usuario 2 tenía 18 intentos para derribar todos los barcos. Ganaba si los desaparecía antes de que sus intentos se acabasen.

Adicional a esto, un buzzer sonaba indicando éxito o error en cada disparo. Y dichos disparos se marcaban en la LCD.

Materiales

  • Arduino UNO, o cualquier equivalente. (Lo he probado sólo con MEGA y UNO)
  • Pantalla LCD de 20 x 4 (o de 16 x 2) – para dibujar el escenario
  • Módulo I2C para LCD – para ahorrar cables
  • 7 leds – para el estado de los barcos
  • 7 resistencias –  para dichos leds
  • 1 Circuito integrado 74hc595 – para controlar los leds
  • Un buzzer – para indicar error o éxito
  • 2 módulos USB a TTL – uno a la pc del jugador 1. El otro a la del jugador 2

Requisitos

Tienes que saber la dirección del módulo I2C para la LCD, y también debes tener instalada la librería. Para ello, y para no hacer largo este post, separé esto en otros tutoriales:

Una vez que hayas leído eso, podemos continuar.

Paso 1: El escenario

El juego en sí no es complicado. Básicamente es un arreglo en donde estaremos cambiando los valores. Me decidí por un arreglo de tipo char, porque se me hace ligero y a su vez perfecto para los usos que le daremos.

Para comenzar vamos a definir la altura y anchura (o como se diga) del escenario; es decir, del arreglo, que debe medir lo mismo que nuestra LCD.

Si nuestra LCD es de 16×2, el arreglo será de 16×2. Si es de 20×4, el arreglo será de 20 x 4.

De todas maneras, haremos modificables las medidas. Así, primero podemos probar con una LCD pequeña, la de 16×2, que es la más popular. Y después, cambiar las constantes y conectar una de 20 x 4 u otras medidas.

Pero dejemos de hablar y veamos el código del escenario y las constantes que usaremos para pintar el arreglo, ya que los valores que habrán dentro de éste serán unos, y los que mostraremos al usuario final en la LCD serán otros:

Carguemos ese código a nuestra tarjeta, conectando a esta la LCD a través del módulo I2C. Veremos algo así:

¿Y eso es todo? claro que sí, no se ve a simple vista, pero el escenario ya está pintado. No se nota nada, porque declaramos la constante AGUA en un espacio en blanco.

Pero hagamos un experimento, cambiemos la constante AGUA y en lugar de ese espacio pongamos un punto (.), compilemos y veamos lo que sucede:

 Si el lector no se ha dado cuenta, esto sirve de muchas cosas. En primer lugar ya vimos que gracias a las constantes podemos cambiar la forma en la que el usuario observa el juego.

Por otro lado, se ve la utilidad de la constante DEBERIA_IMPRIMIR_LETRAS, pues si está en true nos mostrará detalladamente el escenario, no sólo cosas transparentes.

Muy bien, con esto ya tenemos una pequeña parte. Ahora veremos cómo modificar ese arreglo, parsear coordenadas, encender leds, apagarlos, y finalmente cómo llamar a estos métodos escuchando el puerto Serial.

Paso 2: la ubicación de los barcos | coordenadas

Como lo dije arriba, haremos que esto sea flexible. Así que crearemos funciones que sin importar de dónde vengan los datos, funcionarán.

Para ello, declararemos una función para poner determinado barco en determinada coordenada. Como estamos trabajando realmente con un arreglo, las coordenadas son índices o posiciones del mismo. Y como estamos pintando exactamente ese arreglo en la LCD, sólo tenemos que actualizar el dato y dibujar. ¿Inteligente, no?

Pedir coordenadas de barcos

Comenzaremos pidiendo la ubicación de cada barco. No me gusta mucho esta parte del código, me habría gustado hacerla un poco más independiente del número de barcos.

Recordemos que el usuario introducirá las coordenadas a través de la comunicación serial, ya sea utilizando el Monitor serial que el IDE de Arduino provee, u otro.

Como dijimos que se utilizarán 2 comunicaciones seriales, tenemos que escuchar a una u otra. Escuchamos entonces a la del jugador uno. Mandamos un mensaje de bienvenida y comenzamos a pedir las ubicaciones:

Es importante notar la línea que dice:

while (!serialJugadorUno.available());

Sin ella, no habría podido esperar a que el usuario introdujera las coordenadas. Lo que hace ese fragmento es pausar el programa indefinidamente, hasta que haya algo que leer en el Serial. También están los métodos encenderLedDeesCoordenadaValida e intentarDibujarBarco, que veremos más abajo.

Comprobar coordenadas válidas

De este método me siento muy orgulloso, me gustó la manera en la que lo hice. Primero verifica si existe una coma en la cadena. En caso de que no, de una vez regresamos falso.

En caso de que sí, la cortamos. X sería lo que hay desde la posición 0 hasta en donde hayamos encontrado la coma. Y sería desde donde encontramos la coma, hasta el final de la cadena.

Acabo de darme cuenta de que cuando lo hice (que por cuestiones de tiempo no pude arreglar, jaja) había un error al parsear las coordenadas si ponía length – 1. Pero al poner length – 2, todo iba bien. Creo (y sólo creo) que es porque hay un salto de línea por ahí. Y si no, igual no importa.

Bueno bueno, luego comprobamos si la coordenada es un número, para ello utilicé una función que encontré en internet.

Finalmente, la última prueba es que las coordenadas estén en el rango de la LCD. Es decir, que X no sea menor que 0 ni mayor que la longitud de la pantalla. Y para Y lo mismo. ¿Ya vieron cómo las constantes que declaramos nos siguen ayudando?

Dibujar un barco

Este método también fue difícil de hacer. En las instrucciones no especificaba cómo debería ir el barco. Veamos un submarino, creo que ocupa 3 espacios. ¿Cómo los iba a ocupar? ¿Se iba a extender hacia la derecha, hacia arriba, abajo o a la izquierda?

Para eliminar todas estas dudas, hice una función que primero dibujara el barco de derecha a izquierda. Luego hacia abajo, izquierda y finalmente hacia arriba. Si no podía dibujarlo, entonces regresaba false, pues ya estaban ocupadas esas posiciones o el barco no cabía.

También es importante notar el método estaVacioEn que como su nombre lo dice, te indica si no has ocupado una coordenada.

Para dibujar:

Y el método para ver si está vacío:

Espero que el lector se dé cuenta de que las constantes siguen siendo de gran ayuda. Utilizamos de nuevo las que indican las medidas de la pantalla, y también la constante AGUA.

Paso 3: Encender y apagar LEDS

¿Ya dije difícil? bueno, este método también es difícil.

Encender un LED es una de las cosas más simples en el mundo de Arduino, de hecho es casi como el Hola mundo. La pequeña diferencia es que en este caso se tenía que utilizar un circuito integrado 74HC595, del cual ya he hablado.

Lo que tenía que estar modificando era un byte. Sí, un byte, de esos que tienen 8 bits. Y cada que encendía o apagaba un led, tenía que recorrerlo y utilizar bitSet para cambiar el valor de 0 a 1. Luego, llamaba a refrescarLeds para que por medio de shiftOut se escribiera el valor en el integrado.

Para encender determinado led:

Para apagarlo:

Y el que refresca los leds es:

Las constantes nos siguen ayudando. Y ya con esto se acaba el turno del jugador 1.

Paso 5: Alisten, Apunten, ¡Fuego!

Ahora va el jugador 2. Escuchamos la conexión serial 2, le pediremos igualmente una coordenada, reutilizando los métodos que vimos más arriba para validarlas y todo eso.

Comenzamos imprimiendo los intentos restantes. Dichos intentos son el resultado de  restar a una constante (que podemos aumentar o disminuir según sea el caso) el valor de una variable. Dicha variable son los intentos que el usuario ya ha hecho.

Si se agotan los intentos, pierde. Si no, pues no.

Vemos que hay una variable booleana para restar o no el intento. Esto es porque, si el usuario pone una coordenada mal, no se le resta intento. Tampoco si le dispara a un lugar en donde había disparado antes.

Encerramos todo en un ciclo infinito, que será roto únicamente cuando se acaben los intentos o se destruyan todos los barcos. Veamos ahora los métodos que no he explicado.

Comprobar a qué cosa se disparó

Para esto utilizamos el método disparar y obtener objetivo. El método es simple y explicativo. Simplemente te dice a qué lugar disparaste, y dependiendo de ello puedes marcar un disparo acertado, o no hacerlo. También ayuda a saber si se tiene que restar o no un intento.

Por cierto, este método es inseguro, ya que no comprueba que las coordenadas son válidas por sí mismo, sino que confía en que alguien más lo haya hecho por él. Y claro, lo hicimos nosotros antes de llamarlo.

Marcar e indicar disparos acertados o erróneos

Ya casi olvidaba que tenemos un buzzer que indica si acertamos o no. Para marcar el disparo, simplemente ponemos el valor de la constante en esa posición del arreglo. Igual por si fue erróneo.

Y hay otros dos métodos que sirven para hacer sonar al buzzer. Aquí el código de todo:

Comprobar si quedan partes de un barco

Tomando de nuevo como ejemplo al submarino, vemos que ocupa muchos espacios. Si le damos con un disparo, se hundirá una parte de él, pero no lo hemos vencido. Es decir, si ocupa 3 espacios y le damos a uno, quedarán 2 en donde seguirá vivo.

¿Y qué significa esto? que no podremos apagar el LED hasta que se haya hundido completamente. Y tampoco contará como barco derribado si no lo hundimos completamente.

Para ello, existe el método hayMasInstanciasDe, que como su nombre lo dice, comprueba si quedan todavía algunos (aunque sea “heridos”) espacios ocupados por determinado barco. Aquí el código:

Indicando victoria o fracaso

Ya para terminar todo este código, dependiendo de cómo haya jugado el jugador indicamos la victoria o su fracaso. El código es muy simple, sólo imprime mensajes para ambos jugadores.

Y el juego se queda así hasta que el Arduino se reinicia. Si quisiéramos que se repita una vez que pierde o gana, pondríamos lo que está en el setup dentro del loop.

Paso 6: código fuente completo

Para que no andes copiando y pegando parte por parte, aquí dejo el código que compone al Sketch. Recuerda que puede tener errores.

Paso 7: Circuito en fritzing

Hice el circuito para un Arduino UNO, pero se puede modificar fácilmente para cualquier otro modelo. El círculo negro a la derecha es el buzzer.

Circuito de batalla naval en Arduino, diseñado con Fritzing

Circuito de batalla naval en Arduino, diseñado con Fritzing

Conclusión

Hemos terminado. Si tuve errores en el código, o tienes algunas dudas, no dudes en comentar. Cabe mencionar que podemos utilizar una LCD de 16 x 2, o de 20 x 4, o como sea mientras se pueda controlar con el módulo I2C.

En caso de que cambiemos la medida, también tenemos que cambiar las constantes en el código fuente.

Ejemplo de Arduino y LCD con el módulo I2C

Introducción

El módulo I2C para la LCD viene genial cuando queremos ahorrar pines de Arduino. Así, solamente utilizamos 2 pines de datos y 2 de alimentación, ahorramos conexiones y esfuerzo.

De tantas librerías que existen y tantos tutoriales desactualizados me decidí a escribir uno nuevo que funcione completamente, tenga ejemplos y tome una librería confiable, incluida en los repositorios oficiales de Arduino.

Componentes necesarios

  • Una LCD de 16×2, 20×4 o cualquiera que sea compatible
  • Un módulo I2C
  • Un Arduino
  • Cables

Instalando librería

Comencemos con la parte del software. Abriremos nuestro software de desarrollo y en el menú navegamos a Programa > Incluir Librería > Gestionar Librerías:

Aparecerá una ventana después de cargar un momento. Ahora, en el cuadro de búsqueda escribimos “Liquidcrystal_i2c“, esperamos a que los datos se filtren e instalamos la librería llamada LiquidCrystal I2C creada por Frank de Brabander. Si no aparece al inicio, bajamos hasta encontrarla.

En mi caso ya la tengo instalada, pero si no la tenemos simplemente hacemos click en el botón que dice “Instalar”:

Con ello ya tenemos instalada la librería. No es necesario reiniciar ni nada por el estilo; es hora de trabajar.

Preparando Arduino y conexiones

Antes de programar, debemos armar. Aquí dejo el circuito en Fritzing, espero que se explique por sí mismo.

En este caso lo dejo para el Arduino MEGA pero puedes ver este otro post en donde conecto el módulo I2C al UNO y al Arduino Leonardo, lo único que cambia son los puertos.

Programando Hola mundo

Para proseguir con este tutorial, necesitamos la dirección hexadecimal de nuestro módulo I2C, es algo como 0xFF, pero para no intentar adivinara podemos ver este post en donde explico cómo obtenerla.

Es importante tenerla, ya que sin ella no podremos seguir.

Ahora veamos el código para imprimir un hola mundo:

Resultados

Verificamos las conexiones, cargamos el código a la tarjeta y si todo va bien, debe mostrarse algo así:

Si no funciona, por favor recuerda verificar la dirección del módulo I2C, que seguramente no será la misma que aparece en el código. También recuerda revisar los cables y las conexiones minuciosamente; todo puede fallar.

Obtener dirección de módulo I2C para LCD con Arduino

Introducción

Si queremos usar el módulo I2C para conectar nuestra LCD y ahorrar cables, es necesario (en la mayoría de casos) saber la dirección hexadecimal de dicho módulo. Dicha dirección puede (y siempre lo hace) variar.

Para ahorrarnos los problemas, alguien más hizo un sketch en Arduino que prueba con todas las direcciones posibles y en caso de encontrar algún dispositivo I2C nos avisa.

Hoy veremos cómo usar dicho sketch. Por cierto, lo encontré aquí, créditos a su autor.

Conexión

La conexión es simple. Un pin va a tierra, otro a voltaje positivo. Los otros dos son SCL y SDA. Lo que varía son estos dos últimos pines. Aquí mostraré la conexión para Arduino MEGA, UNO y Leonardo.

Arduino MEGA

  • SCL: Pin 21
  • SDA: Pin 20

Imagen de Fritzing:

Arduino UNO

  • SDA: Pin A4
  • SCL: Pin A5

Imagen de Fritzing:

Arduino Leonardo

Los pines SCL y SDA están marcados con esas leyendas. De todos modos dejo la imagen de Fritzing:

Código y modificaciones

Le hice algunas modificaciones al código original. Para comenzar, lo traduje al español y reduje el tiempo de espera en cada iteración. También lo puse en un gist de GitHub para que cualquier persona pueda copiarlo, pegarlo en el editor de Arduino y subirlo a la tarjeta.

Nada de zips, nada de “Descarga esta librería” y cosas de esas. Simplemente pega el siguiente código en tu editor:

Una vez subido al Arduino, abre el monitor serial con Ctrl + Shift + M y se verá algo así:

Así estará infinitamente. Si dice que no se encontró ninguno, por favor verifica la conexión. Ya con la dirección podemos pasar ahora sí a trabajar con una pantalla LCD que usa este módulo.

Recuerda que la dirección es tal cual la manda, por lo que en mi caso es 0x3F. Es esencial copiar tal y como está dicha dirección.

Módulo I2C para Arduino con Fritzing

Introducción

Este es otro post en donde expongo cómo encontrar un componente. En este caso se trata del módulo I2C que tiene 4 pines, dos para alimentación y 2 de datos (SDA y SCL).

Por más que busqué en Fritzing “i2c” no encontré nada, pero buscando en Google me topé con un proyecto en donde se usaba. Lo descargué, vi el nombre del dispositivo, y aquí lo vengo a contar.

I2C en Fritzing

El módulo, para ubicarlo en Fritzing, se tiene que buscar como “lcm 1602 iic” así:

Con eso ya tenemos. Ahora podemos arrastrarlo:

Lo que más me gustó es que tiene todos los pines necesarios para representar exactamente lo que queremos. Incluso tiene los que van conectados con un jumper. También ofrece los de alimentación y datos.

Finalmente cabe aclarar que es una imagen ilustrativa de los pines que tiene virtualmente y cómo podemos conectarlos con cables para realizar un diagrama lo más parecido a lo físico.

Nota: no conecté todos los pines de la parte superior porque sería laborioso y no tendría sentido.

Descargar, instalar y configurar fritzing

Introducción

Fritzing es un programa libre de automatización de diseño electrónico que busca ayudar a diseñadores y artistas para que puedan pasar de prototipos (usando, por ejemplo, placas de pruebas) a productos finales.

Fritzing fue creado bajo los principios de Processing y Arduino, y permite a los diseñadores, artistas, investigadores y aficionados documentar sus prototipos basados en Arduino y crear esquemas de circuitos impresos para su posterior fabricación.

Además, cuenta con un sitio web complementario que ayuda a compartir y discutir bosquejos y experiencias y a reducir los costos de fabricación. y su diseño de arte de artistas.

Personalmente lo ocupo para diseñar circuitos de Arduino, ya que tiene muchos componentes. Además, nosotros podemos crear los nuestros. Es gratuito y puede exportar a imagen, PDF, etcétera.

Descargar

Vamos a la página de descargas: Click aquí

En la siguiente página seleccionamos No donation y hacemos click en Download:

 

Ahora nos llevará a otra página en donde vamos a elegir nuestro sistema operativo. Si tenemos Windows o Linux podemos elegir entre 32 y 64 bits. Si tenemos MacOS X sólo tenemos una opción.

En mi caso la descargaré para Windows de 64 bits. Es un archivo comprimido que podemos extraer con nuestro software de compresión favorito.

Extraer

Recomiendo extraerlo en C:\fritzing para tenerlo como un programa normal

Creando acceso directo

Cuando haya terminado podemos abrir la carpeta que elegimos para extraerlo y dentro habrá una carpeta llamada fritzing.0.9.3b.64.pc o algo parecido.

Entraremos a ella y dentro veremos muchos archivos, aunque sólo nos importa el ejecutable, ya que lo demás son componentes y librerías:

Con un recuadro azul marqué la aplicación. Ahora podemos crear un acceso directo a ella o anclarlo al inicio o a la barra de herramientas.

Y finalmente podemos abrirlo:

Actualizaciones

Cuando haya actualizaciones el programa nos avisará y se actualizará. No necesitaremos intervenir mucho en el proceso. Aunque realmente casi no se actualiza, ya que la última versión estable es del 2016.

De todos modos, en cada actualización hay que asegurarnos de tener nuestros prototipos y diseños en una carpeta separada.

 

 

Diferencia entre #define y const en Arduino

Introducción

Las constantes; como sabemos, no cambian su valor en tiempo de ejecución. Son útiles para prevenir que nosotros mismos tengamos errores.

En el lenguaje de Arduino, que no es otra cosa que C y C++, podemos declarar constantes usando #define y también const. Cada una de ellas tiene su explicación.

#define

Es un macro que se ejecuta antes de la compilación. Para explicarlo de la manera más sencilla, supongamos que definimos lo siguiente:

#define NUMERO 1

void setup(){
  pinMode(NUMERO, OUTPUT);
  digitalWrite(NUMERO, HIGH);
}

Antes de que el código sea compilado, se hará un buscar y remplazar, en donde las ocurrencias serán (valga la redundancia) remplazadas por el valor verdadero. Por lo que (no podemos verlo, pero así es), el programa de arriba se convertiría en lo siguiente:

void setup(){
  pinMode(1, OUTPUT);
  digitalWrite(1, HIGH);
}

Es decir, remplazó las constantes por el valor verdadero.

Ventajas

  • No ocupa memoria para almacenar las constantes, puesto que son remplazadas por sus valores
  • Si vamos a usarlo para cosas pequeñas, como definir un pin, una cadena, etcétera, nos viene genial

Desventajas

  • No tienen tipo. Por lo que el compilador no podrá avisarnos si algo estamos haciendo mal
  • Son globales, por lo que debemos ser sumamente cuidadosos al referirnos a ellas

 

Const

Para declarar una constante, usamos const seguido del tipo de la variable. Por ejemplo:

const int numero = 1;

Al compilar, esto no se remplaza. Queda así como está. Y si el compilador detecta que en algún momento de nuestro código queremos asignarle un nuevo valor nos arrojará un valor.

Ventajas

Obedecen el ámbito de las funciones. Es decir, podemos declarar dos constantes con el mismo nombre en diferentes funciones:

void funcionUno(){
  const int edad = 18;
}

void otraFuncion(){
  const int edad = 50;
}

Y podemos usarlas dentro de cada función sin que choquen. También tiene la ventaja de que tiene tipo, por lo que el compilador nos informará los errores que puede que estemos cometiendo.

Const también permite declarar arreglos, cosa que #define no.

Finalmente, cabe mencionar que el uso de const es recomendado en lugar de #define según este artículo.

Conclusión

Personalmente utilizo #define porque no trabajo en proyectos grandes, y las librerías que incluyo no chocan con el nombre de mis constantes.

Sin embargo, es una buena práctica usar const en lugar de #define según el sitio oficial de Arduino. Y si ellos lo dicen, es porque así debería ser. Además, en la mayoría de casos tenemos memoria de sobra para los proyectos que hacemos, por lo que no tenemos que ahorrarla usando #define.

Arduino – Imprimir byte en serial

Introducción

Estuve trabajando en un proyecto en donde se tenían que encender algunos leds usando un registro de corrimiento 74HC595, y para depurar necesitaba imprimir el byte completo (incluyendo ceros a la derecha). Como no encontré una manera correcta de hacerlo (aunque seguramente existe) hice una propia

Función

Para imprimir una variable de tipo byte, bit por bit, podemos usar la siguiente función:

void imprimirByte(byte b){
  for(byte x = 0; x < 8; x++) Serial.print(bitRead(b, x));
}

Lo que hace es imprimir en el monitor serial el byte completo. Como argumento recibe un byte y no regresa nada. Para llamar al procedimiento, podemos hacerlo así:

byte miByte = B00110011;
imprimirByte(miByte);

La salida sería:

00110011

Alternativa

También podemos simplemente imprimirlo con Serial.println() y pasarle como segundo argumento el formato BIN. Es decir, algo así:

Serial.println(miByte, BIN);

Referencias

Serial.println

Leer más sobre bitRead

Char a Int en Arduino

Si queremos convertir un char a entero en Arduino, podemos usar:

char c = '5';
int convertido = int(c);

El resultado sería el número 53, porque el número 5 es el carácter ASCII número 53. Nosotros no queremos eso, nosotros esperábamos un que ‘5’ se convirtiera en 5. Para obtener lo que realmente necesitamos, podemos usar lo siguiente:

char c = '5';
int convertido = String(c).toInt();

Ahora sí, el resultado sería 5 como entero. De esta forma podemos convertir carácter a entero, e incluso String a entero.

Invertir cadena en Arduino

Introducción

Recientemente tuve la necesidad de girar o invertir una cadena en Arduino. Así que hice una pequeña función que toma como parámetro un String y devuelve una variable del mismo tipo cuyo valor es el de la otra cadena, pero invertida.

Definición de la función.

String invertirCadena(String s) {
  String temporal = "";
  for (int m = s.length() - 1; m >= 0; m--)
    temporal += s[m];
  return temporal;
}

El algoritmo es sencillo y tal vez un poco lento, pero funciona. Básicamente se crea una cadena vacía que será llamada temporal. Luego, recorremos la original de derecha a izquierda y vamos concatenando el carácter con la temporal. Finalmente, la devolvemos.

Invocación

Para invocar o llamar a la función, podemos hacerlo así:

String cadenaInvertida = invertirCadena("aloH");

El resultado de arriba sería la palabra Hola.

Espero que esto haya servido.

Configurar HC-05 bluetooth sin TTL con Arduino y modo AT

Introducción

Cuando conseguimos un módulo bluetooth HC-05 siempre será necesario cambiar el nombre y la contraseña. En casos más avanzados, vamos a necesitar incluso cambiar el modo (esclavo o maestro). Me he topado con muchos tutoriales por ahí, todos varían y algunos piden un módulo USB a TTL.

Al final de todo logré entrar en modo AT para configurar mi módulo. Y no necesité otra cosa más que un Arduino, el propio módulo y el cable con el que se suben los programas al Arduino.

Dicho esto, comencemos.

Pequeña nota: este tutorial supone que tenemos el módulo que se muestra en la imagen de abajo. Dicho módulo trae 6 pines y no trae bien especificado el pin KEY. Aunque si el nuestro sí lo trae, esto debería funcionar, sólo tendríamos que conectar el pin de configuración (9) al de la KEY en lugar del 34.

Materiales

Los acabo de mencionar arriba, pero aquí los dejo de nuevo

  • Cables dupont
  • Módulo Bluetooth HC 05
  • Arduino UNO (o cualquier otro; no he probado pero debería funcionar)

Circuito

El circuito no es nada complejo; no pude hacerlo en tinkercad ya que no existe ese módulo, pero en Fritzing sí lo tienen, así que aquí está:

Observemos algunas cosas…

  • Lo primero que quiero que se note es que el cable amarillo va al pin 34 del módulo bluetooth. Si somos valientes, podemos soldarlo (pero qué pereza y dificultad), y si no, simplemente lo tenemos que mantener ahí para que haga contacto. Le podemos pegar un cable con cinta, o algo que se nos ocurra; de todos modos, sólo será para entrar al modo AT.
  • El RX y TX van a cada pin del Arduino. Notar por favor que esos pines pueden ser cambiados desde el código que se detalla más abajo.
  • EL GND va a tierra y el VCC va a los 5 voltios. Ojo con este de VCC, ya que para configurar tendremos que desconectarlo y hacer unas cosas con él. Explicaré esto más abajo, pero no está de más recalcar que éste cable será el que estaremos moviendo.
  • Finalmente, el pin que dice EN no van a ningún lado. Al menos no para esto.

 

Programando Arduino para programar módulo

Lo primero que tenemos que hacer es subir un pequeño sketch a nuestro Arduino para comunicarnos directamente con el HC-05. Nuestro Arduino simplemente actuará como medio para enviar y traer los datos. Aquí les dejo el código:

/*
 * Configurar módulo Bluetooth HC-05 modo AT
 * parzibyte.me
 * 
  Asignación de pines

  Recordemos que el RX es el pin de Arduino que va conectado al RX del módulo bluetooth
  Y el TX es el pin que va al TX del módulo bluetooth

  El pin configurador es aquel que nos ayudará a que nuestro módulo se ponga
  en modo AT. Es el que va conectado al pin 34 del HC-05
*/

#define PIN_RX 11
#define PIN_TX 10
#define PIN_CONFIGURADOR 9
#include <SoftwareSerial.h>

SoftwareSerial serialBt(PIN_RX, PIN_TX);

void setup() {
  Serial.begin(9600); //Comenzar serial para monitor serial del IDE de Arduino
  pinMode(PIN_CONFIGURADOR, OUTPUT); digitalWrite(PIN_CONFIGURADOR, HIGH); //Poner en alto el pin configurador
  Serial.println("Estamos listos. Ingresa un comando AT:");
  serialBt.begin(38400); //Comenzar comunicación para Bluetooth
}

void loop() {

  /*
    Comenzamos una simple comunicación
    ¿Hay respuesta del módulo? recíbelos e imprímelos en el monitor
    ¿Hay comandos ingresados por el monitor serial que mandar? envíalos
  */

  if (serialBt.available())
    Serial.write(serialBt.read());

  if (Serial.available())
    serialBt.write(Serial.read());
}

 

Nota: recomiendo desconectar cualquier cosa del Arduino antes de subir este código. Una vez compilado y subido, ahora sí podemos conectar el módulo con el circuito que está arriba.

Pasemos al siguiente paso.

Poniendo modo AT

Una vez que nuestro circuito este correctamente conectado como lo muestro arriba, y nuestro código subido al Arduino, vamos a entrar en modo AT. Es importante seguir los pasos al pie de la letra. No tienen que ser al instante; es decir, podemos dejar que pase cualquier cantidad de tiempo entre cada paso.

Todo es cuestión de relajarnos y hacer lo siguiente:

  1. Configurar monitor serial del IDE de Arduino a 9600 baudios y en ajuste de línea elegimos NL & CR
  2. Cerrar monitor serial
  3. Dejar intactos todos los cables que van del Arduino al módulo, así como están en el circuito de arriba. No debemos mover ninguno.
  4. Desconectar Arduino de la PC y de cualquier fuente de alimentación
  5. Desconectar alimentación que va al módulo HC-05. Es decir, desconectar el cable que va al VCC (el rojo).
  6. Conectar alimentación de Arduino
  7. Conectar alimentación de módulo Bluetooth. Es decir, volver a conectar el VCC (el rojo).
  8. Abrir monitor Serial

Si el módulo parpadea cada 2 segundos (se enciende, espera dos segundos para apagarse, espera otros dos segundos y se enciende de nuevo, infinitamente) es que lo hemos hecho bien y podremos pasar al siguiente paso. Si no, verifica si te has saltado algún paso.

Configurando y hablando con nuestro módulo

Al abrir el monitor serial, debió aparecerse algo así:

Eso significa que estamos listos para enviar y recibir información. Lo primero que escribiremos será at y presionaremos enter. Nos debe responder con OK.

Ahora sí viene lo interesante. Vamos a configurar contraseña y nombre. Pero antes, una pequeña explicación.

Leyendo valores

Para leer un valor (es decir, leer una variable del módulo) usaremos:

at+[variable] en donde variable puede ser name, pswd, etcétera. Notar por favor el signo de +, ya que ese signo debe ir literalmente antes del nombre de la variable. Ver los ejemplos de abajo para entenderlo mejor.

Estableciendo valores

at+[variable]=nuevoValor en donde variable puede ser name, pswd, etcétera. Notar por favor el signo de +, ya que ese signo debe ir literalmente antes del nombre de la variable. También es importante ver que usamos el signo =, y luego ponemos el nuevo valor. Ver los ejemplos de abajo para entenderlo mejor.

Nombre del módulo

Para ver el nombre que actualmente tiene el módulo, usamos at+name:

Si lo queremos cambiar, usamos at+name=”nuevo nombre”. Hay un límite de carácteres que el nombre puede llevar, así que no hay que usar uno muy grande. En este caso usaré at+name=”Cambiar nombre”:

Si ahora lo vuelvo a leer usando at+name obtengo:

Contraseña o código de acceso

Lo mismo que el nombre, sólo que ahora usamos at+pswd y at+pswd=”pass”.

Leer código con at+pswd:

Establecer código con at+pswd=”345234″ (número aleatorio). También debe tener su límite (así que no hay que establecer códigos tan largos); y podemos usar letras pero no recomiendo hacerlo, mejor usemos números:

Al volver a leer la contraseña o código de acceso con at+pswd obtenemos:

Guardando cambios

Me parece que no hay un comando para salvar los cambios, porque se guardan al ejecutar el comando. Sin embargo, es de personas educadas terminar la comunicación como debe ser, y para ello usamos at+reset:

Después de esto, debemos desconectar el cable que va al pin 34 del módulo para poder (ahora sí, al fin) conectarnos a nuestro módulo desde nuestros teléfonos, computadoras y cualquier dispositivo que soporte el estándar Bluetooth.

Más comandos

Claro que existen más comandos, aquí dejo un link con el archivo PDF que los trae todos: FKYZ0UTHX7OYY7I (sí, así se llamaba y no lo quise renombrar).

Referencias

Claramente; todo esto no salió de mi cabeza, simplemente me di a la tarea de explicarlo en español, agregarle mis propias palabras y de explicarlo de una mejor manera. Agradecimientos al autor de este link, pues me basé de casi todo lo que dice en su post para hacer el mío.

Tutorial Arduino: 74hc595 y leds

Entendiendo distribución de pines del circuito integrado

El IC 74HC595 tiene 16 pines en total. Los que nos importan en este momento son los ocho que sirven como salida, los del suministro de energía y los que se encargan del latch, data y clock.

Distribución de pines

La distribución es así:

Aquí hay otra imagen de la distribución de pines:

Podemos identificar el orden de los pines guiándonos de la pequeña muesca que tiene. Si vemos la muesca arriba, los pines comienzan a la izquierda y terminan a la derecha de ella.

  • Con verde marqué las salidas. Tenemos ocho en total, comenzando con el pin 15 (la salida 0) y luego yendo del pin 1 al 7.
  • Con azul resalté los tres pines que irán conectados al Arduino. En este caso el pin 11 es el Clock, el 12 es el Latch y el 14 Data.
  • Finalmente, remarqué la tierra  y el voltaje individualmente. Es de gran importancia mencionar que debemos alimentar al circuito por sus dos pines: tanto por el 16 como por el 10. Y conectar a tierra el 13 y el 8.

Los demás, ni yo sé para qué funcionan, y tampoco importan por el momento.

¿Qué vamos a hacer?

Vamos a controlar 8 leds usando sólo 3 salidas usando el CI del título. Los materiales son:

  • Tarjeta Arduino, no importa el modelo
  • Circuito integrado 74HC595
  • 8 leds (o diodos emisores de luz) de cualquier color
  • 8 resistencias de 220 Ohms
  • Cables para conectar todo

 

Montando circuito

Hice el circuito en la maravillosa herramienta de Tinkercad. Los cables amarillos son de la salida, recordemos que los leds deben llevar una resistencia de 220 Ω.

Puse todo ordenado para que se vea cómo funciona, pero en la práctica podemos conectar como sea.

¿Cómo funciona?

Una vez definidos nuestros pines de latch, clock y data, simplemente tenemos que llamar a la función ShiftOut de Arduino. Es una función nativa, así que no necesitamos ninguna librería. También cabe mencionar que no importa el modelo de la tarjeta que tengamos, la función se comportará de la misma manera, y podemos definir los pines como lo deseemos.

Al llamar a dicha función, le pasamos como primer argumento el pin de data, como segundo el pin de clock, después, como tercero, el orden de salida (Primero el bit más significativo o primero el bit menos significativo; es decir, comenzar de izquierda a derecha o de derecha a izquierda) y finalmente una variable de tipo byte que será casteada internamente en caso de que no la definamos como tal.

Ejemplo de llamada a función

 shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, 1);

En ese caso le indicamos que escriba el número 1. Entonces pondrá la salida número 8 a HIGH y las demás a LOW; ya que si recordamos, el 1 en binario es 00000001.

Si ahora le decimos que represente el número 20, pondrá solamente la salida número 4 y 6 a HIGH, porque el 20 en binario es 00010100.

Escribir un número arbitrario

Para comenzar con esto vamos a mostrar un número definido por nosotros mismos. Será el número 20. El código es muy simple. Definimos nuestros pines, los establecemos como salida y escribimos el valor.

/*
  Escribir un número decimal a binario usando leds

  @autor parzibyte
  @web parzibyte.me
*/

#define PIN_CLOCK 2
#define PIN_LATCH 3
#define PIN_DATA 4
void setup() {
  /*
    Al final de todo, son pines de salida,
    y debemos establecerlos como tal
  */
  pinMode(PIN_CLOCK, OUTPUT);
  pinMode(PIN_LATCH, OUTPUT);
  pinMode(PIN_DATA, OUTPUT);

  /*
    Simplemente vamos a escribir un valor
  */
  digitalWrite(PIN_LATCH, LOW); //Le decimos que vamos a escribir algo...
  shiftOut(PIN_DATA, PIN_CLOCK, LSBFIRST, 20); //Lo escribimos
  digitalWrite(PIN_LATCH, HIGH) ; //Y le indicamos que lo guarde
}
void loop() {}

Al subir y cargar nuestro código, el resultado será el siguiente:

Podemos observar que se encendieron los leds en la posición que representa al 16 y al 4 (16 + 4 = 20)

Puedes ver la simulación aquí (necesitarás registrarte).

Escribir los números del 0 al 255

Vamos a hacer esto un poco más divertido, ahora vamos a representar los números que se pueden representar con ocho bits, esto es, del 0 al 255. El código ahora sería:

/*
  Escribir los números del 0 al 255 en su representación binaria usando leds

  @autor parzibyte
  @web parzibyte.me
*/

#define PIN_CLOCK 2
#define PIN_LATCH 3
#define PIN_DATA 4
void setup() {
  /*
    Al final de todo, son pines de salida,
    y debemos establecerlos como tal
  */
  pinMode(PIN_CLOCK, OUTPUT);
  pinMode(PIN_LATCH, OUTPUT);
  pinMode(PIN_DATA, OUTPUT);

}
void loop() {
  /*
    Vamos a hacer lo mismo pero ahora en un ciclo, y dentro de loop, para que cuando llegue a 255 inicie de nuevo
  */
  for (int m = 0; m < 256; m++) {
    digitalWrite(PIN_LATCH, LOW); //Le decimos que vamos a escribir algo...
    shiftOut(PIN_DATA, PIN_CLOCK, LSBFIRST, m); //Escribimos el número en el que ahora está el ciclo
    digitalWrite(PIN_LATCH, HIGH) ; //Y le indicamos que lo guarde
    delay(500); //Esperamos un poco (medio segundo), para que se vea la animación. De otro modo, no veríamos correctamente cómo va "contando"
  }
}

Si ejecutamos el código, veremos cómo va contando. Primero enciende el led que representa al 1, luego al 2, luego al 2 y 1, y así sucesivamente. Puedes ver la simulación aquí (necesitarás registrarte).

Escribir un número definido por el usuario

Seguimos jugando. Ahora vamos a pedir un número por comunicación Serial, y ese número será escrito en los leds.

Veamos ahora el código:

/*
  Escribir un número proporcionado por el usuario a través de la comunicación Serial

  @autor parzibyte
  @web parzibyte.me
*/

#define PIN_CLOCK 2
#define PIN_LATCH 3
#define PIN_DATA 4
void setup() {
  /*
    Al final de todo, son pines de salida,
    y debemos establecerlos como tal
  */
  pinMode(PIN_CLOCK, OUTPUT);
  pinMode(PIN_LATCH, OUTPUT);
  pinMode(PIN_DATA, OUTPUT);

  Serial.begin(9600); //Comenzar comunicación serial

}
void loop() {
  /*
    Vamos a hacer lo mismo pero ahora en un ciclo, y dentro de loop, para que cuando llegue a 255 inicie de nuevo
  */
  if (Serial.available()) { //¿Hay algo que leer en el serial?
    int numero = Serial.parseInt(); //Si es que sí, lo leemos y lo convertimos a entero
    if (numero >= 0 && numero < 256) { //Recordemos que sólo tenemos 1 byte, por lo que no podemos representar números más grandes que 255
      digitalWrite(PIN_LATCH, LOW); //Le decimos que vamos a escribir algo...
      shiftOut(PIN_DATA, PIN_CLOCK, LSBFIRST, numero); //Escribimos el número que el usuario proporcionó
      digitalWrite(PIN_LATCH, HIGH) ; //Y le indicamos que lo guarde
    }
  }
}

Hacemos el mismo proceso, sólo que ahora leemos el número por comunicación Serial. También comparamos si el número cabe en un byte (si está entre 0 y 255) para no tener resultados inesperados. Al ejecutarlo e ingresar un número, este es el resultado:

Puedes ver la simulación aquí (necesitarás registrarte).

Escribir el código ASCII de un carácter

Para terminar con esto, vamos a escribir la representación de un carácter en binario. Por ejemplo, en ASCII, el arroba (@) es representado por el número 64. Y el 64 en binario es 01000000. Así que pediremos un carácter por comunicación Serial y pondremos su representación binaria con los leds.

/*
  Escribir la representación binaria de un carácter proporcionado por el usuario a través de la comunicación Serial

  @autor parzibyte
  @web parzibyte.me
*/

#define PIN_CLOCK 2
#define PIN_LATCH 3
#define PIN_DATA 4
void setup() {
  /*
    Al final de todo, son pines de salida,
    y debemos establecerlos como tal
  */
  pinMode(PIN_CLOCK, OUTPUT);
  pinMode(PIN_LATCH, OUTPUT);
  pinMode(PIN_DATA, OUTPUT);

  Serial.begin(9600); //Comenzar comunicación serial

}
void loop() {
  /*
    Vamos a hacer lo mismo pero ahora en un ciclo, y dentro de loop, para que cuando llegue a 255 inicie de nuevo
  */
  if (Serial.available()) { //¿Hay algo que leer en el serial?
    char caracter = Serial.read(); //Si es que sí, lo leemos. En este caso la variable será de tipo char
    if (caracter >= 0 && caracter < 256) { //Recordemos que sólo tenemos 1 byte, por lo que no podemos representar carácteres cuyo código no esté entre 0 y 255
      digitalWrite(PIN_LATCH, LOW); //Le decimos que vamos a escribir algo...
      shiftOut(PIN_DATA, PIN_CLOCK, LSBFIRST, caracter); //Escribimos el carácter que el usuario proporcionó
      digitalWrite(PIN_LATCH, HIGH) ; //Y le indicamos que lo guarde
    }
  }
}

Ahora en lugar de leer un entero leemos un carácter. Y lo escribimos. Por ejemplo, si yo pongo el @ se encenderá el led que representa al 64:

Nuevamente, se puede simular aquí, y se necesita registro.

Conclusión

Este circuito integrado es una maravilla, pues nos ahorra muchos pines. Ya que sólo usamos 3 y con ellos controlamos 8. Me parece que también existen de más salidas. Por otro lado, existen aquellos que son lo contrario. Es decir, que nos permiten leer muchos valores con pocas entradas.

Todo esto lo hice en el simulador porque es una manera fácil y rápida de que la gente pueda probar, sin necesidad de tener que armar el circuito, ni comprar los componentes. De todas maneras, lo he probado yo con un Arduino en la vida real, y una vez que lo logré y funcionó, lo simulé.

Espero que haya servido.