Archivo de la categoría: Proyectos

Proyectos que he desarrollado y quiero compartir con la comunidad

Global Robot Expo

Desde hoy y hasta el Domingo se celebra la primera Global Robot Expo en Madrid. He tenido la suerte de visitarla el primer día de apertura y esto es con lo que me he encontrado:

Varios de los robots más conocidos nos dan la bienvenida a la exposición.

IMG_2316-1

IMG_2316-24

En la exposición había casi más stands de drones que de robots clásicos.

IMG_2316-0

IMG_2316-8

IMG_2316-10

IMG_2316-14

IMG_2316-17

IMG_2316-18

IMG_2316-25

IMG_2316-36

Robots emocionales.

IMG_2316-2

Brazos robóticos.

IMG_2316-3

IMG_2316-6

IMG_2316-7

IMG_2316-20

IMG_2316-21

Robótica educativa.

IMG_2316-4

IMG_2316-22

IMG_2316-26

IMG_2316-29

IMG_2316-30

IMG_2316-31

IMG_2316-34

IMG_2316-35

Robots manipuladores móviles.

IMG_2316-5

IMG_2316-11

IMG_2316-9

Recinto con red para demostraciones con drones.

IMG_2316-12

IMG_2316-37

Escenario para las competiciones de robots de la lnrc.

IMG_2316-13

Reconocimiento óptico.

IMG_2316-15

Manejando un robot desde un maletín.

IMG_2316-16

Cortadora de cesped robotizada.

IMG_2316-19

Robots bailarines

IMG_2316-23

Embajada de Japón

IMG_2316-27

Nanorobots

IMG_2316-32

IMG_2316-33

Y un artículo sin vídeo es como un día sin pan, así que aquí lo tenéis una pequeña muestra del evento:

Programar el chip wifi ESP8266 como si fuera un microcontrolador (2/2)

En el anterior artículo explicaba cómo generar el toolchain para poder compilar programas y subirlos a nuestro módulo ESP8266. En este artículo explicaré cómo hacer un programa en C. Para ello me voy a poner un reto: un firmware que cuando pulse un botón o la tecla p, haga una llamada a una página web que muestre la acción realizada. Con este ejemplo vamos a trabajar con el gpio, puerto serie, wifi, temporizadores y eventos. No hay mucha documentación sobre cómo programar el chip esp8266 más allá de los ejemplos de código, foros y páginas web con artículos dedicados al chip y de la SDK de Espressif que en el momento de escribir este artículo es la 1.0.1.

Empezaré por mostrar un vídeo de lo que he hecho para tener claro desde el principio lo que explicaré aquí.

Lo que veis en el vídeo es que primero programo el esp8266 con el firmware de este artículo. Luego abro una terminal al puerto serie del ESP8266. Pulso 3 veces el botón físico y otras 3 veces la tecla p en la terminal para que se envíe por el puerto serie. Estas acciones provocan en el esp8266 la llamada a una página web que lo registra, mientras en otra página web se visualiza casi en tiempo real lo que he hecho. Cuando compiléis vosotros el ejemplo podéis usar la misma página para hacer vuestras pruebas.

Este es el esquema del circuito para el botón (he obviado las conexiones al puerto serie para simplificarlo):

placa

Vamos a ver cómo lo hecho. Lo primero es crear una carpeta llamada proyectos-esp8266 en nuestra carpeta personal, entra dentro de esta y crear otra llamada reto. Dentro de esta copiaremos el fichero Makefile que modificamos en el anterior artículo. Después crearemos una carpeta llamada user y dentro de esta compiaremos los ficheros uart.h y uart_register.h del ejemplo de IoT que trae la SDK:

Dentro de la carpeta user crearemos dos ficheros.

user_config.h

user_main.c

Lo primero que salta a la vista es que no existe una función main eso es porque este chip se programa con una función de inicialización y el resto con eventos/interrupciones.

La función de inicialización es user_init (al final del código), como decía esta función es llamada cuando el módulo se enciende y se encarga de inicializar todo en el esp8266. El modificador de función ICACHE_FLASH_ATTR significa que la función se guarde en la flash en vez de en la RAM y que cuando se vaya a usar sea cacheada en esta última, ahorrando así espacio para poder tener más datos en la memoria. Dentro de esta función hay que destacar:

  • system_init_done_cb: Esta función tiene un parámetro que es la función callback que será llamada cuando termine la inicialización.
  • system_os_task: Esta función define la ejecución, como tarea, de la función callback pasada como primer parámetro. Podemos tener hasta 4 tareas (cada una con una prioridad distinta). Más adelante hablaré de ello.

La función inicializado es llamada cuando ha terminado la inicialización como comentába antes. Dentro de esta función hay que destacar:

  • os_printf: Es como el printf de toda la vida, pero su salida es enviada al puerto serie 0 (el esp8266 tiene un puerto serie con tx y rx y otro con tx sólo para hacer debug).

La función inicializa_uart configura el puerto serie. Dentro de esta función hay que destacar:

  • ETS_UART_INTR_ATTACH: Esta función configura a qué función callback se llamará cuando se reciba un caracter por el puerto serie. El segundo parámetro es una estructura que existe por defecto con información del puerto serie y el buffer de recepción, pero yo no lo usaré.
  • PIN_PULLUP_DIS: Desactiva la configuración de pull-up del pin indicado (La lista de pines está en el fichero eagle_soc.h de la sdk), en este caso del pin TX.
  • PIN_FUNC_SELECT: Configura el pin indicado para comportarse de una manera determinada, en este caso para funcionar como TX del puerto serie.
  • uart_div_modify: Configura la velocidad del puerto serie
  • WRITE_PERI_REG(UART_CONF0(0), (STICK_PARITY_DIS)|(ONE_STOP_BIT << UART_STOP_BIT_NUM_S)| (EIGHT_BITS << UART_BIT_NUM_S)): Configura la comunicación como 8 bits, sin paridad y un bit de stop.
  • SET_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST) y CLEAR_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST): Limpia la FIFO de TX y RX.
  • WRITE_PERI_REG(UART_CONF1(0), (UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S): Configura el disparador FIFO de RX.
  • WRITE_PERI_REG(UART_INT_CLR(0), 0xffff): Borrar el flag de todas las interrupciones del puerto serie.
  • SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA): Configura la interrupción de recepción del pin RX.
  • ETS_UART_INTR_ENABLE: Activa las interrupciones del puerto serie.

La función inicializa_gpio configura el pin GPIO 2 (el único disponible en el ESP-01, pero en otros módulos hay más pines gpio usables). Dentro de esta función hay que destacar:

  • ETS_GPIO_INTR_DISABLE: Desactiva la interrupción de los pines GPIO.
  • ETS_GPIO_INTR_ATTACH: Esta función configura a que función callback se llamará cuando haya una interrpción en el pin gpio indicado.
  • PIN_PULLUP_EN: Activa la configuración de pull-up del pin indicado.
  • gpio_output_set: Configura el pin gpio 2 como entrada.
  • GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(2)): Borrar el flag de la interrupcion del pin gpio 2.
  • gpio_pin_intr_state_set: Indica que en el pin gpio 2 sólo debe activarse la interrupción cuando detecta un flanco de bajada (conecta con masa/GND).
  • ETS_GPIO_INTR_ENABLE: Activa las interrupciones gpio.

La función inicializa_wifi configura la conexión a la wifi. Dentro de esta función hay que destacar:

  • wifi_set_opmode: Configura el módulo como estación cliente.
  • wifi_station_set_auto_connect: Indica que cuando se encienda el módulo se conecte automáticamente a la wifi establecida.
  • wifi_station_set_reconnect_policy: Indica que si se pierde la conexión con el punto de acceso, la vuelva a restablecer.
  • os_memcpy(&configuracion.ssid, ssid, 32) y os_memcpy(&configuracion.password, password, 64): Copia el nombre de la red wifi y la contraseña a la estructura del tipo station_config. Sirve para copiar datos de una posición de memoria a otra, sería equiparable al memcpy del C.
  • configuracion.bssid_set = 0: Para que conecte a cualquier wifi que tenga el nombre proporcionado anteriormente. Si hay varias wifis con el mismo nombre (SSID) puedes indicar a qué punto de acceso quieres acceder poniendo aquí su BSSID (su dirección MAC).
  • wifi_station_set_config: Inicializa la wifi con los valores proporcionados en la estructura del tipo station_config.
  • wifi_set_event_handler_cb: Esta función configura a que función callback se llamará cuando haya cambios en la wifi (conexión, desconexión, ip recibida…).

La función callback interrupcion_wifi es llamada por el chip cuando un evento en la wifi es generado. Quizá el más importante es cuando recibimos una IP de nuestro router. En el ejemplo pongo una variable a TRUE para indicar que tiene libertad para procesar las pulsaciones del teclado o del botón.

La función callback interrupcion_gpio es llamada por el chip cuando se ha detectado un evento en los pines GPIO. Dentro de esta función hay que destacar:

  • GPIO_REG_READ(GPIO_STATUS_ADDRESS): Devuelve el estado de los pones gpio y cual ha sido el que ha causado el evento.
  • os_timer_disarm: desactiva un temporizador si este estuviese activo.
  • os_timer_setfn: configura un temporizador indicando a qué función callback llamará cuando expire. Se le puede pasar un parámetro (en este caso NULL).
  • os_timer_arm: Activa el temporizador indicando cuanto tiempo dura en milisegundos y si debe o no repetirse. La idea de usarlo es para evitar los rebotes físicos cuando el botón es pulsado.
  • system_os_post: Indica al chip que, cuando pueda, ejecute la tarea de prioridad 0 que predefinimos en la función user_init con los parámetros 0,0.

La función callback boton_pulsado establece una variable a FALSE para indicar que el tiempo dado para mitigar los rebotes físicos del botón ya ha pasado y de nuevo permite reconocer la pulsación de éste.

La función callback caracter_recibido es llamada por el chip cuando se ha detectado un evento en el puerto serie. Dentro de esta función hay que destacar:

  • READ_PERI_REG(UART_INT_ST(UART0): Lee cual ha sido el motivo de la interrupción.
  • WRITE_PERI_REG(UART_INT_CLR(UART0): UART_RXFIFO_FULL_INT_CLR): Borra el bit de la interrupción correspondiente a carácter recibido.
  • READ_PERI_REG(UART_STATUS(UART0)): Lee el estado del puerto serie.
  • READ_PERI_REG(UART_FIFO(UART0)): Lee el caracter propiamente dicho. El chip ya tiene un buffer donde se pueden almacenar los carácteres recibidos, yo no lo he usado pero puede ser interesante.

La función callback conecta es llamada por el chip como una tarea. Inicia el proceso de envío de datos. Dentro de esta función hay que destacar:

  • os_zalloc: Sirve para reservar memoria, sería equiparable al malloc del C.
  • espconn_gethostbyname: Esta función hace una consulta dns para obtener la ip de un host dado y llamará a una función callback. Usa una estructura del tipo espconn donde se rellenarán todos los datos referentes a la conexión TCP

La función callback encontrado es llamada cuando se ha resuelto un nombre de host. Dentro de esta función hay que destacar:

  • espconn_port: Crea un puerto local para poder enganchar el socket con el puerto remoto 80 (http).
  • espconn_regist_connectcb: Esta función indica al chip que cuando se establece una conexión TCP, debe llamar a la función callback definida.
  • espconn_regist_disconcb: Esta función indica al chip que cuando hay una desconexión, debe llamar a la función callback definida.
  • espconn_regist_recvcb: Esta función indica al chip que cuando se reciben datos desde una conexión TCP, debe llamar a la función callback definida.

La función callback conectado es llamada por el chip cuando se establece una conexión TCP. Dentro de esta función hay que destacar:

  • os_sprintf: Sirve para rellenar un buffer con datos formateados, sería equiparable al sprintf del C.
  • espconn_sent: Envía los datos indicados a través del socket TCP.
  • os_strlen: Devuelve la longitud de una cadena, sería equiparable al strlen del C.

La función callback recibido es llamada por el chip cuando se reciben datos de una conexión TCP. En el ejemplo sólo los muestro directamente. Dentro de esta función hay que destacar:

  • os_free: Sirve para liberar memoria, sería equiparable al free del C.

La función callback desconectado es llamada por el chip cuando se desconecta la conexión TCP. En el ejemplo libero los buffers de memoria reservados previamente.

Quiero comentar es que no soy un experto en el esp8266, por lo que si que me preguntáis algo puede que no lo sepa responder, por ello os recomiendo ir a la página www.esp8266.com donde hay mucha gente que trabaja con el esp8266 y os podrán resolver vuestras dudas mejor que yo. Todo lo que he juntado aquí ha sido fruto de búsquedas por internet, mil y una pruebas con código fuente, etc. Sin embargo lo que aquí he explicado, aún siendo de las partes más importantes de la programación de un ESP8266, no cubre todo lo que se puede hacer con este chip, por lo que una vez te encuentres cómodo con lo aquí expuesto, te animo a que busques por tu cuenta más funcionalidades.

Programar el chip wifi ESP8266 como si fuera un microcontrolador (1/2)

IMG_20150504_230102

En esta tanda de dos artículos explicaré cómo olvidarse de los comandos AT del módulo ESP8266 ESP-01 (aunque lo escrito vale para toda la familia ESP) y poder programarlo como un chip independiente: conectando la wifi, manejando el puerto serie, usando los pines GPIO, etc. La gran ventaja es que tenemos un microprocesador más potente, más versátil, más rápido y además en muchos casos es más barato que si usáramos los microcontroladores PIC o AVR (como contrapartida tiene menos pines de E/S).

CONSTRUYENDO EL TOOLCHAIN

El primer paso que tenemos que hacer para programarlo es construir el toolchain para poder compilar los programas para este chip con el compilador cruzado. Para ello recomiendo tener un linux donde construirlo (ya sea físico o virtualizado), no recomiendo usar windows y cygwin. Yo estoy usando el ubuntu 14.04 LTS.

Lo primero es instalar las herramientas necesarias, para ello ejecutar:

Vamos a usar el toolchain de https://github.com/pfalcon/esp-open-sdk, con el que el proceso de creación es bastante sencillo (ejecútalo en la raíz de tu directorio personal):

Esto habrá creado una carpeta esp-open-sdk. Entra dentro de está y haz un make (con el parámetro STANDALONE=y) para crear todo el toolchain (puede tardar un rato dependiendo de tu ordenador):

Ahora vamos a poner en la variable de entorno PATH la ruta a los binarios, ya que el esptool no funciona si no se pone (cambia oscar por tu usuario):

COMPILANDO PROGRAMAS

Vamos a descargarnos unos ejemplos ya hechos:

Esto creará una carpeta llamada source-code-examples. Entra dentro de esta carpeta y edita el fichero example.Makefile.

Modifica las siguientes lineas (recuerda cambiar oscar por tu usuario):

POR

POR

POR

El campo ESPPORT debes cambiarlo si no coincide con la ruta al dispositivo asociado a tu dongle usb a serie.
Ahora entra dentro del direcotrio blinky, copia el fichero anteriormente editado como Makefile y haz un make para compilar el firmware:

Si todo ha ido bien habremos compilado el firmware para nuestro ESP8266:
shell1

PROGRAMANDO EL ESP8266

Para poder programar nuestro módulo ESP8266 necesitamos un dongle usb a serie (USB2TTL) como este:
IMG_20150501_165235
Después es necesario añadir al usuario que estemos utilizando (en el ejemplo, oscar) en el grupo dialout para poder acceder al dongle:

Ahora sólo queda subir el programa al módulo ESP8266, para ello debes cablear el módulo de la siguiente forma (estando éste sin alimentación):
conexiones
Las líneas rojas van a VCC (3,3V) y las negras a GND (masa). Ahora alimenta el módulo.

Si es la primera vez que vas a programar el módulo wifi, debes borrar las configuraciones por defecto, esto se consigue ejecutando el siguiente comando:

shell2
Las siguientes veces ya no será necesario repetir este paso. Si has hecho este paso vuelve a apagar y encender el módulo.

Finalmente para programar el firmware creado, ejecuta el comando:

shell3
Enhorabuena, acabas de programar por primera vez tu módulo ESP8266. Ahora desconecta el cable que va al pin de programacion (así el módulo no estará en modo de programación), conecta un led entre el GPIO 2 (el que no aparece conectado a ningún sitio en la fila de GND de la foto anterior de las conexiones) y masa. Así es como luce el “hola mundo” del chip ESP8266:

En el siguiente artículo explicaré cómo hacer tus propios programas en C para el esp8266.

Programando un Arduino remotamente con el módulo ESP8266

IMG_20141108_002938

Una de mis viejas aspiraciones cuando construyo robots es poder programarlos sin tener que recogerlos, enchufarles un cable usb o un programador ICSP y volverlos a dejar en su sitio.

En este artículo explicaré cómo con un Arduino UNO y un módulo ESP8266 (llamado WI07C) se puede programar un sketch de Arduino en la placa sin tener que estar cerca de esta, todo mediante wifi y sockets tcp/ip.

Descripción general

Como se puede ver en el vídeo tenemos un Arduino UNO conectado a un display HD44780 y a un módulo wifi ESP8266. Arduino envía cadenas hello world al servidor sockettest que está escuchando por el puerto 49000. Se modifica el código Arduino en el IDE poniendo hello folks, se compila y el fichero .hex generado (se puede ver donde está activandolo en Archivo/Preferencias/compilación) se copia a la carpeta del programa en python. Cuando Arduino recibe un comando reboot se conecta al servidor python por el puerto 50000 entrando en modo de datos, acto seguido se reinicia y empieza la programación remota de Arduino. El proceso se reliza dos veces en el vídeo.

Lo que se aprovecha es el método que tiene Arduino para programarse, ya que usando el puerto serie después de un reset se puede programar un Arduino si se sigue el protocolo STK500 implementado en el bootloader.

Esquema de conexiones

esquema

El Arduino y el display HD44780 se alimentan a 5 voltios, el módulo ESP8266 se alimenta a 3,3 voltios. Como el pin rx del módulo wifi sólo puede funcionar a 3,3V se usa un diodo zener de 3,3 voltios junto con una resistencia de 100 Ω.

En las placas Arduino, el pin de reset del microcontrolador está conectado a una resistencia y esta a su vez está conectada a VCC, con lo que para el microcontrolador el pin está a nivel alto. Cuando se pulsa el botón de reset lo que se hace es derivar la corriente hacia masa (ya que el bóton está conectado a esta) y el microcontrolador, al estar a nivel bajo el pin de reset, realiza un reseteo. Cuando el microcontrolador arranca, todos los pines están configurados como entradas (alta impedancia) y por eso no le afecta que el pin de reset esté conectado directamente al pin 12. Si se configura el pin 12 como salida y luego se conecta a masa (nivel bajo o LOW) se provoca el mismo efecto que si se pulsase el botón de reset, además, al existir la resistencia anteriormente mencionada, no hay que preocuparse de que se produzca un cortocircuito al unir VCC con masa (GND).

Sketch de Arduino

Lo que hace el skecth de Arduino es:

  • Inicializa el puerto serie a 115200 bps.
  • Elimina los caracteres que hubiera en el buffer de entrada del puerto serie.
  • Inicializa el módulo wifi en modo estación, lo resetea, se conecta al punto de acceso normal, configura las conexiones como simples en modo normal y se conecta al servidor normal por el puerto 49000. Si hubiese algún fallo en algún punto pararía la ejecución y lo indicaría en el display.
  • Envia una cadena de texto y un número consecutivo tanto al servidor como al display. Si hubiese algún fallo en algún punto pararía la ejecución y lo indicaría en el display.
  • Si entre el envío de las cadenas de texto se recibe una cadena reboot entonces resetea el módulo, se conecta al punto de acceso bootloader, configura las conexiones como simples en modo normal y se conecta al servidor de programación por el puerto 50000. Acto seguido envía una cadena hello y espera a recibir una cadena welcome, si ha sido así, entonces envía el nombre del fichero .hex con el que quiere ser programado el Arduino y espera a recibir una cadena ok, momento en el cual configura el pin 12 como salida y lo pone a nivel bajo, conectándolo a masa y provocando un reset en el Arduino. Si hubiese algún fallo en algún punto pararía la ejecución y lo indicaría en el display.

Aquí cabe destacar cómo funciona el sistema de reseteo: Justo después del reseteo, el pin de TX de Arduino está a nivel bajo durante un tiempo, lo que provoca que el módulo wifi vea eso como un byte 0, que enviará a través de la conexión TCP/IP. El servidor de programación aprovechará esta circunstancia para saber cuando ha empezado el reseteo e iniciar el protocolo STK500. El bootloader de Arduino entra en acción después del reseteo y espera a recibir ordenes del protocolo STK500, si las recibe actúa en consecuencia, si no, ejecuta el programa principal.

Servidor de programación

Lo que hace el servidor de programación es:

  • Crea un socket que escuche por el puerto 50000
  • Cuando un cliente de conecta espera a la cadena hello, si la recibe reponde con una cadena welcome.
  • Espera a que el cliente le envíe un nombre de fichero .hex. Trata de abrir el fichero en el mismo directorio y lo lee interpretando todas las líneas para guardar los datos del programa en memoria. Si todo va bien envía una cadena ok.
  • Espera a recibir el byte 0, y cuando lo recibe empieza el protocolo STK500 para comunicarse con el bootloader de Arduino y programarlo. Básicamente lo que hace es entrar en modo de programación, indicarle a que páginas quiere acceder y enviar los datos de cada página, así hasta que ha enviado todos los datos del programa, después sale del modo de programación cerrando la conexión

Aquí cabe destacar que cuando se cierra la conexión TCP/IP con el cliente (ya sea por un error o porque el proceso de programación ya ha terminado), el módulo ESP8266 sale del modo de datos automáticamente y no es necesario que el nuevo sketch tenga que enviarle la cadena de escape +++ para poder entrar otra vez en modo de comandos.

Conclusiones

Espero que esto os sirva para que en vuestros proyectos podais programar remotamente vuestros Arduinos a través de una red local o Internet.

Habría que tener en cuenta que el proceso de actualización puede quedarse a medias si la conexión a la red wifi es lenta y provocaría que el programa no se ejecutara correctamente. Así que que una mejora sería acoplar un chip aparte que reprogramase el Arduino por ICSP con un programa preestablecido en caso de que detectase que la programación no fue finalizada correctamente.

Comentar que la versión de firmware del módulo ESP8266 que he usado es la 0019000902 y el Arduino es un UNO. Ambos funcionan a 115200 bps, pero si quisierais utilizar otras velocidades (en otros Arduinos el bootloader configura el puerto serie a 19200 o 57600 bps) habría que cargar un firmware que lo permitiese, como por ejemplo la versión 0.922 de electrodragon y su comando AT+CIOBAUD.

Encender petardos y cohetes con Arduino y Android

Creo que a estas alturas todos hemos visto cómo se encienden petardos y cohetes: simplemente acercando la llama de un mechero a la mecha de estos y la magia de la pólvora hace el resto.

En este artículo voy a explicar cómo hacer el mismo proceso pero de una forma más segura, y por supuesto más tecnológica.

1402682187170

Pero antes unas reglas básicas:

  • Los petardos y los cohetes son peligrosos, por eso se cauteloso cuando los manejes.
  • No enciendas un petardo o un cohete en la mano ni cerca de ti, de otras personas o animales.
  • No molestes a la gente encendiéndolos en zonas residenciales ni en horarios intempestivos.
  • Muchos municipios tienen prohibido el uso de material pirotécnico en toda su zona metropolitana.
  • El hilo de nicrom alcanza temperaturas elevadas, cerciorate que no pasa corriente por él cuando lo estés manejando.
  • Las baterías de litio son peligrosas, sigue las instrucciones de seguridad que las acompañan.
  • Usa cableado que permita un valor de corriente en amperios mucho mayor que lo que va a consumir el sistema.

Este artículo es meramente divulgativo y no me hago responsable de cualquier incidencia que pudiera ocurrir si lo pones en práctica, por tanto si lo llevas a cabo será bajo tu propia responsabilidad.

La idea es encender la mecha de petardos o cohetes desde un móvil Android, tal y como se puede ver en el siguiente vídeo que grabé para la demostración:

El esquema de los componentes es el siguiente:

esquema

Empezamos por una batería LiPo de 3 celdas (11,1 V.) que será la encargada de la alimentación del conjunto. Todo el cableado está pensado para corrientes de 10 A, pero puede diferir según tus necesidades.

Seguimos con un fusible de 10A, que será el que corte la corriente si se produce un cortocircuito (por ejemplo en el caso de que debido a la explosión de un petardo se unieran directamente los terminales VCC y GND que sujetan el hilo de nicrom).

A continuación está el hilo de nicrom. Este cable, que tiene muy poca resistencia (2,2 Ω en mi caso), se pone al rojo vivo cuando pasa una corriente a través de el. La velocidad a la que se calienta depende del voltaje que se aplique, lo normal suele ser alrededor de los 12 voltios. Este hará las veces de encendedor de la mecha, ya que puede llegar a los 300º C. Se puede adquirir en cualquier tienda de electrónica o reciclarse de un secador de pelo o de una tostadora.

Después viene un transistor mosfet de canal N, que será el interruptor que hará que el hilo de nicrom se encienda o se apague. Hay muchos tipos de mosfet de canal N, por lo que nos interesa uno que pueda ser usado con microcontroladores con lógica TTL (como el de la placa Arduino). Yo he usado el STP55NF06L con encapsulamiento TO-220 ¿por qué?, pues en la hoja de características podemos verlo:

El Vds es de 60 V. Como voy a usar 12 V. Tengo más que de sobra.

El Id es de 55 A. Según la ley de Ohm, La fuente de alimentación de 12 V. partido por la resistencia del hilo de nicrom con 2,2 Ω nos dá que se consumen unos 5 A. Igualmente tengo mucho margen.

El Vgs(th) minima es de 1V. Eso significa que cuando el voltaje es menor que 1V el circuito está abierto y que por encima de esto cerrará el circuito dejando pasar la corriente. Ideal para el Arduino que trabaja con 5 V.

La Rds(on) máxima es muy baja: 0,020 Ω. Esto significa que prácticamente el mosfet no se calentará con la corriente con la que le hagamos trabajar (5 A. * 5 A. * 0,020 Ω = 0,5 Watios)

La gráfica Id/Vds indica que con 5 V en el pin Gate del mosfet, podemos conducir una tensión de 12 V. con una carga de mucho más de 120 A. Como sólo tenemos unos 5 A. tenemos más que suficiente.

idvds

Como se trata de un mosfet de canal N, el pin Source (3) tiene que ir a masa y el pin Drain (2) tiene que estar conectado a la carga. El pin Gate (1) tiene que estar conectado a Arduino, que será quien le dirá si tiene que estar abierto o no. Además entre la conexión del Arduino y Gate hay una resistencia de 10K que va a masa directamente, esto es para que:

  • La puerta lógica no quede flotante y su estado esté indeterminado (pudiendo activar el nicrom antes de tiempo), por lo que si el pin de Arduino esta puesto configurado como entrada (al arrancar siempre está asi) el Gate esté conectado a masa (0 V. o LOW).
  • Debido al caso anterior, cuando el pin de Arduino está configurado como salida y pone la entrada a 5 V. (o HIGH), la resistencia de 10K hace que no haya cortocircuito con masa.

Proseguimos con la placa Arduino, cuyo programa se puede descargar de aquí. La placa está alimentada también desde la batería LiPo, ya sea directamente a los pines Vin y GND o a través del conector de alimentación. Unido a Arduino está un módulo Bluetooth HC-06 que será el encargado de comunicarse con el móvil.

Finalmente en el móvil, que tiene que tener el sistema operativo Android, hay que instalar la aplicación ArduDroid desde la Play Store, que con su interfaz sencilla podemos manejar los pines de Arduino directamente.

Screenshot_2014-06-16-13-37-04

Televigilancia con un coche RC, arduino y la raspberry pi

¿Quién no ha tenido alguna vez la necesidad de poder ver nuestra casa desde otro lugar (oficina, hotel, otra casa, etc), o poder hacer inspección de tuberías, respiraderos o sitios inaccesibles? La idea que planteo en este artículo es la de un coche teledirigido al que podemos manejar remotamente mediante wifi y que veamos por donde va.

vigilancia

Principalmente está compuesto de un coche RC, una placa arduino duemilanove (o UNO) con una motorshield y una raspbery pi modelo B con dos USB (un WIFI y una webcam) y el sistema operativo Raspbian.

El funcionamiento es sencillo: Por un lado con un programa en python que se ejecuta en la raspberry pi hacemos un servidor que reciba los comandos por tcp/ip, estos son enviados mediante el puerto serie de la raspberry pi al puerto serie del arduino, que será el encargado de manejar la motorshield para mover el conjunto. Por otro lado en la propia Raspberry Pi hacemos streaming de vídeo para que podamos ver a través de su webcam remotamente.

Todo está alimentado con una batería Lipo 7,4 V. (2S)  de 1000 mAh. Por un lado está conectado directamente a arduino y por otro a un regulador UBEC para alimentar a la raspberry pi a través de los pines GPIO de 5v y GND.

La comunicación entre la rasbperry Pi y arduino se hace simplemente con un cable, ya que no es necesario ninguna protección al ser el pin TX de la raspberry pi el que se conecta al pin RX de arduino, y por tanto no hay riesgo con los voltajes diferentes (siempre y cuando no reprogrames arduino, si es así desconecta el cable de RX hasta haber terminado).

arduino_raspberry

El programa de Arduino es bastante simple, sólo comprueba si existe un byte en el puerto serie y si lo hay lo interpreta para saber qué movimiento hay que hacer con los motores. Se parte del byte 0x30 (0 en ASCII) y se comprueban sus bits:

  • Si el bit 0 está activado el coche va hacia delante.
  • Si el bit 1 está activado el coche va hacia atrás.
  • Si los bits anteriores están desactivados entonces el coche no se mueve.
  • Si el bit 2 está activado gira las ruedas a la izquierda.
  • Si el bit 3 está activado gira las ruedas a la derecha.
  • Si los bits anteriores están desactivados entonces la dirección el coche permanece recta.

En el lado de la Raspberry Pi hay que instalar primero varias cosas:

Editado 17/04/2014: Desactivar la consola serie que viene por defecto activada:
En el fichero /etc/inittab poner una almohadilla (#) al principio en la línea:
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
En el fichero /boot/cmdline.txt sustituir la línea:
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
por
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
Finalmente hay que reiniciar la Raspberry Pi para que coja los cambios.

Después hay que dar permisos de lectura y escritura al puerto serie:

A continuación creamos un fichero llamado servidor.py:

Este programa python se encarga de crear un socket tcp/ip que escucha por el puerto 1976 , cuando alguien se conecta a este puerto entonces permanece a la espera de recibir los bytes que posteriormente enviará a Arduino a través del puerto serie.

Finalmente crearemos un fichero llamado webcam.sh con el siguiente contenido (cambiar 192.168.1.133 por la ip que tenga vuestra raspberry pi):

Este programa shell arrancará un servidor de streaming con GStreamer. De momento GStreamer es el software que conozco que funciona más rápido enviando imágenes con un retardo de 2 segundos, ffmpeg tenía un retardo de hasta ¡¡¡ 10 segundos !!!. La idea la cogí de aquí.

Ahora que ya tenemos lo necesario en nuestra parte del coche, necesitamos configurar el router para redirigir los puertos 22, 1976 y 5000 hacía la ip que tenga la Raspberry Pi.

Desde el ordenador remoto necesitaremos tener el programa VLC para el recibir el streaming, un cliente de ssh  (en windows el mejor es el putty) y Processing para enviar los comandos.

Los pasos para hacer que nuestro sistema de televigilancia son los siguientes:

Conectar mediante ssh a la raspberry pi y ejecutar el comando:

Abrir otra sesión de ssh y ejecutar el comando:

Arrancar VLC y abrir una ubicación de red poniendo la siguiente línea, con esto podremos ver lo que hay frente a la webcam (cambiar 192.168.1.133 por la ip que tenga vuestra raspberry pi):

Arrancar el Processing con el siguiente programa y ejecutarlo (cambiar 192.168.1.133 por la ip que tenga vuestra raspberry pi):

Si todo ha ido bien, ponemos la ventana de processing que nos ha abierto como activa cuando hemos lanzado el programa y pulsamos los botones de los cursores del teclado, momento en el cual veremos a través de la webcam (o en local si lo tenemos enfrente) cómo nos desplazamos.

Y finalmente un vídeo de cómo funciona:

L.I.O.S.: El robot de 10$

English version

Introducción:

Hace algún tiempo leí un artículo sobre un concurso para crear un robot con un coste de 10$ para el aprendizaje de robótica en escuelas con un coste admisible. Este concurso es el reto AFRON.

Así que me pareció una buena idea participar. Se me ocurrió que un robot  muy simple de hacer pero que es un buen punto de partida para aprender es un seguidor de luz, donde los sensores del robot están buscando si hay un foco luz y cuando lo encuentran se dirigen hacia el. Me puse a buscar los componentes, a construir el robot y al final he terminado a L.I.O.S. (Light input output system):

Como se puede ver en el vídeo, las ruedas y el chasis son de cartón de una caja reciclada. Aunque no se aprecie, los sensores son LDR, los motores son dos servos trucados para rotación continua, el cerebro es un microcontrolador PIC 12F683, tiene dos diodos led para indicar el estado y una batería lipo de 3,7V. y 130 mAh para alimentar el sistema.

Funcionamiento:

Nada más enchufar la batería los leds parpadean varias veces. Hay dos LDR que el microcontrolador está comprobando constantemente; si este detecta que en uno de ellos  hay una intensidad de luz grande, entonces enciende el led del lado del LDR y activa el servo del lado contrario (si la luz está a la derecha, entonces es la rueda izquierda la que tiene que moverse y viceversa); si ambos sensores detectan luz entonces los dos led se encienden y los dos motores se activan para ir recto; si no detecta suficiente luz entonces permanece parado y los leds apagados.

Consumo

En resposo consume 23 mA.
Cuando sigue una luz puede consumir hasta 300 mA.

Velocidad

8,7 cm/s. cuando la batería está a 3,7V.

Construcción:

Componentes

Nombre Descripción Precio unitario (enlace) Cantidad Total
PIC12F683 El cerebro 1,78$ 1 1,78$
  Zócalo DIP Para meter o sacar el PIC 0,18$ 1 0,18$
  Batería Lipo Para alimentar el circuito 1,33$ 1 1,33$
  Conector hembra Para enchufar la batería 0,47$ 1 0,47$
  LDR Para detectar la luz 0,32$ 2 0,64$
  Servo Para mover el robot 2,69$ 2 5,38$
  diodo led Para mostrar estado 0,13$ 2 0,26$
  Resistencia 180Ω Para los led 0,08$ 2 0,16$
  Resistencia 10KΩ Para los LDR y los servos 0,08$ 6 0,48$
Otros Cartón (reciclable de cualquier caja), cables (usar los del propio servo), estaño, pegamento y tubo termoretráctil 0,05$ (por reciclaje o mínimas cantidades) 0,05$

Total

10,73$

Herramientas

Nombre Uso Precio aproximado
Cutter Cortar el cartón  4$
  Pegamento Pegar cartón, brazos de servos y servos  3$
  Cinta adhesiva Pegar la plantilla y la batería al cartón  1,50$
Aguja Agujerear el cartón 0,02$
  Pistola de termocola Pegar LDR, leds, resistencias y zócalo al cartón  15$
  Pelacables Pelar todos los cables  10$
  Mechero Reducir los tubos termoretráctiles  2$
  Corta cables Cortar topes de los servos, cables y tubos termoretráctiles  5$
  Destornillador PH0 Apretar o aflojar los tornillos de los servos  1$
  Soldador Soldar cables con LDR, leds, resistencias, enchufe y zócalo  10$ – 25$
  Estaño Para soldar 5$
  Programador Programar el PIC 14$ – 45$
Cargador de baterías Cargar la batería Lipo 15$ – 75$
Multímetro Medir la carga de la batería Lipo 5$ – 30$

Precauciones

  • La hoja del cutter es afilada, tener cuidado de no cortarse.
  • La aguja es muy fina, tener cuidado de no pincharse.
  • El pegamento es muy fuerte, tener cuidado de que no entre en contacto con los ojos y/o la piel.
  • La termocola está muy caliente, tener cuidado de no tocarla.
  • El soldador está muy caliente, tener cuidado de no tocarlo, de no ponerlo en contacto con el cartón y de evitar respirar el humo de la soldadura.
  • La batería lipo no debe cortocircuitarse, ni sobrecargarse por encima de 4,2V. ni descargarse por debajo de 3V.

Servos

Los servos contienen electrónica para manejar su sentido de rotación y tienen engranajes para aumentar su fuerza de tracción, sin embargo sólo pueden rotar 180º, por lo que vamos a modificarlos para que su rotación sea continua como la de cualquier motor.

Lo primero es desmontarlos extrayendo los 4 tornillos de su base y separar las tapas inferior y superior:

Después hay que extraer los engranajes. Uno de ellos contiene una pestaña para que haga de tope y no avance más (marcado con un circulo rojo):

Así es como queda al cortarla:

Por otro lado tenemos el potenciómetro. Aquí debemos desoldar los cables (las flechas verdes) y romper la pared que contiene las dos pestañas que también hacen tope (las fechas rojas):

Así es como quedaría la pared que comentaba:

A continuación debemos soldar las dos resistencias de 10KΩ formando un divisor resistivo en los cables que habíamos desoldado antes (el cable blanco entre las dos resistencias). Para aislar los contactos poner tubo termoretráctil:

También aislar el extremo con tubo termoretráctil:

Finalmente unir todos los engranajes de nuevo, meter la electrónica, poner las tapas y atornillarlas:

Chásis y ruedas

Imprimir en papel esta plantilla en DXF a escala 1:1 (yo he usado el programa de software libre LibreCad):

Pegar el papel con cinta adhesiva al cartón. Agujerear los círculos pequeños con una aguja y cortar las líneas con un cutter:

A continuación poner la aguja en el agujero de una rueda, poner pegamento en el brazo alargado de un servo e introducir el agujero central de este por la aguja hasta pegarlo a la rueda. Repetir el proceso con la otra rueda:

Quitar la pegatina del lateral del servo, poner pegamento en ese lateral y pegarlo en el extremo superior izquierdo de la superficie grande de cartón. Repetir el proceso en el otro lado con el otro servo:

Cortar levemente la superficie pequeña de cartón por el primer tercio, poner pegamento y adherirla a la incisión hecha anteriormente en la superficie grande de cartón (según la plantilla). Colocar las dos ruedas en los ejes del servo:

Agujerear 4 orificios entre los servos, introducir desde abajo los LDR, girarlos 30 grados desde el centro y pegarlos con termocola. Hacer dos orificios a cada lado, introducir desde abajo los diodos led y pegarlos con termocola:

Electrónica

Este es el esquema electrónico:

LDR

  • Soldar una de las patillas de cada LDR a VCC.
  • Soldar la otra patilla de cada LDR a un extremo de una resistencia de 10KΩ
  • Desde la anterior unión izquierda soldar un cable hasta el pin 7 del zócalo y poner tubo termoretráctil.
  • Desde la anterior unión derecha soldar un cable en hasta el pin 6 del zócalo y poner tubo termoretráctil.
  • Soldar el otro extremo de cada resistencia a GND.
  • Pegar las resistencias a la base con termocola.

SERVO

  • Pelar los cables y soldar el rojo a VCC y el marrón a GND de cada servo.
  • Soldar el cable naranja del servo izquierdo al pin 3 del zócalo y poner tubo termoretráctil.
  • Soldar el cable naranja del servo derecho al pin 2 del zócalo y poner tubo termoretráctil.

LED

  • Soldar un extremo de una resistencia de 180Ω a VCC.
  • Soldar el otro extremo al de otra resistencia de 180Ω.
  • Desde la anterior unión soldar un cable hacia la patilla del ánodo del led derecho.
  • Desde la anterior unión soldar un cable hacia la patilla del cátodo del led izquierdo.
  • Soldar el extremo restante de la segunda resistencia a GND.
  • Pegar las resistencias a la base con termocola.
  • Desde el cátodo del led derecho soldar un cable hacia el ánodo del led izquierdo.
  • Desde la anterior unión soldar un cable hacia el pin 5 del zócalo y poner tubo termoretráctil.

PIC

  • Soldar el pin 1 del zócalo a VCC y poner tubo termoretráctil.
  • Soldar el pin 8 del zócalo a GND y poner tubo termoretráctil.
  • Pegar el zócalo a la base con termocola.

Batería

  • Enchufar el conector a la batería y comprobar cual es VCC y cual GND con un polímetro.
  • Soldar un cable a VCC y otro a GND y juntarlos con el resto del circuito. Poner tubo termoretráctil.
  • Enrollar un trozo de cinta adhesiva y ponerla en la zona trasera de la base.
  • Poner la batería encima de la cinta adhesiva y enchufar esta al conector.

Programación:

Desde aquí se puede descargar el código fuente para el firmware del PIC. Para entender el funcionamiento de los registros del PIC 12F683 lo mejor es leerse el datasheet.

Desde aquí se puede descargar el fichero .hex para programar el PIC.

El compilador que se ha usado es el SDCC, que es software libre. Para compilarlo he usado el siguiente comando:

Para subir el fichero .hex al PIC hay que tener un programador de PICs y un software que maneje el programador. Hay mucha variedad. Yo he usado el pickit3 de Microchip y su software para windows, pero hay otras alternativas más baratas que se pueden usar con software libre o gratuitas para linux, mac y windows.

Explicación

A grandes rasgos el funcionamiento es el siguiente:

Al enchufar la batería los leds parpadean 10 veces rápidamente. Los leds están en una configuración determinada para que si el pin del PIC está configurado como salida y la pone en alto luzca un led, si la pone en bajo luce el otro led; si está configurado como entrada (alta impedancia) los leds permanecen apagados.

Se activan las interrupciones del timer0 y del ADC. La interrupción del timer0 está configurada para que salte cada 0,1 ms. y sirve para contabilizar los tiempos en los servos. La interrupción del ADC salta cada vez que un valor ha sido leído en un LDR para activar el led asociado (si se traspasa cierto umbral), poner un valor en una variable de estado, cambiar el canal de ADC y leer el siguiente LDR.

En el bucle principal del programa se comprueba la variable de estado para saber qué servos deben activarse. La activación de los servos es distinta ya que estos están enfrentados y la rotación para ir hacia delante es diferente en cada uno. Para uno supone una señal alta de 1 ms y otra baja de 19 ms., mientras que para el otro supone una señal alta de 2 ms y otra baja de 18 ms.

Modificaciones:

Los sensores del robot son LDR, pero podrían haberse cambiado por dos CNY70 para hacer un robot seguidor de línea con el siguiente esquema:

O dos interruptores de acción rápida para hacer un robot que detectase colisiones con el siguiente esquema:

Probando el marco digital Parrot DF3120 (parte 3 y final)

Con este artículo termino de explicar cómo explotar todas las características de este marco digital. Este artículo lo dividiré en 3 partes debido a su extensión.

La primera parte consiste en explicar cómo usar la librería SDL (Simple Directmedia Layer) para dibujar en la pantalla. Lo bueno de esta librería es que es muy sencilla de usar y te facilita bastante el dibujar gráficos en la pantalla mediante programación.

La segunda parte trata sobre usar las entradas de información del marco. Se va a leer el estado de los 3 botones, del inclinómetro y la cantidad de luz que hay en el ambiente .

La tercera parte la he reservado para las comunicaciones. Dado que el marco tiene bluetooth y una tarjeta de red configurada voy a explicar cómo intercambiar información entre el marco y otros dispositivos.

1- Librería SDL

Antes de empezar a explicar, lo mejor será que ponga un vídeo, después el código fuente, a continuación cómo compilarlo, ejecutarlo y finalmente explicar su funcionamiento.

[VÍDEO]

[CÓDIGO]

[COMPILACIÓN]

Para compilar el programa, copiad el código fuente y guardarlo en la carpeta minifs con el nombre pruebasdl.c, después desde ese mismo directorio ejecutad el comando:

[EJECUCIÓN]

Una vez se haya creado el fichero pruebasdl, descargarlo en el marco junto con las siguientes imágenes:

tal y como explicaba en el anterior artículo y ejecutarlo. Si todo ha ido bien veréis lo mismo que en el vídeo. Para salir del programa simplemente pulsar las teclas CONTROL y C simultáneamente.

[EXPLICACIÓN]

Explicaré cómo funciona el programa. Un buen tutorial de SDL en español lo podéis descargar de aquí.

  • Se declaran los punteros SDL_Surface, que son los que contendrán las imágenes y el buffer de la pantalla.
  • La función SDL_Init se llama con el parámetro SDL_INIT_VIDEO para inicializar la librería SDL internamente.
  • La función SDL_GetError devuelve una cadena con el último error ocurrido en la librería SDL.
  • La función atexit con el puntero a la función SDL_Quit se llama para que, cuando la aplicación termine, se llame a la función SDL_Quit y libere todos los recursos usados por la librería.
  • La función SDL_SetVideoMode se llama para inicializar el buffer de la pantalla con los parámetros de anchura, altura, profundidad de color y que use la memoria de vídeo con la técnica de doble buffer (haciendo un OR de los valores SDL_HWSURFACE y SDL_DOUBLEBUF). Esta función nos devuelve la estructura SDL_Surface de ese buffer de pantalla.
  • La función SDL_ShowCursor se llama con el parámetro SDL_DISABLE para ocultar el puntero del ratón en la pantalla.
  • La función IMG_Load se llama con la ruta de una imagen como parámetro para cargar la imagen. Esta función nos devuelve la estructura SDL_Surface de la imagen.
  • La función signal se llama con el parámetro SIGINT y un puntero a una función para que se capture la pulsación de las teclas CTRL y C. Cuando se pulsen se llamará a la función salida que simplemente cambiará el valor de la variable salir. Esto se usa para poder salir del bucle principal y terminar el programa de una forma limpia.
  • La función SDL_BlitSurface se llama con una imagen, un valor nulo, el buffer de la pantalla y una estructura SDL_Rect como parámetros. Esto copia la imagen en el buffer de la pantalla en el lugar indicado por la estructura SDL_Rect.
  • La función SDL_SetAlpha se llama con una imagen, con los valores SDL_SRCALPHA y SDL_RLEACCEL y un número como parámetros. Esto modifica la transparencia de una imagen (valor 0 para transparente y valor 255 para opaca). No funciona bien con los PNG, por eso la imagen del sol es un GIF.
  • La función SDL_Flip se llama con el parámetro del buffer de pantalla para traspasar todos los pixels del buffer de pantalla a la tarjeta de vídeo y así mostrarlos.
  • La función SDL_Delay se llama con un número como parámetro para parar la ejecución del programa durante un tiempo especificado en milisegundos.
  • La función SDL_FillRect se llama con el buffer de pantalla, una estructura SDL_Rect y un color como parámetros para que dibuje en la zona determinada por la estructura SDL_Rect un rectángulo con el color especificado. En las animaciones se usa para eliminar el dibujo anterior al que se va a pintar y así dar un efecto de movimiento.
  • La función SDL_MapRGB se llama con el formato del buffer de la pantalla y 3 números como parámetros. Sirve para mapear un color RGB al formato del buffer de la pantalla y así adaptarlo a su profundidad de color.
  • La función SDL_FreeSurface se llama con una estructura SDL_Rect como parámetro para liberar todos los recursos utilizados por esta.

Con todo esto hemos logrado dibujar en la pantalla imágenes png y gif, además de animar dos de ellas en un bucle (una haciendo círculos gracias a las funciones trigonométricas de seno y coseno y la otra a fundirse mediante transparencia) a la espera de que el usuario pulse la combinación de teclas CTRL+C para salir del programa.

2- Entradas de información

Al igual que antes pongo un vídeo, después el código fuente, a continuación cómo compilarlo, ejecutarlo y finalmente explicar su funcionamiento.

[VÍDEO]

[CÓDIGO]

[COMPILACIÓN]

Hay que hacer lo mismo que en la COMPILACIÓN del apartado Librería SDL. Sólo que esta vez el fichero de salida se llama pruebaentradas y el del código fuente pruebaentradas.c.

[EJECUCIÓN]

Hay que hacer lo mismo que en la EJECUCIÓN del apartado Librería SDL, incluidas las imágenes si no las tenéis ya. Sólo que esta vez el fichero se llama pruebaentradas.

[EXPLICACIÓN]

En esta ocasión he aprovechado el código del anterior apartado y le he modificado para que responda a eventos. Ahora cada vez que se pulse un botón saldrá en la pantalla el icono correspondiente, se mostrará hacia que lado del marco está la gravedad y cuanta luz llega al sensor trasero.

Me centraré en explicar cómo he recuperado la información de las entradas de las que dispone el marco (botones, inclinómetro y fotoresistencia).

Si os acordáis en el primer artículo explicaba cómo acceder a la memoria del vídeo para escribir los píxeles de la imagen directamente en ella. Aquí lo que vamos a hacer es abrir el fichero /dev/mem ya que desde él podemos acceder a los registros del microprocesador que contienen la información de las entradas y poder configurarlas. Si queréis saber a fondo cómo funciona el microprocesador s3c2412 que gobierna el marco os podéis bajar su datasheet. Las entradas de los botones se pueden leer desde los pines 2, 3 y 4 del puerto F y las del inclinómetro desde los pines 9 y 10 del puerto G, en ambos casos son GPIO y los leeremos mediante polling. El valor de la fotoresistencia se puede leer del pin ADC0 y como indica el nombre es un ADC que leeremos igualmente mediante polling.

En la función inicializa_entradas inicializaremos los registros:

  • Con la función open abrimos el fichero /dev/mem como lectura y escritura.
  • Con la función mmap abrimos las posición de memoria 0x56000000 para poder acceder desde el espacio de usuario a los registros de configuración y de datos de los puertos GPIO y la posición de memoria 0x58000000 para leer los canales ADC. Estos números se pueden encontrar en las páginas 68 y 69 del datasheet que he puesto antes.
  • Para leer los puertos F y G debemos configurarlos antes. Para esto debemos acceder a las direcciones de memoria de configuración del puerto F (GPFCON 0x56000050) y del puerto G (GPGCON 0x56000060) e indicar qué bits serán de lectura. En el puerto F serán los bits 2, 3 y 4 por lo que el valor de configuración para este registro (según las página 275 del datasheet) será xxxxxx000000xxxx, o lo que es lo mismo, para dejar el resto de bits a su valor original y sólo cambiar los 6 bits de los botones hay que hacer una operación AND del valor 0xFC0F. En el puerto G serán los bits 9 y 10 por lo que el valor de configuración para este registro (según la página 276 del datasheet) será xxxxxxxxxx0000xxxxxxxxxxxxxxxxxx, o lo que es lo mismo, para dejar el resto de bits a su valor original y sólo cambiar los 4 bits del inclinómetro hay que hacer una operación AND del valor 0xFFC3FFFF.
  • Para leer continuamente el valor del canal 0 del ADC donde se encuentra conectada la fotoresistencia debemos configurar el registro ADCCON situado en la dirección de memoria 0x58000000.  Lo inicializaremos asignándole el valor 0x7FC2 (según la página 420 del datasheet). Finalmente leemos el valor del ADC para activarlo.

En la función lee_entradas leeremos el valor de las entradas y los guardaremos en una estructura llamada ENTRADAS:

  • Accedemos a las direcciones de memoria de datos del puerto F (GPFDAT 0x56000054) y G (GPGDAT 0x56000064), extraemos uno por uno los valores de los pines con una operación AND, desplazamos esos valores mediante shifting hasta dejarlos en el primer bit  y los vamos guardando en la variable correspondiente de la estructura. Los botones cuando están libres tienen un valor de 1, pero cuando están pulsados tienen un valor de 0. El botón izquierdo corresponde al pin 3, el botón central corresponde al pin 4 y el botón derecho al pin 2. El inclinómetro tiene un valor de 3 cuando el marco reposa sobre su base , un valor de 2 si reposa sobre el lado derecho y un valor de 1 si reposa sobre el lado izquierdo. No detecta cuando el marco reposa por el lado contrario a la base (que sería un valor de 0).
  • Para el ADC0 accedemos a su dirección de memoria de configuración (ADCCON 0x58000000), leemos su valor y comprobamos que el último bit está a 1 para saber si podemos leer el resultado de la conversión o todavía la está haciendo, si está a 1 leemos la dirección de memoria de datos (ADCDAT0 0x5800000C), nos quedamos con los primeros 10 bits y hacemos una conversión a 8 bits para que se pueda usar directamente en la función  SDL_SetAlpha.

Con todo esto hemos modificado el programa del apartado Librería SDL para que ahora sólo represente las imágenes dependiendo del estado de las distintas entradas que componen el marco digital.

3- Comunicaciones

Como en los casos anteriores pongo un vídeo, después el código fuente, a continuación cómo compilarlo, ejecutarlo y finalmente explicar su funcionamiento.

[VÍDEO]

[CÓDIGO]

[COMPILACIÓN]

Hay que hacer lo mismo que en la COMPILACIÓN del apartado Librería SDL. Sólo que esta vez el fichero de salida se llama pruebacomunicaciones y el del código fuente pruebacomunicaciones.c.

[EJECUCIÓN]

En el ordenador debéis tener bluetooth ya sea incorporado o mediante un usb y conexión a internet.

En el ordenador activar el ruteo de paquetes tcp/ip para la interfaz de red del marco (ejecutarlo todo como usuario root, en ubuntu con sudo -s)

En el marco activar la ruta por defecto de los paquetes tcp/ip

En el marco dejar visible a todos el bluetooth y permitir conexiones al marco

En el marco mostrar la MAC ADDRESS del bluetooth (para saber a donde se debe conectar el ordenador por rfcomm)

En el marco dejar en modo de escucha para rfcomm

En el ordenador conectarse al marco mediante rfcomm

En el ordenador descargarse el programa screen (si no se tenía antes)

En el ordenador conectarse al dispositivo rfcomm0 con el programa screen

En el marco ejecutar el programa

En el ordenador desde el programa screen escribir caracteres. ENTER para hacer salir el programa del marco.

Anotaciones

Tendreis que abrir una consola nueva tanto en el ordenador como en el marco después de ejecutar el comando rfcomm puesto que se queda permanentemente conectado hasta que se pulse CTRL + C.

Para salir del programa screen simplemente pulsad CTRL y A a la vez y después de soltarlos pulsad la tecla K.

[EXPLICACIÓN]

Por un lado se pretende conectar mediante bluetooth al marco usando las utilidades BlueZ mediante RFCOMM. Así conseguimos que desde nuestro ordenador podamos enviarle datos al marco.

Por otro lado pretendemos conectarnos a una página de Internet para recuperar una imagen y mostrarla en el marco.

La unión de ambas cosas es lo que habéis visto en el vídeo. Mientras escribo en el programa screen caracteres, estos se envían al marco mediante bluetooth. Despueś el marco los va concatenando y va llamando a una página web que he hecho a tal efecto para que vaya generando la cadena de texto en una imagen PNG. Esta imagen se la descarga el marco y posteriormente la muestra.

Gracias a las utilidades de BlueZ la conexión bluetooth ya se establece mediante comandos y nosotros nos tenemos que dedicar simplemente a abrir el fichero /dev/rfcomm0 y desde este escribir o leer con las funciones básicas que proporciona C para manejo de ficheros.

Las conexiones a Internet se consiguen mediante programación de sockets y esto nos da mucho juego para poder pedir información (descargar una imagen, llamar a un servicio web, etc.) y luego mostrarla en nuestro marco. En el ejemplo cuando se llama a la función carga_imagen hacemos una conexión http a https://www.sistemasorp.es/blog/imagen.php con la cadena pasada como parámetro y guardamos en el fichero texto.png la imagen PNG que se ha generado. No voy a explicar qué hace cada función de los sockets, pero si os recomiendo leer el mejor manual que hay en internet para saber cómo programarlos: Beej’s Guide to Network Programming.

Y aquí acaban esta serie de artículos esperando que os haya servido de ayuda para que podáis empezar a juguetear con el marco y sacarle muchas utilidades. Me gustaría que si hicieseis algo con el lo pusierais en los comentarios, además de vuestras dudas o lo que sea.

1º artículo

2º artículo

Recuperar una cámara Zaapa CIP-RW después de un fallo de actualización

Hace tiempo que mi amigo Roberto quiso actualizar su cámara IP (la cual compró por recomendación mía). El caso es que al actualizar el firmware el proceso falló y la cámara quedó inutilizada. Así han pasado ya muchos meses hasta que hace unos días me encontré con esta página que hablaba de cómo recuperar una cámara Foscam FI8908W cuando el proceso de actualización de firmware ha fallado.

Lo bueno de esta página es que habla de que las cámaras foscam (y la zaapa ciprw es una de ellas con el modelo FI8901W) no mueren del todo, sino que tienen un puerto serie escondido al que se puede acceder y comunicarse con una consola para cargar un firmware. Yo me he comunicado con la cámara con un conversor serie TTL a USB:

La solución ya estaba, sólo tenía que conseguir el firmware de la zaapa (ya que otros no valen) y decirle a mi amigo que me dejase su cámara para arreglársela. Pero no ha sido así de fácil y he tenido que pelearme con varios frentes.

El primero es el servicio técnico de Foscam. En el comentario 101 del anterior enlace un tal David comentaba que Doris de Foscam había sido muy amable y que le había dado los ficheros de recuperación. Yo probé la misma suerte con el servicio técnico de Foscam y esta fué la primera respuesta que obtuve:

Hi,

We do not have a model No. FI8901W camera, could you please double check the model No.?

Es decir, que no saben ni los modelos que han fabricado. Le dije que si existía ese modelo de cámara en su marca y me contesto esto otro:

Hi,

Sorry for my mistake. We have stopped produce this product for a long time. We do not have the firmware now. Sorry for this.

Vamos que no querían ayudarme en nada (David, que suerte tuviste…).

Buscando por Internet unos ficheros de recupercación para la zaapa o para la FOSCAM FI8901W no encontré nada. Pero por suerte encontré esto otro. Una forma de extraer de una cámara que funcionase su firmware a través de la consola serie oculta. El proceso fue pesado: me tuve que bajar el kermit 95 y buscar cómo demonios abrir una consola serie, después esperé un rato largo a que se ejecutara el script, convertir con el jedit una salida en otro fichero y finalmente pasar el convertidor de hexadecimal a binario, el cual tuve que compilar, modificar y compilar de nuevo para que funcionase. Todo esto para que al final no se hubiera decargado correctamente el firmware linux.bin y romfs.img necesarios para reprogramar la cámara estropeada, dando esta errores nada más arrancar.

Parecía que no iba a dar con la solución, pero encontré un programa que te descargaba automáticamente los ficheros necesarios del firmware. Lo ejecuté y parecía que había hecho bien su trabajo, pero pasó lo mismo que en el anterior párrafo aunque esta vez sólo con el fichero linux.bin. Sin embargo gracias a esta otra página descubro que el fichero linux.bin es en realidad un archivo .zip y que lo que había hecho está aplicación es comerse los últimos 168 bytes, asi que leyendo la memoria de  la cámara que funcionaba recuperé esos 168 bytes.

Finalmente seguí paso por paso el proceso de nuevo pero cambiando los comandos fx por estos:

Para Windows 7 como no existe el Hyperterminal, he usado el Tera Term.

Finalmente la cámara de mi amigo ha dejado de ser un pisapapeles y ha vuelto a funcionar, pudiéndola manejar ahora con Firefox, con su IPhone, etc.

Para evitaros las incomodidades por las que yo he pasado os dejo los enlaces de los ficheros de recuperación de la versión que le instalé a mi amigo y que es la última que proporciona Zaapa:

romfs.img

linux.bin

Embeded Web UI 2.0.0.16.bin

 

Probando el marco digital Parrot DF3120 (parte 2)

En el anterior artículo explicaba cómo instalar linux en el marco digital Parrot DF3120. En este explicaré cómo generar el toolchain para poder crear programas que funcionen en el marco digital. De paso crearemos una versión de la imagen más moderna para nuestro marco. El artículo original que lo explicaba es este, pero está desfasado y hay que hacer retoques para que funcione bien.

Lo voy a hacer todo desde mi linux Ubuntu 11.10, por lo que es posible que algunas cosas haya que modificarlas si usáis otra distribución.

Lo primero es instalarse usa serie de paquetes que son necesarios para que todo el proceso sea correcto:

Después hay que bajarse minifs con el git:

A continuación hay que hacer un par de modificaciones:

  • Edita el fichero minifs/conf/board/df3120/config_busybox.conf y reemplaza la línea # CONFIG_CHMOD is not set por CONFIG_CHMOD=y
  • Edita el fichero minifs/conf/packages/05crosstools.sh y reemplaza la línea hset libtool url “http://ftp.gnu.org/gnu/libtool/libtool-2.4.2.tar.gz” por hset libtool url “http://ftp.gnu.org/gnu/libtool/libtool-2.4.tar.gz”
  • Edita el fichero minifs/conf/packages/11graphical.sh y reemplaza la línea hset libpng url “ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.4.8.tar.bz2” por hset libpng url “ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.4.9.tar.bz2”

Después ya podemos ejecutar el script de la siguiente forma (Puede tardar varios minutos):

Ahora vemos que entre otras cosas se han creado dos ficheros en el directorio build-df3120, un .img y un .plt. Pues bien con ellos hay que volver a hacer lo mismo que comentaba en el anterior artículo. Si todo ha ido bien veremos la nueva versión del firmware donde lo más destacado es que aparecen los mensajes de arranque:

Ahora vamos a compilar nuestro primer programa, y cómo no, tenía que ser un Hola Mundo:

Copiamos el código que aparece arriba y lo guardamos en un fichero llamado holamundo.c. Después ejecutamos el siguiente comando:

Esto habrá generado un fichero ejecutable llamado holamundo, pero ¿cómo lo subimos al marco para ejecutarlo?. Pues bien entre otros comandos el marco tiene dos, el tftp y wget para descargar ficheros mediante el protocolo tftp y http respectivamente, por tanto hay que instalar un servidor web o tftpd en nuestra máquina linux.

Servidor web apache:

Servidor tftp: Instrucciones

Si hemos optado por el servidor web sólo hay que copiar el fichero holamundo al directorio /var/www. Si la elección ha sido tftpd entonces hay que copiar el fichero holamundo al directorio que se haya configurado.

Ahora tenemos que descargarlo desde el marco digital. Hacemos un telnet como explicaba en el anterior artículo. En el firmware actual todo el disco está montado como sólo lectura, por lo que tendremos que remontarlo como escritura también de la siguiente forma:

Ahora nos vamos al directorio /tmp y descargamos el programa.

Para tftp el comando sería:

Para wget el comando sería:

Ahora que tenemos el fichero, hay que darle permisos de ejecución y finalmente ejecutarlo:

Obtendremos esto:

Ya hemos compilado nuestro primer programa y lo hemos hecho funcionar, pero claro, nos interesa que se pueda dibujar en la pantalla algo para ver cómo se ve en el marco. Lo primero que hay que saber es que la pantalla tiene asignado el dispositivo /dev/fb0 y que lo que tenemos que conseguir es acceder a su memoria para escribir directamente los colores. Esto se consigue de la siguiente forma:

Con la función open abrimos el dispositivo como lectura/escritura:

Con la función ioctl recibimos en una estructura información sobre la pantalla:

Con la función mmap obtenemos el buffer de la memoria de vídeo para leerlo y escribir en el:

Ahora sólo queda dibujar los bytes en la memoria para que se vean reflejados como pixeles en la pantalla. Al poder representar la pantalla 64k colores estos se codifican a RGB mediante 16 bit con el formato 5-6-5 (rrrrrggggggbbbbb). Así el rojo es 1111100000000000 (0xF800), el verde es 0000011111100000 (0x07E0) y el azul es 0000000000011111 (0x001F). Por tanto cada pixel en la pantalla ocupa 16 bits.

Para probar todo esto he creado un programa que muestra un cuadro verde rebotando por el marco usando la técnica de doble buffer para evitar parpadeos: