Archivo de la categoría: Avanzado

Software Arduino a fondo

Programación Arduino

El lenguaje de programación de Arduino es C++, aunque es posible programarlo en otros lenguajes. No es un C++ puro sino que es una adaptación que proveniente de avr-libc que provee de una librería de C de alta calidad para usar con GCC (compilador de C y C++) en los microcontroladores AVR de Atmel, denominado avr-gcc, y otras muchas funciones específicas para las MCU AVR de Atmel.

El lenguaje de los AVR es un entorno C para programar los chips de Atmel, la mayor parte del lenguaje o core de Arduino está escrito con constantes y funciones AVR y hay bastantes cosas que no son fáciles de hacer con el lenguaje de Arduino sin el uso de código AVR de la avr-libc.

Como el entorno de Arduino usa GCC para compilar el código, todas las variables de los puertos y de los registros de una MCU de Atmel son soportadas por el IDE de Arduino.

Las herramientas necesarias para programar los microcontroladores AVR de Atmel son avr-binutils, avr-gcc y avr-libc y ya están incluidas en el IDE de Arduino, cuando compilamos y cargamos un sketch estamos usando estas herramientas.

Para usar un microcontrolador ATmega8  de la familia AVR de 8 bits de Atmel, sin usar el IDE de Arduino, podemos programarlos usando C y C++ mediante una versión muy extendida de GCC (http://es.wikipedia.org/wiki/GNU_Compiler_Collection) denominda AVR-GCC http://winavr.sourceforge.net/ y http://sourceforge.net/projects/winavr/files/.

Una vez compilado el programa de C/C++ en un binario para AVR con AVR-GCC, necesitaremos “quemarlo” en el microcontrolador. Esto puede hacerse con AVRDUDE http://www.nongnu.org/avrdude/ o UISP http://www.nongnu.org/uisp/ o Atmel Studio http://www.atmel.com/tools/atmelstudio.aspx

Para Linux son necesarias estas herramientas:

  • gcc-avr
  • binutils-avr
  • gdb-avr
  • avr-libc
  • avrdude

Más información: http://playground.arduino.cc/Main/AVR

Un ejemplo de uso de funciones AVR que no dispone el entorno de Arduino es cuando queremos hacer delays muy pequeños. La función delayMircoseconds() puede hacer el delay más pequeño con el lenguaje de Arduino que es de 2 microsegundos.

Para delays menores es necesario usar ensamblador y en concreto la función ‘nop’ (no operation. Cada llamada a ‘nop’ ejecuta un ciclo de reloj que para 16 MHz es un retraso de 62,5 ns.

__asm__(“nop\n\t”);
__asm__(“nop\n\t””nop\n\t””nop\n\t””nop\n\t”);  \\ gang them up like this

También como hemos visto anteriormente, manipular los puertos y pines con el código AVR es más rápido que usar digitalWrite(). Más información https://www.arduino.cc/en/Reference/PortManipulation

Otro ejemplo es el uso de los métodos AVR cbi y sbi que se usan para hacer set o clear de bits el PORT y otras variables. Puedes encontrar estos métodos de código AVR en muchos sitios y ambos deben ser definidos en el sketch de Arduino para ser usados. Pegar este código al inicio del sketch y para usarlo simplemente poner una variable del puerto y el pin para hacer set o clear.

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

Pero para programar el 99% de lo que necesitemos en proyectos sencillos con Arduino, todo esto se puede resumir en que para programar nuestro lenguaje de programación de Arduino es el “Arduino Reference”, que es donde debemos recurrir para cualquier duda de programación que surja. Puesto que Arduino provee de unas librerías que facilitan la programación del microcontrolador. http://arduino.cc/en/Reference/HomePage

A medida que nuestro programa se hace más complejo o necesitamos que sea más rápido o queremos que tenga un uso de memoria más eficiente, entonces es cuando tendremos que recurrir a los comando AVR de la avr-libc.

El gran éxito de Arduino en parte se debe a que el IDE nos permite programar una MCU sin tener que saber todo lo anterior y nos da unas herramientas sencillas y específicas para programar los microcontroladores que suministra en sus placas. Por ejemplo veamos las funciones que nos ofrece para comunicar por el puerto serie: http://arduino.cc/en/Reference/Serial

El IDE de Arduino está basado en Processing: https://processing.org/, es un lenguaje de programación y entorno de desarrollo integrado de código abierto basado en Java, de fácil utilización, y que sirve como medio para la enseñanza y producción de proyectos multimedia e interactivos de diseño digital.

La librería Arduino está basada en wiring: http://wiring.org.co/ y es de donde nacieron las funciones que conocemos como digitalRead(), Serial.println(), etc…

Web del proyecto de Proccesing: https://processing.org/

Processing en github: https://github.com/processing/processing

Web del proyecto Wiring: http://wiring.org.co/

Wiring en github: https://github.com/WiringProject

Processing es útil cuando queremos comunicar Arduino con un ordenador y mostrar datos o guardar datos, pero también podemos usar python, .NET o cualquier otro lenguaje de programación que conozcamos.

Arduino trae algunos ejemplos para trabajar con Processing en el apartado communication, por ejemplo para hacer una gráfica de datos en http://arduino.cc/en/Tutorial/Graph

Ver el reference y la librería Serial de processing: https://processing.org/reference/ y https://processing.org/reference/libraries/serial/

También disponemos de una librería de Arduino para processing que nos permite interactuar entre processing y arduino: http://playground.arduino.cc/interfacing/processing

Por supuesto Arduino se puede programar en otros lenguajes y desde otros entornos de programación. Cabe destacar scratch como un lenguaje visual que hace innecesario saber programación o Atmel Studio que es la herramienta que proporciona Atmel. Más información en: https://aprendiendoarduino.wordpress.com/2014/11/20/tema-4-conceptos-basicos-de-programacion/

Más información: http://wittyrobo.com/mcu328p/c01_p01.html

Fuses

Los fuses son una parte muy importante en la programación de un microcontrolador. Solo es necesario configurarlos una vez, pero si no se hace correctamente podemos tener problemas.

Ya sabemos lo que es la flash, EEPROM y RAM como parte de la MCU, pero no se ha mencionado anteriormente que hay 3 bytes de memoria permanente llamados fuses. Los fuses determinan cómo se va a comportar el microcontrolador, si tiene bootloader, a que velocidad y voltaje va a funcionar, etc… Notar que a pesar de llamarse fuses (fusibles) puede configurarse una y otra vez y no tienen nada que ver con la protección de sobrecorrientes.

Los fuses están documentados en los datasheets, para el Arduino UNO ver página 348 de http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf

Con los fuses seleccionamos el comportamiento de:

  • Clock Source: puede ser un reloj externo, un reloj interno o un cristal externo.
  • Clock Startup: es el tiempo que necesita la fuente de reloj para estabilizarse.
  • Clock Output: habilita una salida de reloj en el PORT C2
  • Clock Divide: Divide por 8 el reloj
  • Reset Disable: convierte el pin de reset en un pin normal, habilitar este fuse hace que no se pueda programar por ISP
  • Brown-out Detect (BOD): selecciona a que voltaje hace disparar la protección de brownout. Para una MCU brownout es el voltaje al que es demasiado bajo para que funcione de una forma fiable a la velocidad de reloj.
  • Selecciona si se usa bootloader o no.
  • Selecciona cuánta memoria se reserva para el bootloader
  • Deshabilitar programación por el puerto serie

Con los fuses podemos bloquear algunos aspectos importamte de la MCU y podríamos brickearlo.

Los 3 bytes de los fuses son:

  • low byte fuse
  • high byte fuse
  • extended fuse

También hay un cuarto byte que se usa para programar los lock bits. Los lock bits pueden ser usados para restringir la lectura/escritura en la memoria de programa (flash), la zona de boot y la de aplicación tienen sus propios lock bits y es posible controlar el acceso a ellos de forma separada.

Para los fuses el 1 significa no usado y 0 usado.

Low Byte Fuses

High Byte Fuses

Extended Fuse Bits

Los valores por defecto el ATmega328p son:

  • Low fuse = 0x62 (B01100010)
  • High fuse = 0xD9 (B11011001)
  • Extended fuse = 0xFF (B11111111)

Los valores de los fuses de Arduino con el ATmega328p son:

  • Low fuse = 0xFF (B11111111)
  • High fuse = 0xDA (B11011110)
  • Extended fuse = 0x05 (B00000101)

En caso de usar el Optiboot bootloader, cambia el valor en el high byte fuse porque el tamaño del bootloader es inferior.

Más información de cada fuse en: http://www.martyncurrey.com/arduino-atmega-328p-fuse-settings/

Pero la mejor forma de ver los fuses es examinar AVR fuse calculator: http://www.engbedded.com/fusecalc/

Luego con los datos de los 3 bytes de los fuses, se pasan como argumento en el avr-dude al cargar el sketch y configurar los fuses. La configuración de los fuses es parte del proceso de cargar un bootloader. Editando el fichero boards.txt en la carpeta del IDE de Arduino en la ruta C:\Program Files (x86)\Arduino\hardware\arduino\avr se puede configurar el valor de los fuses.

Discusion en foro sobre el uso de fuses para proteger el binario de un sketch:  http://www.todopic.com.ar/foros/index.php?topic=44794.0. Es tan simple como agregar “-Ulock :w:03c:h” al final del comando que se le envía a avrdude.exe. Se configuran los lock bits como 1100 0011 (ojo que cambian los bits más significativos y menos significativos)

fuses

Cargar un programa desde el ide de arduino al microcontrolador. Luego desde el programa que mencionado ejecutar el mismo comando enviado por el ide de arduino a avrdude, pero cambiando la ruta del archivo .hex por un programa distinto y agregando al final “-Ulock :w:03c:h” Avrdude muestra en pantalla el avance en el proceso, pero al tratar de verificar el archivo enviado con el que recibe del microcontrolador, la comprobación falla. El microcontrolador se reinicia y ejecuta el programa nuevo correctamente, lo que demuestra que el Arduino no entregará el programa y que avrdude no es capaz de extraerlo del microcontrolador, ni tampoco con esta configuración es posible cargar ningún programa.

Ver el estado de los fuses de un Arduino se puede hacer con avr-dude y un programador, para ello hay que ejecutar el comando “avrdude -c arduino -p m328p -P COM3 -b 19200 -v”

Con AVR studio se puede leer y escribir los valores de los fuses. Pero si queremos cambiar los valores de los fuses con el IDE de Arduino podemos hacerlo de dos formas:

  • Option 1. El “quemado del bootloader” configura los fuses. Para configurar los fuses el ATmega328p se puede hacer en el proceso de cargar bootloader y toma la configuración de los fuses que hay en el fichero boards.txt de la placa correspondiente.
  • Option 2. Configurar los fuses manualmente, sin cargar un bootloader. Para ello necesitaremos la herramienta avr-dude mediante el comando.
    avrdude -c stk500v2 -p m328p -P /dev/ttyACM0 -b 19200 -U lfuse:w:0xFF:m -U hfuse:w:0xDE:m -U efuse:w:0x05:m”

Más información en:

IDE Arduino

El IDE de Arduino es open source y por lo tanto tenemos su código fuente y también podemos hacer nuestra propia versión del IDE. El proyecto del IDE de Arduino en github es: https://github.com/arduino/Arduino y las instrucciones para construir el binario desde el fuente está en https://github.com/arduino/Arduino/wiki/Building-Arduino

El software de Arduino se puede descargar en https://www.arduino.cc/en/Main/Software

Para actualizar Arduino y mantener las configuraciones, en Windows simplemente ejecutar el instalador, este desinstala la versión anterior y mantiene las librerías y sketchs siempre y cuando no hayamos guardado o modificado algo en el directorio de instalación.

También es posible tener varias versiones del IDE instaladas, simplemente usar la instalación manual con el archivo .zip

Para añadir al IDE Arduino soporte de placas de terceros: https://learn.adafruit.com/add-boards-arduino-v164?view=all

Lista no oficial de placas de terceros soportadas por el IDE de Arduino:

https://github.com/arduino/Arduino/wiki/Unofficial-list-of-3rd-party-boards-support-urls#list-of-3rd-party-boards-support-urls, que son ficheros json para añadir en el IDE y dar soporte con el nuevo gestor de placas.

Ruta donde se instalan los cores: C:\Users\enrique\AppData\Local\Arduino15\packages

La explicación de cada parámetro en configuración IDE: https://code.google.com/archive/p/arduino/wikis/Platforms.wikien la ruta: C:\Program Files (x86)\Arduino\hardware\arduino\avr

  • boards.txt: The Arduino environment supports multiple target boards with different chips (currently, only AVRs), CPU speeds, or bootloaders. These are defined in boards.txt. A board is specified by multiple variables prefixed with the same keyword (shown here as BOARD). The file consists of multiple lines with the format key=value. Lines that start with a # are comments and ignored.
  • programmers.txt: Programmers may be specified in the programmers.txt file in a platform. This file has a format similar to the boards.txt file, but with the other variables.
  • The bootloaders sub-folder of a platform contains the bootloaders for the boards in the platform. These should appear as .hex files in a sub-folder of the bootloaders folder. Often, the source code for the bootloader is also included, along with a Makefile for building the .hex file.
  • A core is a set of .c, .cpp, and .h files that implement the basic Arduino functions for a platform. Each core appears as a sub-folder of thecores sub-folder of a platform.

Guia para cambiar estilo IDE Arduino:

AVR libc

Es posible usar comandos estándar de C++ en la programación de Arduino siempre que estén incluidos en el avr libc, así como otros comandos propios para las MCUs AVR tambiñen incluidos en en avr-libc:

Dispositivos soportados por avr-libc: http://www.atmel.com/webdoc/AVRLibcReferenceManual/index_1supp_devices.html

Cuando creamos un programa en Arduino, automáticamente carga varios módulos como stdlib.h, math.h, etc…

Por ejemplo math.h:

El equivalente para linux de avr-libc es la glibc:

glibc como se puede ver tiene versiones para diferentes arquitecturas de los ordenadores como i386, i686, etc… para usar las instrucciones de cada una de sus arquitecturas.

Más información sobre MCUs AVR:

WinAVR

WinAVR es una herramienta importante para el desarrollo de MCUs AVR, incluso después de instalar Atmel Studio como IDE, es recomendable instalar WinAVR.

WinAVR (pronunciado “whenever”) es una suite compuesta de herramientas de desarrollo opensource para los microcontroladores AVR sobre plataforma Windows. Incluye el compilador GNU GCC para C y C++.

Herramientas WinAVR:

  • avr-gcc (compiler)
  • avrdude (programmer)
  • avr-gdb (debugger)
  • avr-libc (with a good HTML help Documentation)
  • and more …..

Web del proyecto:

Más información:

Tutoriales de programación AVR:

Interesante información sobre avr-lib en Wiring y Arduino: https://ccrma.stanford.edu/~juanig/articles/wiriavrlib/wiriavrlib.html

Proceso de compilación

GCC es un conjunto de compiladores que se considera el estándar para los Sistemas Operativos derivados de UNIX y requiere de un conjunto de aplicaciones conocidas como binutils que son unas herramientas de programación para la manipulación de código de objeto.

GCC soporta varios lenguajes y diferentes arquitecturas de HW::

Como GCC está construido para ejecutarse en un sistema como Linux, Windows o mac OS, pero para generar código para un microcontrolador AVR, entonces se denomina avr-gcc que es una versión de GCC solo para arquitecturas AVR. avr-gcc es el compilador que usa el IDE de arduino para convertir el sketch en C++ a un fichero binario (.hex) que es el que se carga en la flash del MCU y que ejecuta.

avr-gcc se puede usar directamente o a través de un IDE como el de Arduino o el Atmel Studio.

En el caso de Arduino el proceso de construcción para que el código escrito llegue a la placa es el siguiente:

  • El IDE verifica el código y comprueba que la sintaxis del código es correcta en C y C++
  • Luego pasa al compilador avr-gcc, que convierte el código en C++ en instrucciones que entiende el microcontrolador.
  • Después el código es combinado con las librerías estándar de Arduino, que son las que ofrecen las funciones básicas como digitalWrite() o Serial.println().
  • El resultado es un fichero hex que contiene los bytes que van a ser grabado en la memoria flash de Arduino.
  • Finalmente el fichero es cargado en la placa Arduino transmitiendolo sobre el USB o la conexión serie si hay un bootloader cargado o sino con un hardware externo (programador).

Cuando un sketch contiene múltiples ficheros, es compilado y los ficheros con extensiones .c o .cpp se compilan de forma separada y los ficheros con otras extensiones se concatenan juntos al fichero del sketch principal antes de pasarlo al compilador. Para usar ficheros con extensión .h, es necesario incluirlos con #include usando “comillas dobles” y no <>

El entorno de Arduino, antes de compilar también hace algunas modificaciones como añadir al principio del sketch #include “Arduino.h”. También el entorno de Arduino busca las definiciones de las funciones en el sketch principal y crea las declaraciones (prototypes) para ellas, estas se insertan después de los comentarios y las directivas de preprocesamiento, pero antes del resto de código, esto significa que si se quiere usar un tipo de dato como argumento de una función, debe declararse dentro de un fichero de cabecera separado.

El entorno de Arduino soporta múltiples placas con diferentes MCUs (no solo AVR), todo los datos de la placa están definidos en el fichero boards.txt en C:\Program Files (x86)\Arduino\hardware\arduino\avr. A la hora de compilar las opciones se toman del fichero boards.txt en la opción de build.

Cuando se compila desde el IDE de Arduino cono avr-gcc, las rutas donde se busca cuando se hace un include son:

  • El directorio del core de la placa <ARDUINO>/hardware/core/<CORE>/
  • El directorio de avr include <ARDUINO>/hardware/tools/avr/avr/include/
  • Cualquiera de los directorios de librerías <ARDUINO>/hardware/libraries/ o C:\Users\<USER>\Documents\Arduino\libraries

Cuando un sketch se verifica, se genera el fichero compilador en un directorio temporal del SO. Todos los ficheros .c y .cpp son compilados y la salida es un fichero .o (object file), tanto el del sktech final como otros que haya en el directorio del sketch o los de las librerías incluidas. Los fichero .o son enlazados todos juntos en una librería estática y el fichero del sketch principal. Solo las partes de las librerías necesitadas para el sketch son incluidas en el fichero final .hex, reduciendo el tamaño de la mayoría de los sketches.

El fichero .hex es la salida final de la compilación y es cargado en la memoria flash de Arduino. Este .hex es cargado en Arduino mediante avrdude y este proceso es controlado por las variables de las placas en el fichero de boards.txt dentro de las opciones “upload”

Para que me guarde los hex en una carpeta concreta: http://forum.arduino.cc/index.php?topic=142706.0

Durante el proceso de compilación se genera un fichero intermedio con extensión .elf que contiene el código máquina y otra información relacionado con información de la memoria y debug. El fichero elf (Executable and Linking Format), es el formato estándar para ficheros ejecutables, objetos de código y librerías compartidas. Elf es como una dll y consiste en unos enlaces simbólicos y tablas que pueden cargarse en una zona de memoria. Los fichero elf tienen varias secciones como datos, textos, etc.. Este fichero se suele usar para debug con emuladores.

Durante el proceso de compilación y carga, el IDE de Arduino muestra mucha información (hay que activarlo antes, ver https://aprendiendoarduino.wordpress.com/2016/06/26/instalacion-software-y-configuracion/) que puede resultar de ayuda para saber lo que está pasando durante el proceso. La herramienta que convierte el fichero .elf a .hex es avr-objcopy.

Más información:

Cómo compilar un sketch de Arduino con makefile:

Opciones de compilación:

Esta imagen muestra todo el proceso:

Información sobre las binutils: http://www.atmel.com/webdoc/AVRLibcReferenceManual/overview_1overview_binutils.html

Arduino también nos ofrece la posibilidad de una herramienta de línea de comandos para compilar los sketches de Arduino llamada Arduino Builder: https://github.com/arduino/arduino-builder, siendo uan herramienta muy intersante para hacer integración continua https://github.com/arduino/arduino-builder/wiki/Doing-continuous-integration-with-arduino-builder o testeo de nuestro softwatre (TDD).

También hay interfaces gráficos para GCC:

Probar/Ejercicio: El compilador de avr-gcc cuando detecta lineas iguales de Serial.print() no aumenta la memoria del static data porque lo reconoce y la guarda una sola vez en RAM y la repite al llamarla. Tampoco aumenta el tamaño del hex.

Ensamblador

Ensamblador es un lenguaje de bajo nivel. Consiste en una lista de instrucciones que no son de ninguna manera comparable a cualquier otro lenguaje como C, Basic o Pascal. El AVR tiene alrededor de 130 instrucciones, dependiendo del tipo, periféricos y tamaño del microcontrolador. En este link está el manual de las instrucciones con su respectiva explicación, y en este otro link se encuentra la guia de usuario de AVR Assembler. Se puede encontrar más información en http://www.avrbeginners.net/ y en http://www.avrfreaks.net/

Como ya hemos visto Arduino podemos programarlo en C puro, pero también podríamos programarlo en ensamblador, aunque no es una opción recomendable. Sin embargo como veremos podremos obtener el código en ensamblador de nuestro sketch.

Sin embargo, podría ser útil en determinadas situaciones insertar código en ensamblador dentro de nuestro sketch de Arduino. El compilador GNU C para procesadores Atmel AVR RISC procesadores permite incrustar el código de lenguaje ensamblador en programas C. Esta característica se puede utilizar para optimizar manualmente las partes críticas de tiempo del software o utilizar una instrucción de procesador específico, que no están disponibles en el lenguaje C.

Las instrucciones de cada procesador se pueden ver en los datasheet correspondientes y para el caso de los AVR de 8 bit en:

AVR Assembler User Guide: http://www.atmel.com/Images/doc1022.pdf

Para insertar instrucciones de ensamblador en C ver: Inline assembler cookbook: http://www.nongnu.org/avr-libc/user-manual/inline_asm.html, simplemente poner en el código C la instrucción asm volatile(); pasando como parámetro el código entre comillas.

Más información:

Proceso de Carga del Sketch

Una vez compilado y obtenido el fichero binario, hay que cargarlo en la memoria flash de Arduino, para ello el IDE de Arduino usa una herramienta llamada avr-dude.

Cuando tenemos problemas al cargar un sketch de Arduino, el problema suele venir de avrdude y en este enlace habla de los problemas y sus soluciones http://elcajondeardu.blogspot.com.es/2016/03/avrdude-nos-lo-explica-rufian-rufian-en.html

Página del proyecto avr-dude:

Manual del AVRdude:

Hay versiones con GUI para avr-dude que nos permiten cargar el sketch con la opciones que queramos.

Usar avr-dude con atmel studio y Arduino: http://wittyrobo.com/mcu328p/c04_p01.html

Uso de Arduino uploader:

Tutorial para usar AVRdude:

Adicionalmente se disponen de otras herramientas para la MCUs de AVR:

Soporte a tarjetas no oficiales con IDE Arduino

Al igual que hemos visto las herramientas necesarias para programar los microcontroladores AVR de Atmel y que necesitamos de una librería avr-libc, un compilador avr-gcc y un programa para cargar el .hex al microcontrolador, lo que compone el soporte en el IDE de Arduino para estos microcontroladores, en caso de querer programar otras MCUs, necesitaremos instalar las correspondientes herramientas para estos microcontroladores.

El proceso de dar soporte a otras tarjetas/microcontroladores en el IDE de Arduino se ha facilitado mucho, disponiendo de unos ficheros json que se descarga el IDE de Arduino y con ellos el IDE se descarga las herramientas necesarias y configura el IDE de Arduino para esas MCUs.

Instalar soporte IDE a otras placas:

IMPORTANTE: especificaciones de formato a usar en el IDE de Arduino para soporte de nuevas placas: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification

Arduino ARM

Por ejemplo las herramienta usadas por Arduino para las placas basadas en microcontroladores ARM como el Arduino MKR1000, son las GNU ARM Embedded Toolchain https://launchpad.net/gcc-arm-embedded que es mantenido por los empleados de ARM. Usa gcc y newlib: https://sourceware.org/newlib/ y accesible el codigo fuente vía git en https://sourceware.org/git/gitweb.cgi?p=newlib-htdocs.git y git://sourceware.org/git/newlib-cygwin.git

Para programar la flash en los microcontroladores Atmel ARM de la familia SAM usar BOSSA: http://www.shumatech.com/web/products/bossa y su código fuente está en https://sourceforge.net/p/b-o-s-s-a/code/ref/master~/

También se usa otra herramienta llamada OpenOCD (Open On-Chip Debugger) http://openocd.org/ y ofrece soporte a la programación y debug, soportando muchos hardware debuggers.

Documentación: http://openocd.org/documentation/

Código fuente: https://sourceforge.net/p/openocd/code/ci/master/tree/

Bootloader

Cuando cargamos un programa en Arduino desde el USB con el IDE, estamos haciendo uso del bootloader, se trata de un pequeño programa que ha sido guardado previamente en el microcontrolador de la placa y que nos permite cargar código sin necesidad de hardware adicional. El bootloader solo está activo unos segundos cuando se resetea el Arduino y después comienza el sketch que está cargado en la flash de Arduino y que hemos programado y subido a la placa.

El bootloader se ejecuta cuando el microcontrolador se enciende o se pulsa el botón reset, durante un corto espacio de tiempo espera que le llegue por el puerto serie un nuevo sketch desde el IDE de Arduino (este distingue un sketch de otra cosa porque tiene un formato definido). Si llega un sketch, este es guardado en la memoria flash y ejecutado, en caso contrario ejecuta el sketch anteriormente cargado.

La mayoría de los Arduinos tienen la función autoreset que permite al IDE de Arduino subir el código sin tener que pulsar el botón de reset.

El bootloader hace que parpadee el pin 13 (led integrado en la placa) cuando se ejecuta.

La mayoría de los microcontroladores de AVR pueden reservar una zona de la memoria flash (entre 256B a 4 KB) para el bootloader. El programa bootloader reprograma el microcontrolador para guardar en la memoria flash el código binario a través de cualquier interface disponible.

El bootloader de Arduino está programado en la memoria flash del ATMega328p y ocupa 0,5 KB de los 32KB disponibles. Este bootloader viene precargado en la memoria flash del microcontrolador y es lo que diferencia el ATMega328p de Arduino de otro que viene de fábrica.

El Arduino UNO viene con el microcontrolador ATMega328p precargado con un bootloader que permite cargar nuevo código sin un programador. El bootloader se comunica usando el protocolo STK500.

El protocolo STK500 http://www.atmel.com/Images/doc2525.pdf es propio de Atmel. Es un protocolo serie y los programadores emulan este protocolo sobre un puerto serie virtual en un USB. Originalmente STK500 fue un programador fabricado por Atmel y a raíz de ello liberaron el protocolo STK500.

En este enlace es posible obtener el código en C del protocolo STK500: http://www.atmel.com/dyn/resources/prod_documents/avr061.zip

Arduino decidió usar avrdude y STK500 serial bootloader para programar o cargar nuevos programas en Arduino sin necesidad de HW adicional. El bootloader de Arduino es esencialmente el bootloader STK500 de Atmel.

Las MCUs AVR de 8bits ATMega con interfaz USB integrado como son el ATmega16U2 y ATmega8U2, vienen de fábrica un USB bootloader en la sección de arranque de la flash. Este bootloader USB permite hacer In-System programming desde USB host controller sin la necesidad de un HW externo. En este documento se describe las funcionalidades del USB bootloader: http://www.atmel.com/Images/doc7618.pdf

El puerto serie durante el proceso de bootloader funciona a 19200 baudios.

El bootloader estándar de Arduino usa el protocolo STK500 versión 2 y por ese motivo es el valor que usamos en el IDE de Arduino.

Los comandos para “quemar” el bootloader en Arduino usan una herramienta open nsource llamada avrdude, de la que se hablará más tarde. Hay cuatro pasos a la hora de cargar el bootloader:

  • Desbloquear la sección de bootloader en el chip
  • Configurar los fuses en la MCU
  • Cargar el código del bootloader en el microcontrolador
  • Bloquear la sección del bootloader en la MCU

Todo esto es controlado por una serie de preferencia en el fichero de preferencias de Arduino: https://www.arduino.cc/en/Hacking/Preferences

Cuando el Boot Reset Fuse (BOOTRST) está configurado, el contador de programa en la memoria flash es inicializado a una dirección de memoria de un bloque en el extremo superior de la memoria (esto depende de como se hayan configurado los fuses, ver https://www.arduino.cc/en/uploads/Main/Arduino_Uno_Rev3-schematic.pdf para más información). El código que comienza no puede hacer nada, si realmente se quiere se podría poner su propio programa de allí si se utiliza un ICSP (los bootloaders por lo general no puede sobrescribirse a sí mismos).

Funciones de la AVR-lib para bootloader: http://www.nongnu.org/avr-libc/user-manual/group__avr__boot.html

El bootloader se trata de un programa especial y puede leer datos de una fuente externa como UART, I2C, CAN, etc… para reescribir el programa guardado en la memoria flash del microcontrolador. El bootloader busca un evento especial que puede ser cualquier cosa, pero para el desarrollo es más conveniente algo en el bus de datos que será puesto en la flash de la MCU. Si el bootloader ve ese evento especial, entonces entra en modo bootloading en el que hace un reflash de la memoria de programa del microcontrolador, pero si no aparece el evento, pasa el control al código del usuario.

El bootloader no consume RAM y los únicos efectos que tiene son modificaciones en los registros del hardware periferivo, pero un buen bootloader no debe dejar ningún estado perjudicial en el que encienda periféricos que malgasten energía cuando pones la MCU en modo sleep. Es una buena práctica inicializar los periféricos que se usan, así aunque el bootloader haga algo extraño, habremos inicializado como queremos que se comporte.

Avrdude es un programa para descargar y cargar a la memoria de las MCUs AVR de Atmel. Puede programar la Flash y la EEPROM y es soportado por el puerto serie.

Avrdude funciona mediante la línea de comandos y soporta los siguientes tipos de programadores:

  • Atmel’s STK500
  • Atmel’s AVRISP and AVRISP mkII devices
  • Atmel’s STK600
  • Atmel’s JTAG ICE (both mkI and mkII, the latter also in ISP mode)
  • appnote avr910
  • appnote avr109 (including the AVR Butterfly)
  • serial bit-bang adapters
  • PPI (parallel port interface)

Avrdude junto con otras herramientas se encuentran en: C:\Program Files (x86)\Arduino\hardware\tools\avr

Para cargar un sketch con avrdude en Arduino en lugar de usar el IDE, simplemente conectar el cable USB y presionar el botón de reset antes de ejecutar avrdude. Luego ejecutar con estas opciones:

  • Use -b 19200 to set the baud rate to 19200
  • The device signature reads dont seem to work so you’ll want to use -F
  • The programmer type is avrisp
  • The device type is -p m168
  • The port is whatever the FTDI chip shows up as

Un tutorial de avrdude se encuentra en http://ladyada.net/learn/avr/index.html

Más información:

Reparar el bootloader de un ATTiny: https://learn.adafruit.com/introducing-trinket/repairing-bootloader

Auto Reset

Para cargar un nuevo sketch en un microcontrolador, es necesario hacer un reset para pausar la ejecución de su programa y poder cargar el nuevo.

En el caso de los Arduinos, tienen la funcionalidad de auto-reset que está diseñado de forma que permite ser reseteado vía software conectado a un ordenador como el IDE de arduino. Una de las líneas de hardware flow control (DTR) del ATmega8U2/16U2 está conectada a la línea de reset de ATmega328 a través de un condensador de 100 nF.

El SW de Arduino usa esta capacidad para cargar el código simplemente pulsando el botón de carga en el IDE. De esta forma se sincroniza perfectamente el envío del nuevo sketch junto con el reset del microcontrolador.

Al resetear lo primero que arranca es el bootloader y puede comenzar la carga del sketch. El bootloader espera unos segundos para ver si un nuevo sketch se está cargando y en ese caso borra lo que hay en la flash y luego empieza a cargar el programa que está en la flash.

Arduino Uno dispone de un jumper soldado que se puede cortar para deshabilitar el auto-reset y luego estos se pueden soldar de nuevo para habilitarlo.

Más información en:

Bootloaders

Además del bootloader que disponemos desde el IDE de Arduino y el que viene precargado en los microcontroladores de Arduino, existen otros bootloaders con mejoras en algunos aspectos o para ofrecer nuevas características.

Codigo fuente del bootloader de Arduino: https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr/bootloaders

Optiboot es un bootloader muy conocido que está más optimizado que el bootloader oficial de Arduino, permitiendo sketches mayores, carga más rápida.

Toda la información del optiboot:

HoodLoader2 te la opción de reprogramar el ATmega16u2 de un Arduino normal con sketcehs: https://github.com/NicoHood/HoodLoader2, se  trata de un proyecto muy intersante.

Como funciona el optiboot: https://code.google.com/archive/p/optiboot/wikis/HowOptibootWorks.wiki

Adaboot es otro bootloader optimizado cuyas mejoras ya las incluye optiboot. Más información: https://learn.adafruit.com/arduino-tips-tricks-and-techniques/bootloader

Optiloader es un sketch diseñado para automatizar las actualización de los bootloaders de Arduino usando otro Arduino como programador. Almacena múltiples copias de optiboot en la flash y cuando se inicia consulta al Arduino a cargar el bootloader y averigua la CPU que tiene e inicia la carga del bootloader ya programación adecuada de los fuses.

Interesante un TFTP bootloader: http://playground.arduino.cc/Code/TFTP_Bootloader_1

Más información: https://github.com/WestfW/OptiLoader

Cargar el Bootloader en Arduino

Antes de cargar el bootloader, debemos asegurarnos la placa seleccionada en el IDE para que al realizar el “quemado” del bootloader se configure el bootloader adecuado para cada placa y los comandos de carga del bootloader.

  • Arduino Uno y mini posee auto reset usando el optiboot bootloader
  • Arduino mega  posee auto reset y usa el stk500v2 bootloader

Para cargar o “quemar” el bootloader, necesitaremos un programador externo (in-system programmer). como USBtinyISP (https://learn.adafruit.com/usbtinyisp), un programador parallelo (http://arduino.cc/en/Hacking/ParallelProgrammer) u otro arduino con un programa adecuado cargado.

El programador se conecta a ICSP y debemos asegurarnos que lo conectamos correctamente y asegurarnos que hemos seleccionado la placa correcta, luego lanzar el comando herramientas > grabar secuencia de inicio desde el IDE de arduino. Este proceso tarda 15 o más segundos.

Más información:

En el fichero de preferencias están todos los datos para la carga del bootloader un función del modelo de bootloader: http://arduino.cc/en/Hacking/Preferences

Ver los ficheros boards.txt y programmers.txt en C:\Program Files (x86)\Arduino\hardware\arduino y ver es esa misma ruta los bootloader.

Más información en: https://code.google.com/p/arduino/wiki/Platforms

Para el Arduino mini hay diferencias a la hora de cargar el bootloader: http://arduino.cc/en/Hacking/MiniBootloader

Cargar sketches con un programador externo

Con un programador externo, además de cargar el bootloader a un microcontrolador, también podemos cargar los sketchs en la MCU sin necesidad del bootloader.

Esto nos permite usar el espacio completo de la memoria flash del microcontrolador, además de ahorrarnos el retraso que hay en el arranque cuando tenemos el bootloader.

Esto nos permite usar un arduino sin un bootloader y también es posible cargar el hex ya compilado en arduino con herramientas gráficas como XLoader: http://xloader.russemotto.com/ o con avrdude directamente como hemos visto anteriormente. La compilación puede ser con el IDE de Arduino o con cualquier otro compilador basado en avr-GCC

Para usar el programador externo debemos modificar ligeramente el fichero de preferencias del IDE de Arduino y debemos hacerlo con el IDE cerrado. Para encontrar el fichero de preferencias: http://arduino.cc/en/Hacking/Preferences

Debemos cambiar la línea  upload.using=bootloader por el identificador de uno de los programadores que tenemos en el fichero programmers.txt. Por ejemplo avrispmkii.

Después de hechos estos cambios, puedes cargar los sketches a la placa con el botón normal de upload, pero no es necesario pulsar el botón de reset, puesto que Arduino ya tiene la configuración de auto-reset.

Para volver a programar usando el bootloader, debemos volver a la configuración upload.using=bootloader en el fichero de preferencias y por supuesto el bootloader de nuevo en la placa.

Más información: http://arduino.cc/en/Hacking/Programmer

Ejemplos de programadores:

También es posible programar un ATtiny con una Raspberry Pi por SPI: http://www.instructables.com/id/Programming-the-ATtiny85-from-Raspberry-Pi/?ALLSTEPS

Ejercicios Bootloader

Ejercicio36-ArduinoISP: Usar un Arduino para hacer In-Sytem Programming a otro Arduino.

Usar un Arduino como pasarela para programar otro directamente sin bootloader.

ATENCIÓN –  esto eliminará el bootloader de Arduino

Tutoriales:

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio36-ArduinoISP

Alimentación Arduino

Una de la partes más importantes a la hora de afrontar un proyecto con Arduino o cualquier microcontrolador es como vamos a alimentarlo y en caso que haya que usar baterías que autonomía va a tener. Pero no solo es alimentar Arduino, sino que hay que tener en cuenta que además es posible que estemos alimentando a través del microcontrolador los sensores y actuadores y si no tenemos en cuenta las limitaciones eléctricas del microcontrolador, podemos encontrarnos que no funcione el proyecto.

Cuanto consume Arduino: http://www.prometec.net/consumos-arduino/

Métodos de Alimentar Arduino

USB

Cuando se trabaja con Arduino normalmente lo alimentas a través del cable USB que va al ordenador. Sin embargo, una vez programado, o bien se deja conectado al ordenador o bien se busca otra forma alimentar Arduino. Alimentar Arduino por USB tiene la desventaja de que solo es capaz de suministrar hasta 500 mA.

Adaptador de Corriente

El método más habitual de alimentar Arduino es mediante un adaptador de corriente (AC DC). Este alimentador debe de dar un voltaje adecuado al arduino que conectemos y la potencia suficiente. Un voltaje adecuado para el Arduino UNO es un alimentador de 7 o 7,5V puesto que por debajo de ese voltaje es posible que la salida 5V de Arduino esté por debajo y por encima el regulador de tensión se calentará innecesariamente. A partir de 12V es desaconsejable Alimentar Arduino porque el regulador de tensión se calienta mucho y puede acabar dañándose. Esta opción es la mejor si el proyecto no necesita moverse y si hay una toma de corriente accesible cerca de Arduino.

Fuente de Alimentación Regulable

Para propósitos de testeo y desarrollo, podríamos usar una fuente de alimentación regulable y usarla para alimentar Arduino, pero en un entorno de laboratorio.  

Baterías

Otra opción para alimentar Arduino es mediante baterías de 9V, pero apenas tienen duración en un Arduino, puesto que el diseño de un Arduino no está pensado en un bajo consumo, por lo que salvo para una pequeña demostración no es una solución válida. Estas pilas tienen una capacidad entorno a 300 mAh y un proyecto sencillo con Arduino puede consumir 200 MAh, por lo que no llegará a una hora de autonomía.

Las típicas pilas AA proporcionan 1,5V. Se pueden poner varias pilas en serie hasta llegar al voltaje necesario (lo ideal es poner 5 o 6) y alimentar Arduino con ellas. La diferencia entre utilizar estas pilas y utilizar las de 9V es enorme. Una sola pila alcalina AA tiene entre 2700-2900 mAh (por los 300 mAh de una recargable de 9V), por lo que son una muy buena opción. La única pega que tiene esta opción es que como pilas que son se gastan, y tendrás que comprar pilas a menudo. Aun así una opción muy recomendable.

Las baterías LiPo (Polimero de Litio). Esta batería tiene mucha duración (tienen muchos mAh). Tienen una vida útil bastante larga, lo que hace que compense utilizar este recurso aunque sean más caras que las pilas AA. Sin lugar a dudas son la mejor opción para alimentar un coche a radiocontrol, dron o cualquier dispositivo móvil que se te ocurra.Existen baterías LiPo de distintos voltajes y capacidades. En el caso de alimentar Arduino, la mejor opción es utilizar una batería de 7,4V y, al menos, 1600 mAh.

Las baterías LiPo se componen de celdas y cada celda es de 3,7V, por lo tanto los voltajes que podemos encontrar de estas baterías son múltiplos de 3,7V.

Estas baterías son recargables y debemos cargarlas adecuadamente para alargar su vida, para ello disponemos de módulos cargadores de baterías LiPo.

Más información sobre baterías:

Otra forma de alimentar un Arduino es mediante una placa solar y un acumulador, pero este tema se tratará un poco después en este post.

Más información en:

Fuente conmutada

Otra forma de alimentar un Arduino es usar una fuente conmutada como las fuentes ATX de los ordenadores. Una fuente conmutada es un dispositivo electrónico que transforma energía eléctrica mediante transistores en conmutación. Mientras que un regulador de tensión utiliza transistores polarizados en su región activa de amplificación, las fuentes conmutadas utilizan los mismos conmutándolos activamente a altas frecuencias (20-100 kilociclos típicamente) entre corte (abiertos) y saturación (cerrados). La forma de onda cuadrada resultante es aplicada a transformadores con núcleo de ferrita para obtener uno o varios voltajes de salida de corriente alterna (CA) que luego son rectificados (con diodos rápidos) y filtrados (inductores y condensadores) para obtener los voltajes de salida de corriente continua (CC).

Las ventajas de este método incluyen menor tamaño y peso del núcleo, mayor eficiencia y por lo tanto menor calentamiento. Las desventajas comparándolas con fuentes lineales es que son más complejas y generan ruido eléctrico de alta frecuencia que debe ser cuidadosamente minimizado para no causar interferencias a equipos próximos a estas fuentes.

Además con esta fuentes tenemos suficiente potencia para alimentar a Arduino y los componentes que conectemos como LEDs, motores, etc…

Ejemplo de fuente de alimentación conmutada: http://electronicaraya.com/?q=catalogo/753

Se podría hacer una fuente conmutada controlada por Arduino: http://es.slideshare.net/pablogindel/fuente-conmutada-con-arduino

Cómo gobernar una fuente ATX con Arduino: http://www.prometec.net/fuentes-atx/

Fuente de alimentación reciclada para uso con Arduino: https://sites.google.com/site/arduinoreciclar/fuente-de-energia

Fuente de alimentación con Arduino: http://www.urpmigeek.com/2012/06/diy-fuente-de-alimentacion-con-arduino.html

Más información de fuentes conmutadas

Este tipo de circuitos reciben el nombre de fuentes conmutadas, convertidores Buck (Buck converters), o fuentes Step Down (De escalón de bajada) y son la base de las fuentes ATX.

La virtud de los buck converters o fuentes de Step Down es que proporcionan un buen rendimiento en la conversión de energía de una batería por ejemplo, sin desperdiciarla en forma de calor, frente a los reguladores de tensión lineales. Estas fuentes son ideales si estamos alimentando un equipo con baterías 12V, como por ejemplo en un coche, y deseamos alimentar nuestro Arduino para cualquier invento. Nos permiten bajar la tensión de 12V de la batería a los 5 V que necesitamos en nuestra entrada Vin con garantías de no desperdiciar energía de la batería en forma de calor, y por tanto extender sensiblemente su duración, al contrario de los reguladores lineales que veremos después.

En general el mercado nos provee de multitud de circuitos montados con fuentes conmutadas y aunque son algo más caras que los simples reguladores lineales, los precios han caído tanto que por unos pocos euros se consigue un Buck converter de calidad.

Ejemplo de fuentes step-down conmutadas:

Un ejemplo de un conversor DC/DC conmutado step-down es el TRACO  TSR 1-2450. Datasheet: https://cdn-shop.adafruit.com/datasheets/tsr1.pdf. Consigue hasta un 96% de eficiencia sin necesidad de disipador y es el sustituto eficiente de un regulador lineal (LDO) como el LM7805. Además estos conversores tienen una salida más exacta (±2 %), menor corriente en standby (2mA) y no requiere de condensadores externos al contrario que los reguladores lineales (LDO). Son ideales para aplicaciones alimentadas con baterías. El problema de estos conversores es que son más caros que los reguladores lineales.

Para alimentar un Arduino con un TSR 1-2450, habría que inyectar la corriente al pin de 5V pero no dispondríamos de protección alguna.

Si lo alimentamos a Arduino a través del pin Vin, estaríamos pasando por el regulador NCP1117 del Arduino y perderíamos toda la eficiencia. Además en este caso necesitaríamos más de 6V y entonces habría que usar el TSR 1-2490.

Más información sobre TRACO power: http://www.tracopower.com/home/

También hay otros DC-DC converters pero aislados  usando un transformador como el THD 12-2412WI: http://docs-europe.electrocomponents.com/webdocs/0aca/0900766b80acafd9.pdf

Application note muy interesante que compara y aconseja en caso usar entre los reguladore lineales y las fuentes conmutadas: http://cds.linear.com/docs/en/application-note/AN140fa.pdf

Video que compara buck converter frente a un linear regulator como el 7805: https://www.youtube.com/watch?v=giGRrODKJSE

Linear vs switching regulator en aplicaciones industriales de 24V: : http://www.ti.com/lit/an/slyt527/slyt527.pdf

Más información: http://www.intersil.com/en/products/power-management/linear-vs-switching-regulators.html

Se podría alimentar también un arduino con un regulador de tensión lineal, pero lo vamos a ver en el siguiente apartado y este ya viene integrado en Arduino.

Fuente con un regulador lineal:

Ejemplo de alimentar un Arduino (ATmega328p) con un regulador lineal: http://www.instructables.com/id/5V-voltage-regulator-with-7805/

Regulador de Tensión

Los microcontroladores que hemos visto funcionan todos a 5V o a 3.3 V, pero como hemos visto anteriormente y según vemos en las especificaciones de Arduino UNO debemos alimentarlo al menos a 7V. Por este motivo, todos los Arduino tienen un regulador de tensión, cuya función es convertir el voltaje de alimentación al voltaje de los elementos electrónicos, principalmente al microcontrolador. Esta conversión tiene un gasto energético que se convierte en calor en el regulador de tensión.

El regulador de tensión necesita un voltaje mínimo para para proporcionar 5V que está entorno 6.5-7V pero todo lo que esté por encima de ese valor se desperdicia y supone una ineficiencia energética.

Como se puede ver en este esquema, Arduino es alimentado mediante un regulador de tensión, en este caso es un NCP1117 http://www.onsemi.com/pub_link/Collateral/NCP1117-D.PDF que alimenta al bus de 5V de Arduino.

A su vez el bus de 5V alimenta otro regulador de tensión LP2985-33 http://www.ti.com/lit/ds/symlink/lp2985-50.pdf del que se obtiene una salida de 3.3V

Además hay disponible una entrada al bus de 5V para la alimentación directa del cable USB.

Ver el esquema completo en:

El límite máximo de alimentación de un Arduino es 20V y viene del límite de alimentación del regulador NCP1117.

Como se ha visto anteriormente los reguladores lineales de tensión son altamente ineficientes y el exceso de voltaje sobre la salida nominal se convierte en calor, por lo tanto a cuando mayor voltaje alimentemos Arduino más se calentará el regulador de tensión NCP1117.

Podemos ver cual es la tensión mínima de funcionamiento del Arduino a partir de los componentes implicados. Supongamos que pedimos a la placa una corriente de 200mA. Respecto al regulador, el dato más importante para el cálculo es la tensión de dropout, esto es, la caída entre entrada y salida cuando funciona. El dropout depende de la corriente y la temperatura. Para 200mA y 25ºC, tenemos algo menos de 1V.

Ventajas y desventajas de los reguladores lineales frente a los conversores conmutados: http://www.digikey.com/en/articles/techzone/2012/may/understanding-the-advantages-and-disadvantages-of-linear-regulators. La principal ventaja de los reguladores lineales es su menor tamaño, menor complejidad de uso, bajo coste y menor ruido y ripple (https://en.wikipedia.org/wiki/Ripple_(electrical))

Debido al uso de los reguladores de tensión y otras protecciones que tiene Arduino, hace que esta placa sea poco eficiente, haciendo que tenga un consumo elevado entorno a los 46mA en reposo para el Arduino UNO. Más información en http://www.prometec.net/consumos-arduino/

Los reguladores de tensión también se le denomina LDO (https://en.wikipedia.org/wiki/Low-dropout_regulator). Un LDO es un regulador de voltaje lineal de CC que puede regular la tensión de salida incluso cuando la tensión de alimentación está muy cerca de la tensión de salida. Las ventajas de un regulador de tensión sobre otros conversores DC-DC conmutados es la ausencia de ruido de conmutación (se lleva a cabo conmutación), el tamaño del dispositivo más pequeño y la simplicidad diseño (por lo general consiste en una referencia, un amplificador, y un elemento de paso). Una desventaja importante es que, a diferencia de reguladores de conmutación, los reguladores de corriente continua lineal debe disipar toda la energía a través del dispositivo de regulación con el fin de regular la tensión de salida.

Un LDO, por su propia naturaleza siempre disminuye el nivel de tensión entrada y no puede usarse para que la tensión de salida sea mayor que la de entrada.

Más información:

Reguladores lineales VS fuentes conmutadas

Para decidir cómo alimentar los proyectos debes tener en cuenta un par de ideas básicas.

Es importante saber que la eficiencia típica de un regulador lineal suele ser de un 40% y puede caer hasta un 15% con facilidad, por eso nunca deberían usarse en proyectos que funcionan a baterías, frente a un 85% típico de una fuente conmutada. Las fuentes conmutadas son recomendables siempre que usemos circuitos alimentados por baterías, pero imprescindibles cuando el consumo aumenta por encima de más o menos medio amperio, porque el calor generado, y su evacuación,  empezaran a dar problemas que irán complicándose cada vez más.

Una fuente conmutada DC que dé a su salida una tensión mayor que a la entrada, es una fuente del tipo Boost, Boost converter, o también una fuente Step-up y esto no es posible con una LDO.

Linear Regulator Switching Regulator
Control    
Design Flexibility Buck Buck, Boost, Buck-Boost
Efficiency Normally low to medium-high for low difference between VIN-VOUT High
Complexity Low Medium to high
Size Small to medium, larger at high power Smaller at similar higher power (depending on the switching frequency)
Total Cost Low Medium to high – external components
Ripple/Noise/EMI Low Medium to high
VIN Range Narrow (depending on power dissipation) Wide

Otro regulador de voltaje muy utilizado es el LM7805: https://www.sparkfun.com/datasheets/Components/LM7805.pdf:

También podríamos hacer una versión de Arduino en protoboard con el LM7805: http://www.prometec.net/arduino-en-protoboard/

NerO es un Arduino UNO pero diseñado desde el punto de vista de la eficiencia energética, https://www.kickstarter.com/projects/1218034479/nero-an-energy-efficient-arduino-uno-compatible-de. NerO dispone de un regulador conmutado en lugar de un LDO, al igual que usa el Arduino Leonardo ETH el MPM3610 http://www.monolithicpower.com/DesktopModules/DocumentManage/API/Document/getDocument?id=3301

Cómo Funciona la Alimentación de Arduino

Este es el esquema de alimentación de un Arduino desde el jack de alimentación.

Esta es la parte del circuito que regula una salida a 5V desde el jack de alimentación.

Abajo a la izquierda tenemos el conector de alimentación Vin. Esta entrada está también disponible al final de la tiras de pines que se halla abajo a la derecha en la figura si no se desea usar este voluminoso conector. A la derecha del conector tenemos los dos condensadores electrolíticos de 47uF y, debajo de éstos, el diodo D1 (M7). Encima del conector de alimentación tenemos el regulador de tensión NCP1117.

Para el diodo M7, el datasheet muestra la siguiente figura para la relación corriente-tensión, tenemos algo más de 0,9V a 0,2 A de de corriente. En total, juntando regulador y diodo tenemos una caída de 1,8V, por tanto, para una alimentación de 5V necesitamos un valor de Vin mínimo de 6,8V.

La placa Arduino no funcinará fiablemente con menos de 7V, pero, dado que internamente funciona a 5V, la eficiencia máxima de la alimentación será del 71% (=5V/7V). Si alimentamos la placa a 9V la eficiencia cae hasta el 55%.

Adicionalmente la placa lleva otra circuitería paralela para gestionar tanto las tensiones de 3.3V como el caso en el que simultáneamente la placa esté alimentada vía jack y vía USB.

Cuando se enchufa la placa solo al cable USB, el micro y todo lo demás es alimentado por los 5V que suministra el conector USB. Si se conecta una alimentación en el rango de 7-12V al jack, el micro y todo lo demás es alimentado por el circuito de regulación.

Pero cuando se conecta la placa tanto vía USB como vía jack al mismo tiempo, la placa usa un transistor T1, para dar preferencia a la fuente de tensión regulada por el jack, anulando la suministrada vía USB. Este transistor es el que permite a la placa vigilar, en caso de que estando el Arduino alimentado de dos formas distintas,  qué sistema se ha desconectado, y cambiar de uno a otro sin que notemos ninguna interrupción. En este caso si la tensión Vin es inferior a 6,6V se alimenta mediante el USB y si es superior, mediante el circuito de regulación.

Además como podría pasar que la alimentación a través del jack tuviera la polaridad cambiada (recordemos que para alimentar correctamente la placa el jack debe tener la tensión positiva en el centro), el sistema actúa como si la placa no estuviera conectada, protegiendo así al Arduino.

Más información:

Esquemáticos de Arduino UNO:

Reguladores de Tensión de Arduino

Alimentación Otros Arduinos

Hemos visto cómo funciona la alimentación en el Arduino UNO y en otros similares como el MEGA, pero otros Arduinos se alimentan de forma diferente y cuando nos toque usarlos habrá que ver cómo funcionan. Veamos unos ejemplos.

Para el caso del Arduino Yun al no disponer de un sistema de regulación de tensión, sólo puede alimentarse mediante un cable micro-USB o mediante el pin Vin donde debemos aplicar exactamente 5V. Arduino Yun no puede alimentarse por el pin de 5V porque en el esquemático https://www.arduino.cc/en/uploads/Main/arduino-Yun-schematic.pdf se ve como hay un diodo que solo permite a la corriente salir.

El Arduino Yun usa el RT8010: http://www.richtek.com/assets/product_file/RT8010=RT8010A/DS8010A-10.pdf

Más información: http://www.open-electronics.org/the-power-of-arduino-this-unknown/

Arduino mejorado con selector de voltaje y un regulador más potente entre otras modificaciones: http://playground.arduino.cc/Main/Luigino328

Más información para alimentar Arduino a 5V:

Las placas Arduino Diecimila y Duemilanove usan el MC33269 como regulador de tensión para conseguir los 5V necesarios para su funcionamiento. Este regulador tiene un “DropOut” de 1V, esto es, que para conseguir los 5V necesita estar alimentado con 6V, como mínimo.

Datasheet MC33269 http://www.onsemi.com/pub_link/Collateral/MC33269-D.PDF

Arduino Leonardo ETH http://download.arduino.org/products/LEONARDOETH/Arduino_Leonardo_Eth_V1_sch.pdf usa un MPM3610 que es un Synchronous Step-Down Converter conmutado

Datasheet MPM3610: http://www.monolithicpower.com/DesktopModules/DocumentManage/API/Document/getDocument?id=3301

Ejemplo: Problema de alimentación con Arduino motor shield

Veamos un ejemplo real de problema en un proyecto por culpa de no tener claro como se alimenta Arduino y los shields. Se trata de un Arduino UNO con un motor shield para mover un coche con dos motores DC de 12V.

El problema radica que al alimentar todo el bloque desde las baterías de 12V de usadas por lo motores, Arduino se queda colgado porque al arrancar los motores baja la tensión que llega al ATmega328p por debajo de 5V y deja de funcionar. Sin embargo en las pruebas con el Arduino conectado al USB para programar y hacer debug esto no pasaba.

Esquema Motor Shield: https://www.arduino.cc/en/uploads/Main/arduino_MotorShield_Rev3-schematic.pdf

Esquema del Arduino UNO: https://www.arduino.cc/en/uploads/Main/arduino-uno-schematic.pdf

Al alimentar a 12V desde LSP5 (Borna marcada con Vin) en el motor shield, es el VMOT el que alimenta Vin del Arduino y al L298P (driver de motores). Lo que ocurre es que VMOT cae por debajo de los 6,5V necesarios para alimentar al Arduino e incluso es incapaz de alimentar al VSS (5V para la logica) L298P que lo recoge del regulador de tensión del Arduino a traves del bus de 5V como se ve en el esquema.

La causa de esa caída de tensión puede ser de los motores conectados al L298P están demandando mucho.

La solución es alimentar por separado los motores y el Arduino, que es precisamente lo que pasa cuando Arduino estaba conectado al USB, para ello hay que cortar el jumper en placa denominado Vin-Connect.

Cuando Arduino está alimentado por USB esto no pasa porque en ese caso te saltas la alimentación del regulador de tensión que tiene el Arduino. Es lo que se ve en el esquema de Arduino UNO como USBVCC y al ser Vin menor que 6.6V el mosfet FDN340P deja alimentar desde el USB en lugar de Vin.

Cómo decide la alimentación Arduino entre el USB o el Vin/adaptador

Eso sí, debemos tener en cuenta que al alimentar Arduino por el USB la corriente máxima será de 500 mA.

Mosfet:

Más información: http://arduino.stackexchange.com/questions/893/arduino-what-happens-if-i-power-the-arduino-with-both-the-usb-and-external-pow

Como arduino selecciona automáticamente entre USB y Vin:

Entradas de Alimentación de Arduino

Una vez visto cómo funciona la alimentación de Arduino, ya podemos entender las diferentes formas desde las que podemos alimentar la placa y los riesgos que tiene cada una de ellas.

Lugares desde donde se puede alimentar Arduino:

Arduino tiene 4 posibles entradas de alimentación:

  • Puerto USB: llega al bus de 5V, procedente del puerto USB de un ordenador o de cualquier fuente de alimentación que se proporciona con un puerto USB como una batería. Si la alimentación proviene de un ordenador, hay una limitación de corriente de 500 mA, si por el contrario está utilizando una fuente de alimentación externa, la corriente máxima de salida (independientemente de la garantizada por la misma fuente de alimentación, que en general es de un máximo de 1 A o 2 A) está limitada a 500 mA por el fusible de protección auto-restaurable.
  • JACK: una fuente de alimentación, por lo general, se debe conectar a esta toma, con el polo positivo en la parte central de la toma, y el valor debe que oscilar entre 6V y 20V, el recomendado es 7-12V, por lo que no es aconsejable utilizar tensiones inferiores a 7V o superiores a 12V.
  • Pin Vin: este conector tiene una doble función.
    • Entrada para alimentación externa, no está protegida por el diodo ante inversiones de polaridad. La conexión va directamente a la entrada del regulador. Por supuesto no se debe aplicar tensión al jack, de lo contrario podrían surgir conflictos peligrosos
    • Salida de la que extraer el voltaje aplicado a la toma de JACK, pero sin la caída del diodo de protección. Podría resultar útil para alimentar cargas pequeñas que requieran una tensión superior a 5 V e igual a la aplicada a la toma JACK (siempre teniendo en cuenta la caída de tensión del diodo).
      En ambos casos el polo negativo de voltaje se puede encontrar en los pines de GND. Algunos shields usan este pin para alimentarse.
  • Pin 5V: está conectado directamente a la salida del regulador y al bus de 5V que se usa para alimentar cargas externas a Arduino como los sensores. En el caso de no aplicar tensiones al puerto USB o al jack, la toma de 5V se puede utilizar para alimentar Arduino directamente, si es que tiene una fuente externa estabilizada de 5V. Uno tiene que tener en cuenta que, en general, los reguladores no les gustan los voltajes que se aplica a su salida, pero en este caso particular, esta situación resulta a ocurrir incluso cuando la alimentación de Arduino se hace desde el puerto USB, por lo tanto, se puede suponer que no es un gran problema. En este caso no hay ninguna forma de protección, ya que tanto el diodo y el fusible se encuentran por encima de este bus y por lo tanto no tienen ninguna función activa. Al igual que en el caso de la toma de Vin, el polo negativo de la tensión se puede encontrar en los pines GND


NOTA: Arduino tiene un conector de salida de 3,3V para las cargas eléctricas que operan en esta tensión, mediante un segundo regulador que se conecta directamente a la V. 5 Este pin no se puede utilizar como entrada.

Como Destruir un Arduino

Ahora que ya conocemos bien cómo funciona la alimentación en Arduino, será fácil entender las malas prácticas que pueden dañar o destruir un Arduino.

Veamos 10 formas de destruir un Arduino:

  • Cortocircuitar un pin de entrada/salida con tierra. Configuramos uno de los pines como salida, lo establecemos en alto y este está directamente conectado a tierra, sin ningún componente que cree resistencia entre estos dos puntos (el pin de salida y el pin GND). El Pin de entrada/salida se sobrecarga y se destruye.
    Según las especificaciones de Arduino,este puede entregar un máximo de 40mA por cada pin, pero sin nada que haga de resistencia entre el pin y tierra este entregará unos 200mA, suficiente para destruir el microcontrolador.

  • Dos pines que se cortocircuitan mutuamente. Configuramos ambos pines como entradas, uno tiene un valor alto, el otro un valor bajo. Ambos son conectados uno con otro sin que exista ningún componente entre ellos. En este caso, ambos pines se sobrecargan mutuamente y son destruidos.
    Por un motivo similar al de la forma 1. El pin que esta en baja en este caso haría las veces de tierra, y entregarían tensiones muy por encima del máximo del microcontrolador, lo que lo destruye.

  • Sobretensión en los pines de entrada/salida. El voltaje máximo recomendado para cualquier pin de entrada/salida es de 5V (Salvo las versiones que operan a 3.3V), si aplicamos cualquier tensión por encima de 5.5V destruiremos nuestro Arduino.
    Los pines de Arduino cuentan con un diodo que protege el microcontrolador cuando se recibe una tensión superior a 5V, pero esta proyección esta pensada para descargas cortas, producidas por ejemplo por una descarga electrostática o un pequeño pico de tensión al arrancar, si esta sobre tensión dura, más que eso el diodo se quema, deja de proteger el pin del microcontrolador y este se quema.

  • Invertir la polaridad al alimentar Arduino por su patilla Vin. Cuando queremos alimentar nuestro Arduino mediante su patilla Vin y por error conectamos Vin a tierra y GND a 5V.
    Arduino no cuenta con protección en caso de invertir su polaridad de alimentación, por lo que la corriente avanzará “en dirección contraria” por todo el circuito de Arduino, destruyendo el regulador de voltaje y probablemente el microcontrolador.

  • Aplicar más de 5V al bus de 5V Al aplicar 6V o más al pin de 5V de Arduino se queman muchos de los componentes de esta placa, incluso podría llegar la corriente al puerto USB del ordenador si este está conectado.
    No hay ningún tipo de protección ni regulador de voltaje en la pata 5V de Arduino, por lo que la electricidad correrá libremente por todos los componentes destruyéndolos a su paso.

  • Aplicar más de 3.3V en el pin de 3.3V de Arduino. Si aplicamos más de 3.6V en la patilla de 3.3V podría dañar varios componentes de Arduino y probablemente también cualquier Shield que este conectado en ese momento.  Si llegasen a entrar más de 9V se detruiria también el regulador de 3.3V y la tensión podría causar daños en el puerto USB del ordenador si estuviese conectado en ese momento.
    El pin de 3.3V no tiene circuitos de protección. La corriente entraría directamente al regulador de 3.3V y a cualquier componente conectado a esta tensión (Shield, módulos de bluetooth..etc). Si la tensión fuese de 9V o más el regulador sería destruido y la corriente llegaría también a los componentes alimentados normalmente por 5V.

  • Cortocircuitar Vin y GND. Si conectamos la alimentación a Vin y este está cortocircuitado con GND.
    Si esto ocurre, el diodo de protección de Arduino sería destruido, la tensión aumentaría de forma brusca y el calor disipado sería suficiente para dañar las pistas.

  • Utilizar Vin como salida de corriente. Al alimentar la placa mediante la patilla 5V y utilizar Vin para alimentar componentes.
    l regulador no tiene protección para evitar que la corriente circule a la inversa. Al realizar esta conexión estamos haciendo que la corriente circule hacia atrás, lo que destruirá el regulador.

  • Aplicar más de 13V en el reset. Si aplicamos más de 13 en la patilla de reset de Arduino dañaremos el microcontrolador.
    13V es el máximo que soporta la patilla de reset de microcontrolador de Arduino. Un voltaje superior daña el chip.

  • Superar la tensión total que pueden entregar la salidas. Si el consumo de los pines es superior a 20mA ( o la suma total de sus consumos supera los 200mA) se supera la carga máxima que es capaz de resistir el microcontrolador y este sufre daños.
    Se supera la tensión máxima que puede atravesar el microcontrolador y al no poder entregar más se daña.

Más información:

Clones de Arduino mejorados para ser más resistentes:

Videos de como destruir un Arduino:

Limitaciones de Alimentación del Microcontrolador

Hemos visto cómo alimentar arduino y es la alimentación de todos los componente que la placa, incluido el microcontrolador. A la hora de hacer un proyecto, debemos tener en cuenta cómo se alimentan los elementos externos a la placa como sensores o actuadores y las limitaciones de corriente de la propia placa de Arduino y del microcontrolador.

Cuando alimentamos varios sensores o servos al bus de 5V, debemos tener en cuenta la limitación del regulador de tensión NCP1117 de 1A para saber el máximo número de sensores en función de su consumo. En el caso de un relé si lo alimentamos directamente del pin de Arduino, hay que tener en cuenta la limitación del pin.

Para el microcontrolador ATmega328p los valores máximos absolutos son:

  • DC Current per I/O Pin → 40.0 mA
  • DC Current VCC and GND Pins → 200.0 mA

VCC current es la corriente que se puede dar (source) del pin Vcc del microcontrolador

GND current es la corriente que se puede obtener (sink) del pin GND del microcontrolador.

Aunque cada puerto I/O puede dar más corriente que en las condiciones normales (20 mA en VCC = 5 V, 10 mA en VCC = 3V) bajo condiciones de estado estable (no transitoria), hay que tener en cuenta lo siguiente.

  • La suma de toda la corriente en HIGH (source) para los puertos C0 – C5, D0 – D4, ADC7, RESET no debe exceder los 150 mA
  • La suma de toda la corriente en HIGH (source) para los puertos B0 – B5, D5 – D7, ADC6, XTAL1, XTAL2 no debe exceder los 150 mA.
  • Si la corriente en HIGH superar los valores nominales, el voltaje en HIGH puede superar los valores nominales. No se garantiza que los pines puedan dar (suorce) más corriente que la de los valores de test.
  • La suma de toda la corriente en LOW (sink) para los puertos C0 – C5, ADC7, ADC6 no debe exceder los 100 mA
  • La suma de toda la corriente en LOW (sink) para los puertos B0 – B5, D5 – D7, XTAL1, XTAL2 no debe exceder los 100 mA
  • La suma de toda la corriente en LOW (sink) para los puertos  D0 – D4, RESET no debe exceder los 100 mA
  • Si la corriente en LOW supera los valores de test, el voltaje de LOW puede exceder los valores nominales. No se garantiza que los pines puedan obtener (sink) más corriente que la de los valores de test.

Más información:

Limitaciones de potecia, corriente y voltaje: http://www.electricrcaircraftguy.com/2014/02/arduino-power-current-and-voltage.html

Alimentar Arduino con Baterías

La capacidad de las baterías se mide en mAh o Ah. Un miliamperio hora es el término que se utiliza para determinar la duración de una batería. Si una batería o pila tienen 1000 mAh, podrás alimentar algo que consuma 1000 mA durante una hora (o 100 mA durante 10 horas). En realidad esto solo se cumple en la teoría. En la práctica, cuanto más rápido se descargue la batería, más potencia se estará disipando en la resistencia interna que tiene. Eso quiere decir que si realmente durase 10 horas alimentando un dispositivo que consume 100 mA, probablemente no duraría una hora alimentando algo con un consumo de 1000 mA.

¿Cuanto consume Arduino? Un pequeño circuito con una placa de Arduino y un Display ya suponen un consumo por encima de los 200 mAh, mientras que una pila recargable de 9V tiene entorno a los 300 mAh apenas podremos alimentar Arduino durante poco más de una hora. Alimentar Arduino con una pila de 9V es una mala opción.

Actualmente las baterías más usadas para alimentar Arduino son las LiPo, son las que se utilizan en radiocontrol y similares. Pero también pueden usarse otras como las AA, batería de coche, o las USB para los teléfonos.

Además de la capacidad, estas baterías LiPo vienen con lo que llaman la tasa de descarga, es decir lo rápido que se puede descargar la batería. Esto se muestra con la letra C. De manera que si tienes 10C y 5000mAh puede dar 50000 mA en una hora. Claro que no va a llegar pero de pueden utilizar 50A durante el tiempo que te dure la batería, que vendría a ser la décima parte de 1 hora. 60 minutos entre 10 son 6 minutos. A mayor C más cara va a resultar la batería, tal vez solamente necesites 2A para algún momento puntual así que seguramente sea necesario tanta tasa de descarga.

El único problema a estas LiPo es la carga, hay que ser cuidadosos porque tienen sus propios cargadores, si te pasas de carga se queman. No debe de pasar nada pero si no se pone el voltaje correcto en el cargador puede que se queme.

Cargador de batería LiPo: https://www.adafruit.com/products/1904

Más información sobre baterías LiPo: http://www.educachip.com/cargar-baterias-lipo/

A la hora de alimentar un Arduino con batería además de conocer los diferentes tipos de baterías, debemos conocer las técnicas a nivel de programación y electrónica para que Arduino consuma menor y pueda tener una larga vida con batería.

Para conseguir más autonomía en un Arduino alimentado con batería:

  • Apagando el circuito. Seguramente no necesites que tu circuito esté todo el tiempo encendido. Si estás tomando datos de temperatura seguramente con tomar uno a la hora o a las dos horas te bastará. Si se trata de una alarma casera necesitarás encender el sistema una vez cada minuto o cada dos minutos para saber si hay alguien. Esto en Arduino se llama modo Sleep y lo que hace es hibernar y se queda en estado de baja energía hasta que lo enciendes. Este modo se verá más adelante.
  • Utilizando placas solares. Las hay para Arduino y las hay pequeñas que puedes añadir a tu proyecto. La electrónica consume poco así que esto puede ser una carga para tu batería y un extra para utilizar menos energía.
  • Elegir una placa que consuma poco. El Arduino UNO consume más que el Nano. Es normal, el UNO por ejemplo como acepta entre 7V y 12V, perdiendo energía en forma de calor. Y luego al ser más grande necesita más carga para alimentar a todos los elementos. Luego el Nano es tan poca cosa que consume muy poco, unos 15mA frente a los 46mA del UNO. Aún así, una placa que funcione a 3.3V aún consumirá menos. Hay varias así, de hecho ahora todas van en esa dirección ya que el consumo es algo que cada vez importa más.
  • Crear un código muy pulido. Ser fino programando tiene su recompensa ya que a más líneas más consumo tenemos. Esto pasa también con el tiempo. A más líneas más tiempo se pierde y eso puede suponer más consumo. En este enlace https://foro.hacklabalmeria.net/t/arduino-bajo-consumo/4230  e dedicaron a medir los mA utilizados en los sketches de Arduino y encontró una librería llamada JeeLib que lo que hace es reducir la corriente utilizada. Eso implica aumentar el número de horas de la batería.

Más información:

En realidad los Arduinos oficiales, son poco eficientes, pero disponemos de otros clones de Arduino fabricados para tener bajo consumo como los moteino: https://lowpowerlab.com/guide/moteino/ que además incluyen comunicación inalambrca y está basado en el ATMega328p.

También es posible modificar un Arduino Mini para alimentarlo con batería durante más de un año, combinado con la librería low power: http://www.home-automation-community.com/arduino-low-power-how-to-run-atmega328p-for-a-year-on-coin-cell-battery/

Más enlaces con proyectos de Arduinos bajo consumo:

Otra opción interesante para alimentar directamente el microcontrolador de Arduino sin la placa con una batería, de forma que sea mucho más eficiente, es alimentar directamente mediante el bus de 5V de la placa. La propuesta consiste en conectar el pack de 4 pilas a la placa Arduino usando un diodo en 1N4001 en serie. La caída de tensión en el diodo será de unos 0,7V por lo que la tensión que se verá en la línea interna de 5V de la placa Arduino será 5.3V. Dado que el micro ATmega328 que es el corazón de Arduino UNO puede ser alimentado hasta con tensiones de 5.5V, nos hallamos dentro del margen correcto de funcionamiento. Los dos condensadores son para filtrar un poco el ruido y el valor dependerá del uso que se dé a la placa.

La realización de la solución anterior tiene un problema potencial si conectamos la placa Arduino al PC a través de un puerto USB cuando aún está alimentada por el pack de pilas.

Si conectamos las pilas con diodo, que dá una tensión de 5.3V a la línea +5V de la placa. Dado que no hemos conectado nada en Vin, el transistor conducirá, por lo que al conectar la placa al puerto USB tendremos un conflicto entre los 5,3V de nuestras pilas y los 5V del puerto USB. En el mejor de los casos se dará una corriente en el sentido de las pilas hacia el PC que, cuando alcance 500mA, hará saltar el fusible que lleva la placa.

El uso de este tipo de alimentación requiere de desconectar el pack de pilas cuando se desee programar la placa Arduino usando el puerto USB.

Más información: http://aim65.blogspot.com.es/2012/03/legobot-alimentando-el-arduino.html

En este enlace lo explica muy bien la alimentación de Arduino para sistemas autónomos, resumiendo todo lo visto: http://www.homautomation.org/2014/04/03/best-ways-to-power-a-arduino-according-to-your-need/

Alimentación Arduino por energía solar:

Niveles de tensión 5V y 3.3V

Uno de los problemas principales que nos podemos encontrar cuando estás realizando un proyecto es que tus dispositivos no trabajan con el mismo voltaje. Un caso especialmente habitual como usuario de plataformas del tipo Arduino es que te encuentras con un dispositivo que trabaja a 3.3V teniendo una placa que trabaja a 5V, en cuyo caso te toca pasar de 5V a 3.3V.

Aunque en algunas ocasiones puedes conectar ambas cosas sin que nada se rompa no suele ser buena idea conectar los dispositivos directamente. Lo mejor que puedes hacer es utilizar algún tipo de interfaz o elemento que te permita realizar la conexión de forma segura.

5 formas de pasar de 5V a 3.3V para elegir la que mejor se adapte a tu proyecto. Son las siguientes:

  • Utilizando un divisor de tensión.
  • Añadiendo diodos 1N4148 (o similar) en serie.
  • Mediante un buffer CD4050 (o similar) alimentado a 3.3V.
  • Usando un regulador de voltaje variable LM317 (o similar).
  • Con un regulador de tensión LM7833 de 3.3V (o similar).

Más información: http://www.educachip.com/pasar-de-5v-a-3-3v/

También nos podemos encontrar con el caso contrario, cada vez es más habitual que los Arduinos tengan entradas y salidas a 3,3V en lugar de a 5V, pero mucho elementos que conectado a Arduino funcionan con lógica de 5V.

Más información: https://findeprehistoria.wordpress.com/2010/07/29/interfaz-de-3-3v-a-5v-y-visceversa/

Y también tenemos los conversores de niveles lógicos como http://tienda.bricogeek.com/herramientas-de-prototipado/82-conversor-de-niveles-logicos-33-5v.html

Memoria Arduino

Arduino y todos los microcontroladores tienen varios tipos de memoria integradas, en el caso de Arduino y los microcontroladores AVR de Atmel usan tres tipos de memorias:

  • SRAM (static random access memory): Variables locales, datos parciales. Usualmente se trata como banco de registros y memoria volátil. Es la zona de memoria donde el sketch crea y manipula las variables cuando se ejecuta. Es un recurso limitado y debemos supervisar su uso para evitar agotarlo.
  • EEPROM:  Memoria no volátil para mantener datos después de un reset. Se puede grabar desde el programa del microcontrolador, usualmente, constantes de programa. Las EEPROMs tienen un número limitado de lecturas/escrituras, tener en cuenta a la hora de usarla. Esta memoria solo puede leerse byte a byte y su uso puede se un poco incómodo. También es algo más lenta que la SRAM. La vida útil de la EEPROM es de unos 100.000 ciclos de escritura
  • Flash: Memoria de programa. Usualmente desde 1 Kb a 4 Mb (controladores de familias grandes). Es donde se guarda el sketch ya compilado. Sería el equivalente al disco duro de un ordenador. En la memoria flash también se almacena del bootloader. Se puede ejecutar un programa desde la memoria flash, pero no es posible modificar los datos, sino que es necesario copiar los datos en la SRAM para modificarlos.
    La memoria flash usa la misma tecnología que las tarjetas SD, los pen drives o algunos tipos de SSD, esta memoria tiene una vida útil de unos 100.000 ciclos de escritura, así que cargando 10 programas al día durante 27 años podríamos dañar la memoria flash.

La memoria flash y la EEPROM son no volátiles, es decir, la información persiste tras el apagado del Arduino.

Memoria de Arduino UNO:

  • Flash  32k bytes (of which 0.5k is used for the bootloader)
  • SRAM   2k bytes
  • EEPROM 1k byte

Memoria de Arduino MEGA:

  • Flash  256k bytes (of which 8k is used for the bootloader)
  • SRAM   8k bytes
  • EEPROM 4k byte

Memoria de Arduino MKR1000:

  • Flash  256k bytes
  • SRAM   32k bytes
  • EEPROM no. Dispone de EEPROM emulation en la memoria flash (ver documentación del microcontrolador)

Memoria ESP8266:

  • 64 KiB of instruction RAM, 96 KiB of data RAM
  • External QSPI flash – 512 KiB to 4 MiB (no dispone de memoria Externa)

La memoria SRAM es un recurso escaso que debe gestionarse, especialmente si se usan los strings o cadenas de caracteres de forma intensiva. Si un Arduino se queda sin memoria SRAM, el sketch compilará bien y se cargará en el Arduino sin problema, pero se producirán efectos inesperados.

En caso de usar muchos strings, una técnica para evitar agotar la memoria SRAM es guardar en la memoria flash los strings que no se modifiquen en tiempo de ejecución, usando PROGMEM: https://www.arduino.cc/en/Reference/PROGMEM

Desde la versión 1.0 del IDE de Arduino, se introdujo la macro F(). Esta sintaxis se usa para almacenar strings en la memoria flash en lugar de en la memoria SRAM. No es necesario cargar ninguna librería para usar la macro F().

  • Serial.println(“This string will be stored in flash memory”); //este print ocupará 42 bytes de memoria SRAM con el contenido de la constante string
  • Serial.println(F(“This string will be stored in flash memory”)); //el string dentro de del println no se carga en la SRAM y se lee de la flash

En el caso que el sketch ocupe más memoria flash, el IDE te avisa de que no puede cargarlo en Arduino.

Desde las últimas versiones del IDE de Arduino tras compilar el sketch, aparece un resumen de la memoria flash que ocupa el programa y la memoria ocupada por las variables globales en la SRAM y el espacio que queda para las variables locales. Como recomendación, si se supera el 70%-75% de la  SRAM con las variables globales es muy probable que Arduino se quede sin memoria RAM.

Recordar que al incluir una librería, estoy añadiendo variables y tamaño al programa, lo que aumentará el uso de memoria SRAM y flash. Algunas librerías hacen un uso grande de la memoria SRAM y flash.

Memoria en Arduino:

Un buen tutorial para aprender como funcionan las memorias de Arduino: https://learn.adafruit.com/memories-of-an-arduino/you-know-you-have-a-memory-problem-when-dot-dot-dot

Toda la información de las memoria del ATMega328p está en la página 34 del datasheet http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf

Más información de las memoria de Arduino

MCU vs CPU en funcion de la arquitectura de la memoria: https://learn.adafruit.com/memories-of-an-arduino/arduino-memory-architecture

Como medir la memoria libre que tenemos en Arduino: https://learn.adafruit.com/memories-of-an-arduino/measuring-free-memory

Como saber cuando me he quedado sin memoria: https://learn.adafruit.com/memories-of-an-arduino

Consumidores de Memoria en Arduino: https://learn.adafruit.com/memories-of-an-arduino/large-memory-consumers

Como optimizar la memoria flash: https://learn.adafruit.com/memories-of-an-arduino/optimizing-program-memory

Cómo optimizar la memoria SRAM: https://learn.adafruit.com/memories-of-an-arduino/optimizing-sram

Memoria SRAM

Al ser el recurso más escaso en Arduino hay que entender bien cómo funciona. La memoria SRAM puede ser leída y escrita desde el programa en ejecución.

La memoria SRAM es usada para varios propósitos:

  • Static Data: Este bloque de memoria reservado en la SRAM para todas las variables globales y estáticas. Para variables con valores iniciales, el sistema copia el valor inicial desde la flash al iniciar el programa.
  • Heap: Es usado para las variables o elementos que asignan memoria dinámicamente. Crece desde el final de la zona de Static Data a medida que la memoria es asignada. Usada por elementos como los objetos y los Strings.
  • Stack: Es usado por las variables locales y para mantener un registro de las interrupciones y las llamadas a funciones. La pila crece desde la zona más alta de memoria hacia el Heap. Cada interrupción, llamada de una función o llamada de una variable local produce el crecimiento de la memoria.
    La mayor parte de los problemas ocurren cuando la pila y el Heap colisionan. Cuando esto ocurre una o ambas zonas de memoria se corrompen con resultados impredecibles. En uno casos se produce un “cuelgue” del programa y en otros casos la corrupción de memoria puede notarse un tiempo después.

A partir de la versión 1.6 del IDE al compilar un sketch nos da el tamaño que va a ocupar en la flash el proyecto y el espacio que va a ocupar en la SRAM las variables globales, es decir, la zona de static data.

Como ya se ha visto anteriormente, en la memoria SRAM también se encuentran los registros que ocupan las primeras 256 direcciones de memoria. Por lo tanto la SRAM empieza a partir de la dirección 0x0100.

Los registros al estar en la SRAM son volátiles y no conservan su valor después de un reset. Mirando la documentación del microcontrolador se puede ver cuales son los valores por defectos de los registros.

ram-map

Si vemos a fondo la memoria SRAM de Arduino.

  • .data variables is the first RAM section and it is used to store program static data, such as strings, initialized structures and global variables.
  • .bss variables is the memory allocated for uninitialized global and static variables.
  • heap is the dynamic memory area, and this is the playground area for malloc (and alike). The heap can grow (when new allocation is made) or “possibly” decrease in size (when memory is released, as for example when using free) based on the requirements.
  • stack is the memory area located at the end of the RAM and it grows towards the heap area. The stack area is used for function calls, storing values for local variables. Memory occupied by local variables is reclaimed when the function call finished.
  • external RAM is only available to some of the MCUs and it means that it is possible to add RAM in a kind of similar way that we do for a PC. Usually this is expensive (a few KB of external RAM costs in general more than the MCU) and requires also advanced hardware and software skills.
  • free available memory is the area between heap and stack and this is what we need to measure in order to detect problems caused by not enough RAM resources.When this area is either too small for the required tasks, or is missing at all (heap meets stack), our MCU starts to missbehave or to restart itself.

El siguiente código permite calcular la memoria libre en bytes para un Arduino y funciona tanto con el IDE de Arduino como con Atmel Studio:

extern unsigned int __bss_end;
extern unsigned int __heap_start;
extern void *__brkval;

uint16_t getFreeSram() {
  uint8_t newVariable;
  // heap is empty, use bss as start memory address
  if ((uint16_t)__brkval == 0)
    return (((uint16_t)&newVariable) - ((uint16_t)&__bss_end));
  // use heap end as the start of the memory address
  else
    return (((uint16_t)&newVariable) - ((uint16_t)__brkval));
};

PROGMEM

PROGMEM se usa para guardar en la memoria flash en lugar de en la SRAM. La palabra PROGMEM en un modificador de variable que debe usarse solo con los tipos de datos definidos en pgmspace.h. Al usarlo le dice al compilador que ponga la información de la variable en la memoria flash en lugar de la SRAM, donde iría normalmente.ç

PROGMEM es parte de la librería pgmspace.h http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html que solo está disponible para la arquitectura AVR, así que para usarlo hay que inclirla al principio del sketch con #include <avr/pgmspace.h>

Más información:

  • sizeof() – devuelve el número de bytes en una variable o el número de bytes ocupados por un array.
  • PROGMEM

En muchos casos, una gran cantidad de RAM es ocupada por la memoria estática, como resultado del uso de variables globales (tales como cadenas o números). Siempre que estos datos no se vayan a cambiar, puede ser fácilmente almacenado en la llamada PROGMEM (memoria de programa o flash) Esto representa trozo de la memoria flash, y es bueno saber que, en general, la memoria flash es mucho más grande que la memoria RAM (por ejemplo, Atmega2560 tiene 8 KB de RAM y flash de 256 KB). La desventaja de usar PROGMEM es la velocidad de lectura, que es más lento en comparación con la lectura de los mismos datos de la RAM.

Más información sobre memoria en Arduino:

Práctica: Uso de Memoria en Arduino

Para entender el uso de la memoria, hagamos una práctica añadiendo y quitando elementos del sketch y viendo la ocupación de memoria.

Funciones para calcular memoria libre en Arduino:

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

Enunciado: Calcula memoria RAM de tu Arduino UNO sin ejecutar ningún programa con la función freeRam() y comparalo con el dato que da al compilar otro programa, también averigua cuánto ocupa la memoria Flash de los programas. Luego calcula la memoria RAM y la Flash utilizada con un programa que cada loop saque por puerto serie cada 5 segundos el siguiente texto:

“Arduino es una plataforma de hardware libre, basada en una placa con un microcontrolador y un entorno de desarrollo, diseñada para facilitar el uso de la electrónica en proyectos multidisciplinares. El hardware consiste en una placa con un microcontrolador Atmel AVR y puertos de entrada/salida. Los microcontroladores más usados son el Atmega168, Atmega328, Atmega1280, ATmega8 por su sencillez y bajo coste que permiten el desarrollo de múltiples diseños. Por otro lado el software consiste en un entorno de desarrollo que implementa el lenguaje de programación Processing/Wiring y el cargador de arranque que es ejecutado en la placa.Desde octubre de 2012, Arduino se usa también con microcontroladoras CortexM3 de ARM de 32 bits,5 que coexistirán con las más limitadas, pero también económicas AVR de 8 bits. ARM y AVR no son plataformas compatibles a nivel binario , pero se pueden programar con el mismo IDE de Arduino y hacerse programas que compilen sin cambios en las dos plataformas. Eso sí, las microcontroladoras CortexM3 usan 3,3V, a diferencia de la mayoría de las placas con AVR que generalmente usan 5V. Sin embargo ya anteriormente se lanzaron placas Arduino con Atmel AVR a 3,3V como la Arduino Fio y existen compatibles de Arduino Nano y Pro como Meduino en que se puede conmutar el voltaje.”

Luego haz que aumente la RAM con el modificador F y compruebalo.

Resultado:

Ejemplo de cálculo de la velocidad de la memoria: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Otros/velocidadMemoria

Ejemplo de como llenar la memoria de Arduino: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Otros/llenarMemoria

  • Opción todo a 0: solo ocupa la memoria de las variables globales definidas pero no inicializadas. 822 bytes libres.
  • Opción todo a 0 y eliminar el array de 100 Strings global: Dispongo de toda la memoria.
  • Opción LOCAL = 1: defino una nueva variable local en el loop pero al inicializarla en cada loop no aumenta la memoria.
  • Opción STRINGS = 1: tengo un array de 100 objetos Strings y a medida que los voy inicializando con 10 bytes lleno el heap y acabo llenando la memoria
  • Opción GLOBAL = 1: en el momento que inicalizo el array de 1000 long asignando un valor me ocupa 4000 bytes en la RAM y ya de un error de compilación.

 

Firmata

Firmata es un protocolo genérico para la comunicación con microcontroladores desde software instalado en un ordenador. Este protocolo se puede implementar en cualquier arquitectura de microcontroladores, así como en cualquier paquete de software.

El objetivo de firmata es permitir controlar completamente Arduino desde software instalado en un ordenador, sin escribir una sola línea de código de Arduino.

Por ejemplo, cuando se dice que Windows 10 puede usarse con Arduino o incluso se puede leer en algunos artículos “Como instalar windows 10 en Arduino”, realmente lo que significa es que puedes controlar un Arduino desde Windows 10, mediante la comunicación con el protocolo firmata entre Windows 10 y Arduino. Windows 10 implementa este protocolo de forma nativa.

Enlaces Windows 10 y Arduino:

Explicación de Windows + Arduino:

La librería: https://github.com/ms-iot/remote-wiring

Esto permite instalar un programa en windows 10 con soporte nativo de .NET para comunicarse con un Arduino y hacer que encienda un led, mueva un motor o lea la temperatura de un sensor conectado al Arduino sin tener que programar el Microcontrolador.

Más adelante entraremos a fondo en como usar Arduino con Windows 10.

Para comprobar fácilmente cómo funciona firmata, disponemos de un programa que funciona en Windows, Linux, Mac OS-X y necesita la version 2.2 o superior de la librería Firmata para Arduino (actualmente está en la 2.5). Este programa se llama “Firmata Test Program” y está disponible en: http://firmata.org/wiki/Main_Page#Firmata_Test_Program

Para implementar el protocolo firmata en Arduino debemos usar el sketch StandardFirmata que está incluido en el IDE de Arduino: https://github.com/firmata/arduino/tree/master/examples/StandardFirmata

La última versión de la librería Firmata para Arduino está en: https://github.com/firmata/arduino

Hay dos modos de uso de firmata. Un modelo es usar los métodos ofrecidos por la librería firmata dentro del sketch para enviar y recibir datos entre el Arduino y el software ejecutándose en el ordenador. Por ejemplo, mandar el valor leído de una entrada analógica.

El segundo modelo y más común es cargar en Arduino el sketch de propósito general llamado “StandardFirmata” o alguna de sus variaciones como “StandardFirmataPlus” o “StandardFirmataEthernet” y usar el software en el ordenador para interactuar con Arduino.

Un listado de los clientes de firmata para diversos lenguajes de programación se puede encontrar en: https://github.com/firmata/arduino#firmata-client-libraries

En caso que deseemos contribuir en el desarrollo o mejorar en la implementación de firmata en Arduino ver: https://github.com/firmata/arduino#contributing

Y cualquier problema sobre el desarrollo se puede seguir en el hilo de gitter: https://gitter.im/firmata/arduino y en los problemas de diseño: http://firmata.org/wiki/Design_Issues

Se debe tener en cuenta que debido a la limitada memoria de Arduino, el número de funcionalidades que se puede añadir es limitada.

Práctica: Probar como funciona el protocolo firmata en Arduino.

  1. Descargar el programa “Firmata Test Program” para sistema operativo correspondiente de http://www.pjrc.com/teensy/firmata_test/
  2. Cargar el sketch “StandardFirmata” en Arduino: Archivo -> Ejemplos -> Firmata -> StandardFirmata.
  3. Probar que funciona encendiendo Leds y leyendo valores de los pines analógicos y digitales.

Firmata_Test

Detalles del protocolo

El estándar del protocolo firmata se puede encontrar en: https://github.com/firmata/protocol, donde disponemos de las espcificaciones del protocolo standard, así como las implementaciones para comunicar con dispositivos i2c, onewire, soporte para encoders, servos, motores paso a paso, etc…

La anterior web oficial del protocolo firmata es http://firmata.org/wiki/Main_Page que se mantiene a efectos de documentación

Firmata está basado en el formato de mensaje de midi: http://www.midi.org/techspecs/midimessages.php en el que los comandos se mandan en 8 bits y los datos en 7 bits. En Midi System Exclusive (Sysex http://www.2writers.com/eddie/tutsysex.htm), los mensajes pueden tener cualquier longitud y se usa de forma más extensiva en el protocolo firmata.

El núcleo del protocolo está descrito en: https://github.com/firmata/protocol/blob/master/protocol.md

La implementación del protocolo firmata para Arduino se encuentra en https://github.com/firmata/arduino aunque este protocolo se podría implementar en cualquier otro microcontrolador.

La versión actual del protocolo firmata es la 2.5. Se trata de un protocolo serie a una velocidad de 57600 baudios.

Comandos

Los comandos (primer byte del protocolo), se descomponen en el primer nibble (el más significativo) es el propio comando y el segundo nibble del byte (el menos significativo) que en algunos casos aparece como 0 y da el número de puerto o de pin.

Los comandos son:

  • 0x90 – datos del pin digital (un puerto son hasta 8 pines digitales que se almacenan en en los “port registers” que permiten una manipulación a bajo nivel más rápida. Cada puerto es controlado por 3 registros. Más información en https://www.arduino.cc/en/Reference/PortManipulation o en el capítulo del Tema 3 “Microcontroladores. Registros de memoria”.
  • 0xE0 – datos del pin analógico
  • 0xF4 – Configurar el modo del pin
  • 0xF5 – configurar el valor del pin digital
  • 0xC0 – configurar reporte del pin digital (una vez habilitado, el valor del pin debe ser reportado a la aplicación cliente)
  • 0xD0 – configurar reporte del pin analógico (una vez habilitado, el valor del pin debe ser reportado a la aplicación cliente)
  • 0xF9 – versión del protocolo

En esta tabla se ve el mensaje utilizado y los bytes de datos usados:

type command MIDI channel first byte second byte
analog I/O message 0xE0 pin # LSB(bits 0-6) MSB(bits 7-13)
digital I/O message 0x90 port LSB(bits 0-6) MSB(bits 7-13)
report analog pin 0xC0 pin # disable/enable(0/1) – n/a –
report digital port 0xD0 port disable/enable(0/1) – n/a –
start sysex 0xF0
set pin mode(I/O) 0xF4 pin # (0-127) pin state(0=in)
set digital pin value 0xF5 pin # (0-127) pin value(0/1)
sysex end 0xF7
protocol version 0xF9 major version minor version

Comandos sysex: la idea de estos comandos es disponer de un espacio para un segundo comando usando el primer byte después del SysEx start byte (0xF0). La diferencia es que los datos pueden tener cualquier tamaño al contrario que los mensajes MIDI standard que tienen 2 bytes)

  • 0x71 – string
  • 0x79 – nombre/versión del firmware
  • 0xF7 – fin de Sysex

Más información en: https://github.com/firmata/protocol/blob/master/protocol.md#sysex-message-format

Más información del protocolo en: https://github.com/firmata/protocol/blob/master/protocol.md

La librería Firmata para Arduino

La librería Firmata de Arduino implementa el protocolo Firmata visto anteriormente para comunicar el Arduino con el software ejecutado en un ordenador

La última versión de la librería firmata para Arduino se encuentra en: https://github.com/firmata/arduino

La referencia de la librería Firmata para Arduino se encuentra en: https://www.arduino.cc/en/Reference/Firmata

Los métodos disponibles en la librería son:

  • begin(long) – Comienza la librería, es posible poner otra velocidad diferente a la velocidad por defecto que es 57600 baudios. También es posible iniciar el protocolo firmata desde otro Stream que no sea el que viene por defecto que es Serial
  • printVersion() – envía la versión del protocolo al ordenador
  • blinkVersion() – parpadea la versión de protocolo en el “build in LED”, generalmente el pin 13.
  • printFirmwareVersion() . envía la versión de firmware y su versión al ordenador
  • setFirmwareVersion(byte major, byte minor) – Configura la versión del firmware
  • setFirmwareNameAndVersion(const char *name, byte major, byte minor) – Configura nombre y versión del firmware

Métodos de envío de mensajes:

  • sendAnalog(byte pin, int value) – Manda el valor del pin analógico
  • sendDigitalPort(byte portNumber, int portData) – Manda el valor de un puerto digital de 8 bits.
  • sendString(const char* string) – Manda un string a un ordenador.
  • sendString(byte command, byte bytec, byte *bytev) – Manda un string al ordenador usando un tipo de comando
  • sendSysex(byte command, byte bytec, byte* bytev) – Manda un comando un con array de bytes
  • write(byte c) – Manda un byte al stream de datos.

Métodos de recepción de mensajes.

  • available() – Comprueba si hay algún mensaje entrante en el buffer
  • processInput() – Procesar los mensajes entrantes que hay en el buffer, mandado los datos a cualquiera de las funciones de callback registradas.
  • attach(byte command, callbackFunction myFunction) – Registrar una función a un tipo de mensaje entrante.
  • detach(byte command) –  desregistrar la función del tipo de mensaje

Otros métodos:

  • sendValueAsTwo7bitBytes(int value) – Escribe el valor como 2 bytes
  • startSysex(void) – Comenzar mensaje sysex
  • endSysex(void) – Finalizar mensaje sysex

Para asociar una función de callback a un tipo de mensaje de Firmata, la función debe cumplir el estándar de “callback function”. Hay varios tipos de funciones de respuesta en Firmata:

  • genérica: void callbackFunction(byte pin, int value);
  • reset del sistema: void systemResetCallbackFunction(void);
  • string: void stringCallbackFunction(char *myString);
  • sysex: void sysexCallbackFunction(byte command, byte byteCount, byte *arrayPointer);

Hay varios tipos de mensajes que se pueden asociar a las funciones de callback:

  • ANALOG_MESSAGE //the analog value for a single pin // Comando (0xE0)
  • DIGITAL_MESSAGE //8-bits of digital pin data (one port) // Comando (0x90)
  • REPORT_ANALOG //enable/disable the reporting of an analog pin // Comando (0xC0)
  • REPORT_DIGITAL //enable/disable the reporting of a digital port // Comando (0xD0)
  • SET_PIN_MODE //change the pin mode between INPUT/OUTPUT/PWM/etc. // Comando (0xF4)
  • STRING_DATA //C-style strings, uses stringCallbackFunction for the function type // Comando (0x71)
  • SYSEX_START //generic, arbitrary length messages (via MIDI SysEx protocol), uses sysexCallbackFunction for the function type // Comando (0xF0)
  • SYSTEM_RESET //message to reset firmware to its default state, uses systemResetCallbackFunction for the function type

Para instalar Standard Firmata en Arduino, se puede serguir este tutorial: http://www.instructables.com/id/Arduino-Installing-Standard-Firmata/?ALLSTEPS

Veamos el sketch que implementa firmata en Arduino llamado StandardFirmata.ino y es muy usado por aplicaciones para ordenador y móvil. Código: https://github.com/firmata/arduino/blob/master/examples/StandardFirmata/StandardFirmata.ino

Detalles:

  • Implementa control de servos (librería servo.h), dispositivos I2C (librería wire.h)
  • En línea 96, implementa la función wireWrite y wireRead para que funcione con todo tipo de versiones de IDE Arduino al compilar.
  • En línea 747 setup: inicializa la versión de firmware y asocia las funciones de callback a los mensajes de entrada. La implementación de cada función se hace en las líneas anteriores. Luego resetea a la configuración por defecto de los pines.
  • En línea 777 loop: en cada loop primero comprueba el cambio de estado de las entradas digitales. Luego busca mensajes entrantes firmata y los procesa si es necesario. Por último lee las entradas analógicas según el intervalo de muestreo configurado y manda datos a los dispositivos I2C con modo de lectura continua activado.

Y también tenemos estas otras implementaciones de firmata en Arduino:

Existen implementaciones específicas otras plataforma de desarrollo como spark que se puede ver en: https://github.com/firmata/spark

Ejercicio38 – Entendiendo Firmata:

Para poder ver los mensajes enviados por el protocolo firmata y entender cómo funciona, vamos a ejecutar un sketch que manda las lecturas de todos los puertos analógicos por el puerto serie con firmata.

Dado que los mensajes son en hexadecimal no es posible ver los mensajes con el terminal proporcionado por el IDE de Arduino y para ello se puede usar esta otra aplicación de terminal: https://sites.google.com/site/terminalbpp/

Pasos a seguir:

  1. Cargar en Arduino el sketch del ejercicio38 Entendiendo_Firmata: https://github.com/jecrespo/Aprendiendo-Arduino/blob/master/Ejercicio38-Firmata/Entendiendo_Firmata/Entendiendo_Firmata.ino
  2. Entender que hacer este sketch
  3. Abrir el programa de Terminal y configurarlo con:
    1. Baud rate = 57600
    2. Receive en HEX
    3. Habilitar las pantallas Dec, Hex y Bin
  4. Ejecutar el programa y capturar lo que envía Arduino en Hexadecimal.

Terminal_Firmata

En cada loop manda FFFF que nos indica que inica un loop, luego manda para el caso de un Arduino UNO manda las lecturas de los 6 puertos analógicos con el comando ANALOG_MESSAGE E0, E1, E2, etc… y luego el valor leído

Para entender lo que muestra, hay que ver cómo está implementado el protocolo para el comando ANALOG_MESSAGE en https://github.com/firmata/protocol/blob/master/protocol.md

type command MIDI channel first byte second byte
analog I/O message 0xE0 pin # LSB(bits 0-6) MSB(bits 7-13)

E1 — Pin analógico 1
7D — 01111101
07 — 00000111
Valor = 00001111111101 = 1021

También manda en valor en decimal para comprobar con el Serial.println

Avanzado: Ver los ejemplos que trae la librería firmata de Arduino, entender y comprobar cómo funciona.

  • SimpleAnalogFirmata
  • SimpleDigitalFirmata

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio38-Firmata

Firmata para controlar buses

Firmata no solo nos permite leer y escribir en puertos analógicos y digitales, también es posible manejar diferentes buses.

Firmata y Arduino en Windows 10

Microsoft ha entrado en el IoT con Windows 10 IoT Core que es una versión de Windows 10 optimizada para pequeños dispositivos como Raspberry Pi 2 y que usa la API de Universal Windows Platform (UWP) para construir aplicaciones.

En Abril de 2015 Microsoft anuncia Windows 10 IoT Core y la participación con Arduino: https://blogs.windows.com/buildingapps/2015/04/29/microsoft-brings-windows-10-to-makers/

Windows 10 IoT Core también soporta la API Arduino-Wiring usada en los sketches y librerías para un acceso directo al hardware desde Windows 10. Para programar Arduino Microsoft nos propone su IDE Visual Studio. Esto facilita a la gente familiarizada con la programación en .NET entrar en el mundo Arduino.

Más información en:

Para empezar con Windows IoT, solo hay que seguir las instrucciones de: http://ms-iot.github.io/content/en-US/GetStarted.htm en el apartado de Arduino y Windows 10.

En nuestro caso el apartado que nos interesa para comunicar una aplicación desarrollada en Windows con Arduino es el Windows Remote Arduino.

Básicamente esta librería open source une un dispositivo con Windows 10 y Arduino mediante el protocolo firmata de forma sencilla.

Ejemplo para hacer blink con Windows Remote: https://www.hackster.io/windowsiot/basic-windows-remote-arduino-47eeb9

Esta imagen explica el funcionamiento de Windows Remote Arduino:

1_architecture

Una muy buena explicación de Windows Remote Arduino: https://blogs.windows.com/buildingapps/2016/02/04/what-is-windows-remote-arduino-and-what-can-it-do/

También es posible hacer aplicaciones .NET sin tener windows 10 usando una librería de firmata: http://www.acraigie.com/programming/firmatavb/

Es posible encontrar más proyectos de  Windows 10 + Arduino en: https://microsoft.hackster.io/en-US/search?q=arduino

Otros enlaces:

Firmata y Arduino con Python

Una forma sencilla de comunicar Arduino con el ordenador mediante software open source es usar python. Hay disponibles varias librerías de firmata para python que facilitan el interfaz entre Arduino y el programa hecho en python.

Dado que Python es posible usarlo en multitud de Sistemas Operativos e incluso en Raspberry Pi o similares, tenemos una herramienta potente con Firmata + Python para comunicar Arduino con cualquier otro dispositivo.

Una buena guía para usar Arduino con python se encuentra en el playground de Arduino: http://playground.arduino.cc/Interfacing/Python

Para comunicar por puerto serie el ordenador ejecutando python, la mejor opción es usar la librería pyserial de python:

No solo es posible interactuar con Arduino por el puerto serie, sería similar hacerlo vía bluetooth, ethernet, etc… con las librerías adecuadas disponibles en python.

Librerías de Firmata para python:

Un artículo que explica perfectamente y en un lenguaje muy sencillo cómo controlar un Arduino a través de un programa de ordenador mediante firmata se puede leer en: http://edupython.blogspot.com.es/2014/06/como-programar-tu-arduino.html

Al usar firmata en Arduino y correr los programas en un ordenador tenemos unas serie de ventajas y desventajas respecto a cargar el sketch en el propio Arduino. Dependiendo del objetivo de nuestro proyecto puede ser más útil una estrategia u otra.

Ventajas:

  • Nuestro programa no está limitado por la memoria RAM y Flash de Arduino
  • El software de control se puede programar en cualquier lenguaje, no solo C++, siempre que tenga soporte para firmata. Por ejemplo: Firmata: Processing, Visual Basic, Perl, C#, PHP, Java, JavaScript, Ruby y por su puesto Python.

Desventajas:

  • Programas más restringidos, es posible que algunas operaciones complejas no sea posible hacerlas. Por ejemplo el uso de interrupciones.
  • Al arduino siempre debe estar conectado al ordenador. Debe tener comunicación para poder ejecutar acciones.

Ejercicio 38 – Blink (Arduino + Python + Firmata)

Vamos a probar varios programas para controlar Arduino desde programas corriendo en el ordenador hechos en python.

Preparar entorno para python:

  1. Descargar Python para el sistema operativo correspondiente: https://www.python.org/downloads/
  2. Instalar Python: https://docs.python.org/3/using/windows.html
  3. Instalar dependiencias python: http://code.rancidbacon.com/LearningAboutArduinoandPython

Preparar Arduino:

  1. Cargar el sketch StandardFirmata en Arduino.

Ejecutar el programa desde el ordenador usando la librería PyMata:

  1. Ejecutar el ejemplo blink.py: https://github.com/jecrespo/Aprendiendo-Arduino/blob/master/Ejercicio38-Firmata/Python_Firmata/blink.py 
  2. Para conocer algo más de PyMata, ver los ejemplos de https://github.com/MrYsLab/PyMata/tree/master/examples

Para entender a fondo la librería PyMata ver la documentación de la API: http://htmlpreview.github.io/?https://github.com/MrYsLab/PyMata/blob/master/documentation/html/PyMata.pymata.PyMata-class.html

Ejercicio 38 – Medidor de luz con Firmata

Vamos a hacer un medidor de luz controlado por una fotoresistencia LDR pero usando firmata.

Hagamos este ejemplo sencillo pero sin programar una sola línea en el Arduino y controlarlo desde el ordenador: http://www.geekfactory.mx/tutoriales/tutoriales-arduino/tutorial-arduino-con-fotoresistencia-ldr/

Se trata de encender los LEDs en función de la intensidad de luz. Leer el código del ejemplo original y trasladarlo a un programa en python con firmata.

El esquema de conexiones es:

arduino_con_fotoresistencia_ldr-510x322

En este caso vamos a usar la librería pyFirmata que ya tenemos instalada y en Arduino ya está instalado el standardFirmata.

Ejecutar el ejemplo Medidor_Luz.py de https://github.com/jecrespo/Aprendiendo-Arduino/blob/master/Ejercicio38-Firmata/Python_Firmata/Medidor_Luz.py

Más información de pyFirmata en: https://github.com/tino/pyFirmata

Solución a los ejercicios: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio38-Firmata

Otro ejemplo explicado similar está en http://edupython.blogspot.com.es/2014/06/como-programar-tu-arduino.html

Avanzado: ejemplos con pyFirmata más complejos en: https://bitbucket.org/fab/pyfirmata/src/96116e877527/examples/, incluso hay un programa con una interfaz gráfica que funciona en linux.

Implementaciones de firmata en otros lenguajes

Como hemos visto, podemos controlar Arduino desde el ordenador mediante el protocolo firmata programando con cualquier lenguaje de programación que tenga implementado firmata o hagamos nosotros mismos la implementación. Podemos usar diversas librerías en función del lenguaje de programación que queramos usar:

Cuando se habla que programar Arduino con tal o cual lenguaje se refiere a hacer el control desde un ordenador que da órdenes a un Arduino corriendo standardFirmata.

En esta web tenemos múchos ejemplos de software/librerías para programar un Arduino desde un ordenador: http://firmata.org/wiki/Download (alternativa https://web.archive.org/web/20150911005414/http://firmata.org/wiki/Download)

Ejemplos interesantes:

Como ya se ha dicho, firmata no solo puede usarse por el puerto serie sino por cualquier otro medio. Ejemplo de uso de firmata con bluetooth para comunicar arduino + beaglebone: http://www.instructables.com/id/Wireless-Arduino-Control-Using-the-BeagleBone-Blac/

Firmata Builder

Firmata Builder es un módulo que nos permite generar un sketch de Arduino desde una selección de características de firmata.

Más información en:

Firmata Builder nos permite crear un sketch StandardFirmata reducido para nuestras necesidades y añadir otras funcionalidades propias.

ConfigurableFirmata es una versión de Firmata que separa las características del protocolo en clases individuales, haciendo más sencillo mezclar las características estándar del protocolo con otras personalizadas. La forma más sencilla de usar ConfigurableFirmata es usando FirmataBuilder.

Proyecto en github: https://github.com/firmata/ConfigurableFirmata

Fuente de ConfigurableFirmata: https://github.com/firmata/ConfigurableFirmata/tree/master/src

Librerías cliente que soportan ConfigurableFirmata: https://github.com/firmata/ConfigurableFirmata#firmata-client-libraries

Ejemplo: https://github.com/firmata/ConfigurableFirmata/blob/master/examples/ConfigurableFirmata/ConfigurableFirmata.ino