Fork me on GitHub

Lámpara RGB con NodeMCU

June 18, 2016

Siguiendo con las pruebas con NodeMCU armé un pequeño script que cambia aleatoriamente los valores de un led rgb cada cierto tiempo. Para setear los valores del led usé el módulo pwm. Salvo el pin 0 el resto de los pines soporta pwm. Acá el esquema de conexiones

Para generar los valores aleatorios usé math.random de la librería estándar y para el timer el módulo tmr. Metí todo en funciones y quedó así

Quería probar el upload del archivo y entonces encontré luatool, escrito en Python :) Se pueden subir n archivos y uno de ellos debe ser init.lua, que será el que se ejecute durante el start.

luatool  --port /dev/ttyUSB0 --src rgb.lua --dest init.lua --verbose

Eso es todo :)

Lua Trabajos esp8266

Primeros pasos con NodeMCU

April 3, 2016

NodeMCU es un proyecto IoT Open Source hecho en China que incorpora el chip ESP8266 para conexión WiFi y que además es programable en Lua 5.1.

Algo muy interesante de NodeMCU es que su firmware incorpora el intéprete Lua, al cual se accede mediante el puerto serial, permitiendo escribir comandos e interactuar directamente con el hardware en tiempo real.

El intérprete embebido incorpora muchos módulos útiles como wifi para manejar la conexión.. wifi, net y http para crear servidores o clientes http, gpio y pwm para control de los pines y varios otros. Está todo muy bien documentado en https://nodemcu.readthedocs.org.

Para empezar lo primero es instalar el firmware usando esptool. Aquí hay una buena guía para esto, pero básicamente es seguir este ejemplo

sudo python esptool.py --port /dev/ttyUSB0 write_flash 0x00000 nodemcu_integer_0.9.6-dev_20150704.bin

Al finalizar veremos algo así

Wrote 450560 bytes at 0x00000000 in 44.3 seconds (81.3 kbit/s)...

Leaving...

Luego hay que ingresar usando el puerto serie al que esté conectado, para eso se puede usar minicom o screen. Prefiero screen porque minicom me borra lo escrito al redimensionar la ventana.

screen /dev/ttyUSB0 9600

Al ingresar se ven unos caracteres raros (posiblemente chino y no tengo la fuente) y el prompt del intérprete de Lua. Si el prompt no aparece generalmente lo hace luego de apretar Enter, sino node.restart() reincia NodeMC

NodeMCU 0.9.6 build 20150704  powered by Lua 5.1.4
lua: cannot open init.lua
>

Listo, estamos en condiciones de escribir Lua! Acá van un par de ejemplos

> -- Connect to your AP
> wifi.setmode(wifi.STATION)
> wifi.sta.config("SSID", "password")
> ip = wifi.sta.getip()
> print(ip)
192.168.18.110
> -- A simple HTTP server
> srv = net.createServer(net.TCP)
> srv:listen(80, function(conn)
>     conn:on("receive", function(conn,payload)
>         print(payload)
>         conn:send("<h1>Hello from NodeMCU.</h1>")
>     end)
>     conn:on("sent", function(conn) conn:close() end)
> end)

Lua Trabajos esp8266

Interrupciones con Arduino

March 25, 2016

Una interrupción es una señal que interrumpe la ejecución del micro, quien deja inmediatamente lo que estaba haciendo y pasa a atender a una función especial que se encuentra por fuera del flujo del programa y que contiene las instrucciones necesarias para tratar el evento. Una vez finalizado el código de la función el micro retoma su rutina anterior en el lugar exacto donde la interrumpió.

En Arduino este tipo de funciones se llaman ISR (Interrupt Service Routines) y tienen un par de limitaciones con respecto al resto: no pueden recibir parámetros ni retornar algo.

Por otra parte en Arduino las interrupciones son por hardware, para lo cual hay que hacer uso de algún pin, pero no cualquiera puede usarse para esto. En Uno, Nano y Mini los pines habilitados son 2 y 3. En cualquiera de estos pines es posible setear el evento que lanzará la interrupción:

  • LOW: La interrupción se dispara cuando el pin es LOW.
  • CHANGE: Se dispara cuando pase de HIGH a LOW o viceversa.
  • RISING: Se dispara en el flanco de subida (cuando pasa de LOW a HIGH).
  • FALLING: Se dispara en el flanco de bajada (cuando pasa de HIGH a LOW).

A continuación un ejemplo sencillo usando un switch en el pin 2, el cual al ser presionado setea en cero la variable state. Para asegurarse de que las variables compartidas entre las ISR y el resto se actualicen correctamente hay que declararlas como volatile.

volatile int state = 1;

void interrupt()
{
    state = digitalRead(BUTTON_PIN);
}

void setup()
{
    attachInterrupt(0, interrupt, CHANGE);
}

void loop()
{
    for (int i = 0; i < 25; i++) {
        while( ! state);
        // task here
    }
}

Las ISR se conectan a un pin particular mediante la función attachInterrupt. El 0 indica que se conecta al primer pin habilitado para esto, es decir el 2.

El código completo aquí.

Arduino

Pruebas con OpenCV

November 13, 2015

Acabo de leer Arduino Computer Vision Programming, un libro de introducción a OpenCV. Al leer el título me imaginé conectando alguna cámara directamente a Arduino pero después de investigar un poco descubrí que OpenCV es demasiado para ejecutarlo con Arduino, por eso todos los tutoriales que hay por ahí lo usan desde una computadora y se limitan a pasarle datos sencillos a Arduino luego de haber procesado y analizado las imágenes.

opencv matching

En definitiva lo que rescaté del libro son los conceptos básicos de OpenCV y cómo usarlo con C++. Aquí un pequeño ejemplo donde se intenta detectar una imágen pasada por parámetro.

Arduino

Guardando mis comandos con Lai

September 1, 2015

Hace un par de años hice Lai, un programa para mantener un registro de aquellos comandos, snippets o notas que necesito tener a mano en la consola en cualquier computadora que uso. La instalación era un poco difícil hasta que se me ocurrió hacer una imagen con Docker. Ahora solo hay que crear una cuenta en lai.nerdlabs.com.ar y agregar este alias al inicio de la sesión

alias lai='docker run -it \
           --env USER= \
           --env KEY_NAME= \
           -v ~/.ssh/id_rsa:/root/.ssh/id_rsa \
           -v ~/var/lai:/app/data \
           --rm=true \
           lvidarte/lai python lai/app.py'

Lai utiliza el esquema cliente-servidor. En cada máquina hay que instalar un cliente que sincronizará contra el server. Para la comunicación se usa clave pública-privada. La clave pública hay que subirla al server y definirle un nombre o KEY_NAME para poder identificarla ya que es posible tener más de una. El USER es el mail de la cuenta de Google, que es el único modo de autenticación soportado.

Modo de uso

usage: lai [-h] [-v] {search,add,get,edit,editor,delete,sync,copy,status} ...

Cada comando tiene su ayuda

$ lai <command> --help

Para agregar algo

$ lai add 'grep -R <pattern> --include \*.txt <dir>'

También puedo poner una descripción

$ lai add 'tmux Prefix [' -d 'switch to copy mode'

El comando por defecto es search así que la búsqueda se reduce a

$ lai grep
1: grep -R <pattern> --include \*.txt <dir>

Puedo compartir cosas con otros usuarios haciéndolas públicas

$ lai edit 1 --public

Esto permite buscar entre lo público del server (y que no compartí yo)

$ lai search --server grep vim
55e477d48c4f21481fcd3cea: vim -d files #diff files with vim

Y copiarme aquello que quiera

$ lai copy --server 55e477d48c4f21481fcd3cea

Finalmente para sincronizar

$ lai sync

Docker Python Software Libre Trabajos

Golang defer, panic y recover

August 25, 2015

Golang tiene un mecanismo llamado defer que sirve para asegurarnos de que cierto código siempre se ejecutará al finalizar una función

Lo que sucede acá es que second se ejecutará luego de que main haya finalizado. Este mecanismo es útil para realizar tareas de limpieza, como cerrar archivos o conexiones.

f, _ := os.Open(filename)
defer f.Close()

Lo bueno de esto además es que Close queda junto a Open y es más fácil de leer.

Por otro lado tenemos panic que lanza una especie de excepción en tiempo de ejecución. Esta excepción la podemos interceptar con recover y obtener su valor. Acá podemos ver cómo con la ayuda de defer podemos interceptar la llamada a panic

$ go run panic.go 
open /file: permission denied

Y acá hay otro ejemplo un poco más interesante

Calling g.
Printing in g 0
Printing in g 1
Printing in g 2
Printing in g 3
Panicking!
Defer in g 3
Defer in g 2
Defer in g 1
Defer in g 0
Recovered in f 4
Returned normally from f.

Referencias

Golang

Pruebas con Docker

August 21, 2015

Docker es genial para hacer pruebas sin tener que instalar nada directamente en tu sistema. Es una buena forma de mantener tu Linux liviano y aprovechar mejor los recursos de tu máquina ya que no deberías tener corriendo servicios que no estás usando. Además todo lo que instalás vía Docker queda perfectamente contenido dentro de imágenes que al borrarlas eliminan totalmente lo instalado. Por eso también hay quienes van más allá y lo usan para correr aplicaciones de escritorio. En definitiva, pensá bien cada apt-get install que hagas, no hay necesidad de llenar de paquetes tu instalación.

Veamos un caso sencillo en el queremos probar Node con Redis

Este servicio incrementa una variable en Redis por cada request, es un simple contador de visitas. Para levantar esto con Docker necesitamos dos containers: uno para Redis y otro para el script de Node. Empecemos por Redis. En Docker Hub tenés todas las imágenes oficiales de Redis, basta con seleccionar la que querés usar.

docker run --name counter_db \
            -v $PWD/data:/data \
            redis:3.0

Ok, tenemos Redis 3.0 levantado en un container de nombre counter_db. También le decimos a Docker que los datos los vamos a guardar localmente en el dir ./data.

Ahora necesitamos levantar nuestra app, para lo que usaremos una de las imágenes oficiales de Node. Acá lo que tenemos que hacer es crear nuestra propia imagen basándonos en una de las oficiales.

Para levantar el server nos conviene usar el script start.sh que hace lo siguente

#!/bin/bash
npm install
nodemon server.js

De esta forma nos aseguramos de que antes de iniciar se instalen todas las dependencias en package.json

{
  "dependencies": {
    "redis": "^0.12.1"
  }
}

Ahora podemos crear la imagen

docker build -t counter_app .

Y finalmente levantar el container y linkearlo con el servidor Redis

docker run -p 3000:3000 \
           --name counter \
           -v $PWD:/app \
           --link counter_db \
           counter_app

En este punto tenemos todo levantado y listo para probar

$ curl localhost:3000
{"counter":1}
$ curl localhost:3000
{"counter":2}

Si queremos automatizar el proceso de levantar cada container podemos usar docker-compose. Para esto creamos el archivo docker-compose.yml con lo siguiente

Ahora sí, solo hay que hacer

docker-compose up

y tendremos todo el stack levantado.

Docker

Visor lcd de temperatura y humedad

August 6, 2015

Estuve jugando un rato con un lcd y un sensor de temperatura y salió esto

La lista de materiales es la siguiente

El esquema de conexiones para el LCD (hecho con circuits.io) es el siguiente

Sólo hay que agregarle el sensor, que tiene 3 patas: gnd, vcc y data que conecté al pin 5 en el Arduino. Para leerlo usé una librería de Adafruit. El código me quedó así

Algo interesante que encontré es que en Arduino la función printf no funciona con floats, por lo que %f se reemplaza por ?, así que hay que hacer un poco de trabajo extra para mostrarlos.

Referencias

Arduino Trabajos

Cola circular en Arduino usando clases

August 2, 2015

Aquí va un sencillo ejemplo de implementación de una cola circular para Arduino usando clases al estilo C++. Para compilar y subir el código final usaremos inotool en lugar del IDE oficial de Arduino. Comenzamos entonces haciendo

$ ino init

Esto crea la siguiente estructura

$ tree
.
├── lib
└── src
    └── sketch.ino

sketch.ino es el sketch propio de Arduino, donde irán el setup() y el loop(). Dentro del directorio lib crearemos nuestra librería Queue que contendrá los archivos .h y .cpp correspondientes

$ tree
.
├── lib
│   └── Queue
│       ├── Queue.cpp
│       └── Queue.h
└── src
    └── sketch.ino

Para la cola usaremos un array de enteros sin signo de 8 bits (uint8_t). Definiremos la longitud del array en el setup. Veamos entonces Queue.h para tener un parnorama de los métodos y propiedades de nuestra clase

Read more »

Arduino

Older | Newer