Archivo de la etiqueta: avr-libc

Programación Arduino

La programación de Arduino es la programación de un microcontrolador. Esto era algo más de los ingenieros electrónicos, pero Arduino lo ha extendido a todo el público. Arduino ha socializado la tecnología.

Programar Arduino consiste en traducir a líneas de código las tareas automatizadas que queremos hacer leyendo de los sensores y en función de las condiciones del entorno programar la interacción con el mundo exterior mediante unos actuadores.

Arduino proporciona un entorno de programación sencillo y potente para programar, pero además incluye las herramientas necesarias para compilar el programa y “quemar” el programa ya compilado en la memoria flash del microcontrolador. Además el  IDE nos ofrece un sistema de gestión de librerías y placas muy práctico. Como IDE es un software sencillo que carece de funciones avanzadas típicas de otros IDEs, pero suficiente para programar.

Estructura de un Sketch

Un programa de Arduino se denomina sketch o proyecto y tiene la extensión .ino. Importante: para que funcione el sketch, el nombre del fichero debe estar en un directorio con el mismo nombre que el sketch.

No es necesario que un sketch esté en un único fichero, pero si es imprescindible que todos los ficheros estén dentro del mismo directorio que el fichero principal.

void setup() {
 // put your setup code here, to run once:
}

void loop() {
 // put your main code here, to run repeatedly:
}

La estructura básica de un sketch de Arduino es bastante simple y se compone de al menos dos partes. Estas dos partes son obligatorios y encierran bloques que contienen declaraciones, estamentos o instrucciones.

Adicionalmente se puede incluir una introducción con los comentarios que describen el programa y la declaración de las variables y llamadas a librerías.

setup() es la parte encargada de recoger la configuración y loop() es la que contiene el programa que se ejecuta cíclicamente (de ahí el término loop –bucle-). Ambas funciones son necesarias para que el programa trabaje.

La estructura del sketch está definida en el siguiente enlace: http://arduino.cc/en/Tutorial/Sketch

Se puede resumir un sketch de Arduino en los siguientes diagramas de flujo:

Un ejemplo puede ser el diagrama de flujo de un sistema de arranque y parada de un motor DC:

Esquema de conexiones:

El código asociado a este diagrama se puede encontrar en https://github.com/jecrespo/Aprendiendo-Arduino-Proyectos/tree/master/Proyecto_02-Motor_DC_Controlado

Lenguaje de Programación Arduino

El lenguaje de programación de Arduino es C++. 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 y muchas utilidades específicas para las MCU AVR de Atmel como avrdude: https://learn.sparkfun.com/tutorials/pocket-avr-programmer-hookup-guide/using-avrdude

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, pero cuando compilamos y cargamos un sketch estamos usando estas herramientas.

Aunque se hable de que hay un lenguaje propio de programación de Arduino, no es cierto, la programación se hace en C++ pero Arduino ofrece una api o core que facilitan la programación de los pines de entrada y salida y de los puertos de comunicación, así como otras librerías para operaciones específicas. El propio IDE ya incluye estas librerías de forma automática y no es necesario declararlas expresamente. Otra diferencia frente a C++ standard es la estructuctura del programa que ya hemos visto anteriormente.

Toda la información para programar Arduino se encuentra en el reference de la web de Arduino: https://www.arduino.cc/en/Reference/HomePage y es la capa superior que ofrece Arduino para programar los microcontroladores de una forma sencilla y con un lenguaje de programación entendible fácilmente.

Un manual sencillo de entender para la programación es el “arduino programming notebook” de brian w. Evans. Puedes consultarlo o descargarlo desde:

En contraposición al core de Arduino, es posible usar comandos estándar de C++ en la programación de Arduino siempre que estén incluidos en el avr libc:

Cuando compilamos y cargamos el programa en Arduino esto es lo que ocurre:

Además todo esto no solo es válido para las placas Arduino, sino para muchas otras placas y microcontroladores que usando el mismo lenguaje de programación tenemos soporte para compilarlo y transferir el código binario a la memoria flash del microcontrolador.

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");

Otra característica propia de la programación de microcontroladores en C++ son el acceso a los elementos de HW mediante la lectura y escritura en los registros del microcontrolador.

Los registros son unas zonas concretas de la memoria RAM accesibles directamente desde la CPU o desde otros elementos del microcontrolador que permite hacer operaciones directas.

Cálculos de la velocidad de las operaciones en Arduino: http://forum.arduino.cc/index.php?topic=200585.0

Librerías

Las librerías son trozos de código hechos por terceros que usamos en nuestro sketch. Esto nos facilita mucho la programación y hace que nuestro programa sea más sencillo de hacer y de entender. En este curso no veremos como hacer o modificar una librería pero en este curso debemos ser capaces de buscar una librería, instalarla, aprender a usar cualquier librería y usarla en un sketch.

Las librerías normalmente incluyen los siguientes archivos comprimidos en un archivo ZIP o dentro de un directorio. Estas siempre contienen:

  • Un archivo .cpp (código de C++)
  • Un archivo .h o encabezado de C, que contiene las propiedades y métodos o funciones de la librería.
  • Un archivo Keywords.txt, que contiene las palabras clave que se resaltan en el IDE (opcional).
  • Muy posiblemente la librería incluye un archivo readme con información adicional de lo que hace y con instrucciones de como usarla.
  • Directorio denominado examples con varios sketchs de ejemplo que nos ayudará a entender cómo usar la librería (opcional).

La instalación de librerías se puede hacer directamente desde el gestor de librerías o manualmente.

En el Arduino Playground también tenemos un listado mucho más amplio de librerías, ordenadas por categorías: http://playground.arduino.cc/Main/LibraryList

También tenemos información de como interactuar con diferente HW en http://playground.arduino.cc/Main/InterfacingWithHardware

Además de estas librerías “oficiales” que podemos obtener desde el gestor de librerías y las publicadas en el playground de Arduino, existen muchos desarrollos disponibles en Internet y los propios fabricantes de componentes HW publican las librerías para poder usarlo o incluso la propia comunidad de usuarios.

Ejemplo de librería: https://github.com/jecrespo/simpleNTP

Ejemplo de Programación

Como ejemplo del proceso de programación con Arduino es el contador de minutos para charlas hecho con una matriz 8×8 de leds tricolor: https://www.adafruit.com/product/1487

Este contador marca los minutos que llevas durante la charla y marca en bloque de 10 colores para indicar la finalización de cada capítulo de 10 minutos

Pasos:

  1. Leer caracteristicas del HW y como conectarlo: https://learn.adafruit.com/adafruit-neopixel-uberguide
  2. Elegir una librería para manejarlo: http://fastled.io/
  3. Instalar la librería: https://github.com/FastLED/FastLED
  4. Leer cómo manejar la librería: https://github.com/FastLED/FastLED/wiki/Basic-usage
  5. Escribir el código y publicarlo: https://github.com/jecrespo/Aprendiendo-Arduino/blob/master/Otros/Neopixel_contador/Neopixel_contador.ino

Computación Física

La computación física (physical computing) se refiere al diseño y construcción de sistemas físicos que usan una mezcla de software y hardware para medir e interactuar con el medio que le rodea.

La computación física significa la construcción de sistemas físicos interactivos mediante el uso de software y hardware que pueden detectar y responder al mundo analógico. En un sentido amplio, la computación física es un marco creativo para entender la relación de los seres humanos con el mundo digital. En el uso práctico, el término describe con mayor frecuencia proyectos artesanales, de diseño o de hobby que utilizan sensores y microcontroladores para traducir entradas analógicas a un sistema de software y controlar dispositivos electromecánicos tales como motores, servos, iluminación u otro hardware.

La computación física es un enfoque para aprender cómo los seres humanos se comunican a través de computadoras que comienza por considerar cómo los seres humanos se expresan físicamente. La interacción clásica con los ordenadores es a través de teclados, ratones, pantalla, altavoces, etc… y toda la programación se hace con esos límites. En el caso de la computación física, no existen esos límites sino los del ser humano que interactúa.

Programación en Tiempo Real (RTC)

En informática, la programación en tiempo real (RTC) o reactive computing describe sistemas de hardware y software sujetos a una “restricción en tiempo real”, por ejemplo, un evento a una respuesta del sistema. Los programas en tiempo real deben garantizar la respuesta dentro de las limitaciones de tiempo especificadas. A menudo se entiende que las respuestas en tiempo real están en el orden de milisegundos, ya veces microsegundos. Un sistema no especificado como en tiempo real normalmente no puede garantizar una respuesta dentro de un periodo de tiempo, aunque pueden darse tiempos de respuesta reales o esperados.

Un sistema en tiempo real ha sido descrito como aquel que “controla un entorno recibiendo datos, procesándolos y devolviendo los resultados lo suficientemente rápido para afectar el entorno en ese momento”. El término “tiempo real” se utiliza en el control de procesos y sistemas empresariales significa “sin demora significativa”.

El software en tiempo real puede usar:

Con Arduino hacemos una programación en tiempo real recibiendo continuamente datos de los sensores o de los puertos de comunicación, analizandolos y respondiendo al entorno mediante los actuadores o las comunicaciones en un tiempo muy rápido.

Los sistemas operativos en tiempo real (RTOS) son sistemas que responden a la entrada inmediatamente. Se utilizan para tareas tales como la navegación, en las que el ordenador debe reaccionar a un flujo constante de nueva información sin interrupción. La mayoría de los sistemas operativos de uso general no son en tiempo real porque pueden tardar unos segundos, o incluso minutos, en reaccionar.

Implementación de multitarea:

Existen sistemas operativos en tiempo real (RTOS) para Arduino como freeRTOS: http://www.freertos.org/

freeRTOS en Arduino: https://feilipu.me/2015/11/24/arduino_freertos/

Anuncios

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/

Programación Arduino

El lenguaje de programación de Arduino es C++. 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 y muchas utilidades específicas para las MCU AVR de Atmel como avrdude: https://learn.sparkfun.com/tutorials/pocket-avr-programmer-hookup-guide/using-avrdude

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, pero cuando compilamos y cargamos un sketch estamos usando estas herramientas.

Aunque se hable de que hay un lenguaje propio de programación de Arduino, no es cierto, la programación se hace en C++ pero Arduino ofrece unas librerías o core que facilitan la programación de los pines de entrada y salida y de los puertos de comunicación, así como otras librerías para operaciones específicas. El propio IDE ya incluye estas librerías de forma automática y no es necesario declararlas expresamente. Otra diferencia frente a C++ standard es la estructuctura del programa que ya hemos visto anteriormente.

Toda la información para programar Arduino se encuentra en el reference de la web de Arduino: https://www.arduino.cc/en/Reference/HomePage

Lenguaje de programación C++

Es posible usar comandos estándar de C++ en la programación de Arduino siempre que estén incluidos en el avr libc:

Características de C:

  • Es el lenguaje de programación de propósito general asociado al sistema operativo UNIX.
  • Es un lenguaje de medio nivel. Trata con objetos básicos como caracteres, números, etc… también con bits y direcciones de memoria.
  • Posee una gran portabilidad
  • Se utiliza para la programación de sistemas: construcción de intérpretes, compiladores, editores de texto, etc

Un buen libro de referencia para C:

Y un libro que se puede descargar gratuitamente Essential C: http://cslibrary.stanford.edu/101/EssentialC.pdf

Una muy buena plataforma online para aprender C: http://c.learncodethehardway.org/book/

Por supuesto en Internet hay muchas webs de referencia donde consultar dudas a la hora de programar en C++:

C++ es un lenguaje de programación diseñado a mediados de los años 1980 por Bjarne Stroustrup. La intención de su creación fue el extender al exitoso lenguaje de programación C con mecanismos que permitan la manipulación de objetos. En ese sentido, desde el punto de vista de los lenguajes orientados a objetos, el C++ es un lenguaje híbrido.

Posteriormente se añadieron facilidades de programación genérica, que se sumó a los otros dos paradigmas que ya estaban admitidos (programación estructurada y la programación orientada a objetos). Por esto se suele decir que el C++ es un lenguaje de programación multiparadigma. Actualmente existe un estándar, denominado ISO C++.

C# es un lenguaje propietario de Microsoft que mezcla las características básicas de C++ (no las avanzadas) simplificandolas al estilo Java y ofreciendo un framework. C# forma parte de la plataforma .NET

Elementos básicos en la programación de Arduino

Un manual sencillo de entender para la programación es el “arduino programming notebook” de brian w. Evans. Puedes consultarlo o descargarlo desde:

Cuando compilamos y cargamos el programa en Arduino esto es lo que ocurre:

{} entre llaves

Las llaves sirven para definir el principio y el final de un bloque de instrucciones. Se utilizan para los bloques de programación setup(), loop(), if.., etc.

Una llave de apertura “{“ siempre debe ir seguida de una llave de cierre “}”, si no es así el compilador dará errores. El entorno de programación de Arduino incluye una herramienta de gran utilidad para comprobar el total de llaves. Sólo tienes que hacer click en el punto de inserción de una llave abierta e inmediatamente se marca el correspondiente cierre de ese bloque (llave cerrada).

; punto y coma

El punto y coma “;” se utiliza para separar instrucciones en el lenguaje de programación C. También se utiliza para separar elementos en una instrucción de tipo “bucle for”.

Nota: Si olvidáis poner fin a una línea con un punto y coma se producirá en un error de compilación.

/*… */ bloque de comentarios

Los bloques de comentarios, o comentarios multi-línea son áreas de texto ignorados por el programa que se utilizan para las descripciones del código o comentarios que ayudan a comprender el programa. Comienzan con / * y terminan con * / y pueden abarcar varias líneas.

Debido a que los comentarios son ignorados por el compilador y no ocupan espacio en la memoria de Arduino pueden ser utilizados con generosidad.

// línea de comentarios

Una línea de comentario empieza con / / y terminan con la siguiente línea de código. Al igual que los comentarios de bloque, los de línea son ignoradas por el compilador y no ocupan espacio en la memoria. Una línea de comentario se utiliza a menudo después de una instrucción, para proporcionar más información acerca de lo que hace esta o para recordarla más adelante.

A la hora de programar Arduino, es fundamental usar la referencia que disponemos online en http://arduino.cc/en/Reference/HomePage o en la ayuda del IDE de Arduino. Cualquier duda sobre un comando, función, etc… debemos consultar en la referencia de Arduino.

Existe una guía de estilo para escribir código claro de Arduino y que sea fácil de entender. No es obligatorio, pero es una recomendación:

  • Documentar al máximo
  • Usar esquemas
  • Predominar la facilidad de lectura sobre la eficiencia del código
  • Poner el setup() y loop() al principio del programa
  • Usar variables descriptivas
  • Explicar el código al principio
  • Usar identación

Guia de estilo: http://arduino.cc/en/Reference/StyleGuide

También disponemos de varias cheat sheets o chuletas para cuando se empieza a programar:

Una buena guía de estilo de C++: http://informatica.uv.es/iiguia/AED/laboratorio/Estilocpp.pdf

Para documentar nuestros sketchs:

Lenguaje de programación de Arduino, estructura de un programa

Para programar un Arduino, el lenguaje estándar 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 en los microcontroladores AVR de Atmel y muchas funciones específicas para los MCU AVR de Atmel.

avr-binutils, avr-gcc y avr-libc son las herramientas necesarias para programar los microcontroladores AVR de Atmel.

AVR-libc reference manual de Atmel: http://www.atmel.com/webdoc/AVRLibcReferenceManual/index.html

Dispositivos soportados: http://www.atmel.com/webdoc/AVRLibcReferenceManual/index_1supp_devices.html

Webs del proyecto: http://www.nongnu.org/avr-libc/ y http://savannah.nongnu.org/projects/avr-libc/

Tratamiento de la memoria de la MCU por avr-libc: http://www.atmel.com/webdoc/AVRLibcReferenceManual/malloc_1malloc_intro.html

Módulos de avr-libc: http://www.atmel.com/webdoc/AVRLibcReferenceManual/ch20.html

GNU C libc: http://www.gnu.org/software/libc/index.html

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.

Cuando GCC está construido para ejecutarse en un sistema como Linux, Windows o mac OS y generar código para un microcontrolador AVR, entonces se denomina avr-gcc

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.

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

Proyecto GCC: https://gcc.gnu.org/

Pero para programar proyectos de complejidad media, la mayoría de los comandos que necesitemos con Arduino los encontraremos en la referencia de programación de Arduino en el “Arduino Reference”, que es donde debemos recurrir para cualquier duda de programación que surja. Arduino provee de unas librerías que facilitan la programación del microcontrolador. http://arduino.cc/en/Reference/HomePage

El gran éxito de Arduino en parte se debe a que nos permite programar un MCU sin tener que saber todo lo anterior y nos da unas herramientas sencillas y específicas para programar unos 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 lenguaje de programación usado por Arduino está basado en Processing: http://www.gnu.org/software/libc/index.html,  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.

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

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

Processing es útil cuando queremos comunicar Arduino con un ordenador y mostrar datos o guardar datos, pero también podemos usar otros lenguajes de programación como python, .NET o cualquier otro 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 para darnos cuenta en la similitud de los lenguajes: https://processing.org/reference/ y https://processing.org/reference/libraries/serial/

También disponemos de una librería de Arduino dentro de 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, lo que va  a hacer que el código sea diferente. 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/

Como ya hemos visto, la estructura básica del lenguaje de programación de Arduino es bastante simple y se compone de al menos dos partes. Estas dos partes necesarias, o funciones, encierran bloques que contienen declaraciones, estamentos o instrucciones.