Archivo de la etiqueta: bootloader

Memoria Arduino

Arduino y todos los microcontroladores tienen varios tipos de memoria integradas en el mismo chip, 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.

Memorias en Arduino:

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 memorias de Arduino

Para profundizar sobre el uso de memoria en los microcontroladores AVR de Atmel, memoria dinámica, reserva y liberar memoria, visitar los siguientes enlaces:

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 defecto de los registros.

Si vemos a fondo la memoria SRAM de Arduino a partir de la dirección 0x0100:

  • .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.

Más información sobre heap y stack:

Calcular Memoria SRAM Libre

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

Explicación del código:

  • extern en un cualificador de variables que indica al compilador de la existencia de variables globales definidas en otros fichero de cabecera que hemos incluido (#include) y no es necesario definirlas en nuestro fichero.
    extern int x; le dice al compilador que un objeto llamado x de tipo int existe en algún sitio.
  • La función getFreeRam define una nueva variable (llamada NewVariable), que se se almacenará una variable local de una función en la pila (stack). Debido a que el área de memoria de pila crece hacia el heap, la dirección de memoria de esta nueva variable es la última dirección de memoria utilizada por la pila en el momento de llamar a este método.
  • El *__brkval es un puntero a la última dirección de memoria (hacia la pila) utilizado por el heap. No tenemos que preocuparnos acerca de la gestión de __brkval ya que esto se hace internamente.
  • También tenemos que estar seguros de que heap no está vacío, porque entonces __brkval no se puede utilizar (que es un puntero NULL). Si el heap está vacío, entonces usamos __bss_end que es una variable definida internamente, y se almacena en la última parte de la zona de memoria RAM variables de .bss
  • La cantidad de memoria libre de RAM es la diferencia entre las direcciones de memoria usada por la nueva variable newVariable y dirección referenciada por __brkval o la dirección de _bss_end si la zona de heap está vacía.
  • El resultado es el número de bytes en MCUs de 8 bits como en Arduino uno. En el caso de MCUs de 32 bits como el Arduino DUE, que son bloques de 32 bits.

Más información: http://web-engineering.info/node/30

Este código está disponible en la librería: https://github.com/maniacbug/MemoryFree

Y la versión revisada: https://github.com/McNeight/MemoryFree

En el playground de Arduino hay más información sobre el cálculo de memoria disponible: https://playground.arduino.cc/Code/AvailableMemory

Un código más simple de calcular la memoria libre:

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

Códigos para cálculo de memoria libre SRAM

Como medir a memoria libre flash, SRAM y EEPROM: https://learn.adafruit.com/memories-of-an-arduino/measuring-free-memory  

I/O Memory

El espacio de memoria I/O de los registros son un conjunto de registros adiciona a los registros de propósito general.

Los 32 (32x8bits) registros de propósito general están directamente conectados con la ALU.

Todas las I/Os (Inputs/Oputputs) y periféricos están localizados en el espacio de memoria I/O. Todas las localizaciones de los registros I/O pueden ser accedidos mediante las instrucciones LD/LDS/LDD y ST/STS/STD, transfiriendo datos entre los registros de propósito general y el espacio I/O.

Instrucción LDS (Load Direct from Data Space): http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_lds.html

Instrucción SBI (Set Bit in I/O Register): http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_sbi.html

Instrucción CBI (CBI – Clear Bit in I/O Register): http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_CBI.html

Lista de instrucciones en ensamblador:  http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_instruction_list.html

Los registros I/O en el rango 0x00-0x1F son accesible directamente mediante las funciones SBI y CBI.  En estos registros el valor de los bits puede ser leído con las instrucciones SBIS y SBIC.

Memoria Flash

La memoria flash —derivada de las siglas EEPROM— permite la lectura y escritura de múltiples posiciones de memoria en la misma operación. Gracias a ello, la tecnología flash, siempre mediante impulsos eléctricos, permite velocidades de funcionamiento muy superiores frente a la tecnología EEPROM primigenia, que sólo permitía actuar sobre una única celda de memoria en cada operación de programación. Se trata de la tecnología empleada en los dispositivos denominados memoria USB.

Más sobre la memoria flash.

En Arduino la memoria flash o espacio de programa es donde el sketch de arduino en binario es almacenado.

La memoria flash en Arduino está dividida o particionada en dos zonas  una para el bootloader y otra para almacenar el sketch.

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 es un programa que se ejecuta inmediatamente antes de ejecutar el programa que hay en la memoria flash al que cede el control cuando finaliza su ejecución.

Más información sobre el bootloader en: https://aprendiendoarduino.wordpress.com/2016/11/09/bootloader/

Incluso se podría particionar la memoria flash para dejar una zona con un sistema de ficheros donde se podrían almacenar archivos, como ya se hace en algunos casos con el ESP8266.

PROGMEM

PROGMEM se usa para guardar en memoria flash en lugar de en la SRAM y ahorrar espacio en la SRAM, especialmente cuando se usa gran cantidad de cadenas de caracteres. 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 ocuparía un 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). Una desventaja de usar PROGMEM podría ser la velocidad de lectura, que es más lento en comparación con la lectura de los mismos datos de la RAM, aunque la diferencia de velocidad no es mucha.

La verdadera utilidad de PROGMEM es en bloques de datos grandes que necesitan ser almacenados en la flash. El uso de PROGMEM se hace en dos pasos, después de hacer que la variable se guarde en la flash, necesitamos de varios métodos definidos en la librería pgmspace.h, para leer los datos de la flash y cargarlos en la SRAM.

IMPORTANTE: para el uso de PROGMEM, las variables deben ser o bien definidas de forma global o definidas como static.

La sintaxis de uso de PROGMEM es:

 
const dataType variableName[] PROGMEM = {};   // use this form
const PROGMEM  dataType  variableName[] = {}; // or this form
const dataType PROGMEM variableName[] = {};   // not this one

Más información sobre PROGMEM en Arduino:

La macro F() se puede usar para facilitar el manejo de PROGMEM en las instrucciones print, de forma que todo el texto a imprimir (ya sea en Serial, Ethernet u otra librería) se lea de la Flash y no ocupando tamaño en la SRAM. Esta macro está incluida en el core de Arduino.

Cuando un sketch tiene problemas de memoria SRAM, el primer y más sencillo paso a aplicar es poner todos los print con la macro F.

Sintaxis:

 
Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));

Más información sobre la macro F y consideraciones a tener en cuenta al usarla: https://www.baldengineer.com/arduino-f-macro.html

Ver librería Flash que facilita el uso de PROGMEM: http://arduiniana.org/libraries/flash/

Fuses & Lock Bits

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 la MCU, 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 tres bytes que conforman los fuses en el ATMega328p:

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 cambiar la configuración de los fuses, puede usarse el avrdude.Tutorial para cambiar la configuración de los fuses: http://www.instructables.com/id/How-to-change-fuse-bits-of-AVR-Atmega328p-8bit-mic/

Arduino default fuse settings: http://www.codingwithcody.com/2011/06/25/arduino-default-fuse-settings/

Calculadora de Fuses:

Más información:

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.

Función 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); 
}

Paso 1: Calcula memoria RAM y Flash en Arduino UNO de un programa que solo ejecute la función freeRam en el loop cada 30 segundos y muestre el dato por el monitor serie.

Solución Ejercicio14_1: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_Avanzado_2017/tree/master/Ejercicio14-Memoria_1

Paso 2: Calcula memoria RAM y Flash en Arduino UNO de un programa que imprima por el monitor serie en cada loop cada 30 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.”

Solución Ejercicio14_2: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_Avanzado_2017/tree/master/Ejercicio14-Memoria_2

Paso 3: Calcula memoria RAM y Flash en Arduino UNO del programa del paso 2 pero usando la macro F en el Serial.print.

Solución Ejercicio14_3: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_Avanzado_2017/tree/master/Ejercicio14-Memoria_3

Práctica: Velocidad Memoria en Arduino

Hacer un programa para hacer una comparativa de la velocidad de lectura de la memoria SRAM, Flass y EEPROM.

Solución Ejercicio15: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_Avanzado_2017/tree/master/Ejercicio15-Velocidad_Memoria

Para ampliar ver ejercicio de llenar memoria: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Otros/llenarMemoria

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

Cómo conseguir un “Arduino” Gratis

Para conseguir un “Arduino” gratis, se puede recurrir a la opción de solicitar muestras gratuitas a Atmel en http://www.atmel.com/ en el apartado “buy” y luego “request a sample”.

Atmel como el resto de fabricantes de componentes electrónicos disponen de programas de muestras gratuitas que podemos usar para probar sus productos y hacer nuestros prototipos.

Otros fabricantes donde solicitar muestras gratuitas de sus microcontroladores:

Obviamente de esta forma, no vamos a tener un Arduino gratis, sino el microcontrolador que es el principal componente de un Arduino. Para dejar claro qué es un Arduino y qué es un microcontrolador, en esta página del curso #aprendiendoarduino explico qué es Arduino y el hardware libre: https://aprendiendoarduino.wordpress.com/2014/11/23/tema-1-plataforma-hardware-arduino/

Dado que quería testear varios microcontroladores con el IDE de Arduino, pedí varios componentes a Atmel a través de su programa de muestras gratuitas. Estos son los elementos que pedí:

En la imagen siguiente dejo el albarán de lo que llegó a mi casa, donde se puede ver el precio de cada uno de ellos, en concreto el microcontrolador ATmega328P que tiene el Arduino UNO cuesta 1.56 dólares:

albaran

En total pedí 4 microcontroladores de la familia megaAVR de 8 bits: http://www.atmel.com/products/microcontrollers/avr/megaAVR.aspx, un microcontrolador de la familia tinyAVR http://www.atmel.com/products/microcontrollers/avr/tinyavr.aspx y una EEPROM de 512Kb diseñada para almacenar programas de FPGAs pero que quiero tratar de usar como memoria externa.

Centrándonos en los microcontroladores, tanto el ATmega328P como el ATmega168P son soportados de forma nativa por el software de Arduino. Viendo el fichero boards.txt del IDE de Arduino en su versión 1.6, se observa que son varias las placas oficiales de Arduino que tienen estos microcontroladores.

Para el ATtiny85, tenemos que recurrir al playground de Arduino para saber como configurar el IDE de Arduino y poder usarlo con esta MCU. En este enlace está la información necesaria: http://playground.arduino.cc/Main/ArduinoOnOtherAtmelChips. En este otro enlace explica perfectamente como usarlo: http://highlowtech.org/?p=1695 y finalmente en este tutorial explica como programar un ATtiny con el IDE de Arduino: http://www.instructables.com/id/Program-an-ATtiny-with-Arduino/

Los microcontroladores ATtiny son especialmente útiles en pequeñas aplicaciones que no necesiten un gran número de entradas y salidas, en mi caso lo uso para descargar tareas al arduino principal y que sean hechas por el ATtiny comunicándolos por puerto serie o inalámbricamente por RF.

ATtiny dispone de 6 entradas/salidas programables, un interfaz serie, sensor de temperatura integrado on-chip, programación vía puerto SPI, oscilador interno, etc… y sobre todo muy bajo consumo, que lo hace idóneo para aplicaciones con baterías.

Este el el pinout de un ATtiny85:

Para el ATmega88PA, el proceso es similar. En este enlace tenéis toda la información en este enlace: http://www.morethantechnical.com/2012/04/04/bootloading-an-atmega88-for-arduino-w-code/. En este caso tenemos un bootloader para este microcontrolador, basado en el bootloader del ATmega168.

El ATmega88PA es un microcontrolador muy similar al ATmega168PA y al ATmega 328P, compartiendo el mismo mapa de pines pero con solo 8 Kbytes de memoria flash, 1 Kbyte de SRAM y 512 bytes de EEPROM, lo que nos permitirá ponerlo en la placa de un Arduino UNO para poder usarlo.

En el caso  del ATmega32A, este tutorial explica paso a paso como usar el IDE de Arduino con el ATmega32: http://www.instructables.com/id/Using-Atmega32-with-Arduino-IDE/

Este microcontrolador tiene una flash de 32 Kbytes, una frecuencia máxima operativa algo menor que el ATmega328p, pero más pines de entrada y salida que la MCU del Arduino UNO , así como algunas limitaciones de funcionalidad sobre el ATmega328p.

Para más información sobre cómo personalizar el IDE de Arduino para soportar otros microcontroladores, está perfectamente explicado en este enlace: http://playground.arduino.cc/Main/CustomizeArduinoIDE

Por último, en este fantástico tutorial de ladyada, explica como usar avrdude, que en definitiva es el programa que usa el IDE de Arduino para cargar los programas en la flash de los microcontroladores de la familia AVR de Atmel: http://www.ladyada.net/learn/avr/avrdude.html y la web del proyecto avrdude es: http://savannah.nongnu.org/projects/avrdude.

Por lo tanto según el manual de avrdude que puedes encontrar en http://www.nongnu.org/avrdude/user-manual/avrdude.html, los microncontroladores que puedes programar con avrdude y por ende con el IDE de Arduino son los que aparecen en este listado: http://www.nongnu.org/avrdude/user-manual/avrdude_4.html#Option-Descriptions, así como los programadores soportados.

Después de esta explicación sobre varios microcontroladores, veamos los pasos para conseguirlos con el programa de muestras gratuitas de Atmel.

Primero es necesario registrarse en Atmel, obtener un usuario de myAtmel y entrar en el apartado Buy/Request a Sample:

request a sample

Después de esto aparece un listado para buscar las muestras gratuitas que deseamos:

listado samples

Aquí tenemos muchísimas referencias, en este caso para buscar los microcontroladores compatibles con el IDE de arduino, selecciono en part type “MCU AVR”. Aun así las referencias son muchísimas.

Si queremos por ejemplo un ATmega328p que es el microcontrolador que usa el Arduino UNO al poner “328p” en part number, nos salen 12 opciones:

328p

Ahora veamos las diferencias de esos doce part numbers que tiene Atmel para el ATmega328P. Para ello, vamos al apartado “Ordering Information” del documento resumen que ofrece Atmel para el ATmega328P http://www.atmel.com/Images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Summary.pdf y vemos que existen estos doce tipos de microcontroladres ATmega328p:

Ordering Codes

Se divide en dos partes en función de la rango de temperaturas de trabajo y dentro de ellos el tipo de package o formato. Para saber a qué tipo de encapsulado corresponde cada formato, simplemente leer el documento resumen de Atmel anteriormente mencionado a partir de la página 24 donde describe cada uno de ellos.

En estas imágenes también se puede ver algunos de los formatos con otra codificación.

Packaging Range 2

Packaging Range 1

En nuestro caso como queremos un ATmega328P para sustituirlo en nuestra placa de Arduino UNO, necesitamos el formato PDIP-28 o 28DIP o 28P3, que son el mismo formato con diferente nomenclatura, pero en definitiva un formato de 28 pines para poder poner en una protoboard o en un Arduino UNO.

Después de seleccionar el microcontrolador o los elementos que queramos probar, se envía la solicitud (Submit Request) y debemos rellenar un formulario indicando el tipo de aplicación, el equipo final y el cliente final. Además se debe rellenar los detalles del proyecto.

Dejo una captura de pantalla de los datos a rellenar:

Formulario

En mi caso expliqué el proyecto al que iba a destinar el material, en concreto un prototipo para monitorización industrial. Tras enviar el pedido, en unos minutos recibí un email confirmándolo y en menos de 24 horas recibes otro email con el estado del envío y el número de seguimiento del pedido.

En aproximadamente una semana llega el “Arduino”, solo me queda quitar el ATmega328P del Arduino UNO y sustituirlo por este.

ATmega328P

Pero aún nos queda un paso para poder usar este microcontrolador gratuito en el Arduino UNO, se trata de cargar el bootloader.

Lógicamente, los microcontroladores que vende Atmel tiene la flash vacía y si quiero programarlos tan fácilmente como la plataforma Arduino nos permite simplemente conectando a un puerto USB de nuestro ordenador y cargar el código en la flash de la MCU pulsando un botón, necesito que el ATmega328P tenga cargado el bootloader que hace que todo sea mucho más simple.

Para cargar el bootloader y entender mejor porqué es necesario para usar un microcontrolador en el Arduino UNO, lo explico en el apartado de bootloader del curso #aprendiendoarduino https://aprendiendoarduino.wordpress.com/2014/11/17/tema-7-conceptos-avanzados-de-hardware/

Para cargar el bootloader es necesario o bien un programador ISP o bien tener otro Arduino y convertirlo en un programador como muy bien queda explicado en este tutorial: http://arduino.cc/en/pmwiki.php?n=Tutorial/ArduinoISP

Con este artículo no he pretendido solo hacer un paso a paso de como conseguir gratis un microcontrolador como el usado en el Arduino UNO, sino que lo he aprovechado para hablar de otros microcontroladores, intentar explicar un poco mejor que Arduino es una plataforma para programar de forma sencilla MCUs de la familia AVR de Atmel y como programas otros microcontroladores de Atmel con el IDE de Arduino.

Referencias:

 

Tema 7 – Conceptos avanzados de Hardware

  • Diseño HW de un Arduino
  • Esquema lógico de Arduino
  • ICSP
  • Bootloader
  • Interrupciones (próximamente)
  • Microcontroladores. Registros de memoria. (próximamente)
  • Firmware USB to Serial Chip (próximamente)
  • Bit Banging vs Hardware dedicado (próximamente)
  • Conceptos avanzados de electrónica (próximamente)
  • Atmel Studio (próximamente)

Diseño HW de un Arduino

Como vimos anteriormente, Arduino es una plataforma para programar de forma sencilla algunos microcontroladores de la familia AVR de Atmel.

http://es.wikipedia.org/wiki/AVR

Pero además es un entorno de programación para estos microcontroladores, por lo tanto podemos utilizar todo lo aprendido para programar un microcontrolador solo sin necesidad de la plataforma Arduino y montarlo sobre una placa que hayamos hecho para un propósito específico.

Con un microcontrolador AVR y una serie de componentes electrónicos, podemos construir un arduino sobre una protoboard:

Si el microcontrolador no tiene bootloader cargada, entonces necesitaremos cargarlo de alguna forma, ya sea usando otro arduino o mediante hardware externo.

Por ejemplo con https://www.sparkfun.com/products/9716 que nos convierte de USB a serial y con funcionalidad de auto reset cuando un nuevo sketch es cargado al Arduino.

También podemos usar el mini USB adapter: http://arduino.cc/en/Main/MiniUSB

Regulador de tensión usado por el Arduino UNO: http://www.unihedron.com/projects/sqm-le/PDFspecs/NCP1117-D.PDF

Tenemos también el boarduino: https://learn.adafruit.com/boarduino-kits

Para cargar el bootloader en un microcontrolador atmega tenemos dos opciones:

Los pasos a seguir para “quemar” el bootloader están en: http://arduino.cc/en/Main/Standalone

Los pasos para cargar el bootloader desde un Arduino y como cargar un programa en una MCU de Atmel desde Arduino: http://arduino.cc/en/Tutorial/ArduinoToBreadboard

Pin mapping: http://arduino.cc/en/Hacking/PinMapping

Fijaros en el pequeño integrado que hay en la placa de Arduino uno, es un microcontrolador completamente funcional y no solo un conversor de USB a Serial. Podríamos usar ambos MCUs en la misma placa, pudiendo descargar trabajo de la MCU principal en la secundaria. Para ello usa el hoodloader2 en el Atmega16U2 o Atmega8U2 dependiendo de la versión de Arduino Uno que tengamos y comunicamos ambas MCUs por HW serial

Como usar el segundo MCU del Arduino UNO: http://www.freetronics.com/blogs/news/16053025-using-both-microcontrollers-on-your-arduino-uno-compatible-board#.VIg48zGG9B9

Web del proyecto: http://nicohood.wordpress.com/2014/11/30/hoodloader2-ready-to-use-usb-hid-for-arduino-unomega/

HoodLoader2: https://github.com/NicoHood/HoodLoader2

Diferencias entre las diversas versiones de HW de los Arduino: http://startingelectronics.com/articles/arduino/uno-r3-r2-differences/

HW arduino UNO a fondo: https://learn.adafruit.com/arduino-tips-tricks-and-techniques/arduino-uno-faq

Por supuesto si queremos saber más sobre el microcontrolador de Arduino disponemos de toda su documentación en: http://www.atmel.com/Images/doc8161.pdf.

Por ejemplo en la página 434 tenemos los 3 encapsulados posibles.

Y en la página 316 se pueden ver los consumos de Arduino y la dependencia entre la frecuencia máxima de reloj y el Vcc.

No solo debemos centrarnos en la AV· 328P, existen una amplia gama de MCUs de Atmel y de otros fabricantes que son las herramientas SW (IDE, compilador, etc…) adecuadas podemos programar con todo lo visto en el curso.

Familia de Microcontroladores de megaAVR Atmel de la que disponemos a AVR libc para poder programarlos como hemos visto hasta ahora:

Uso avanzado de memoria con AVR libc: http://www.atmel.com/webdoc/AVRLibcReferenceManual/malloc.html

Atmel Xplained son una placas de prototipado al estilo de Arduino fabricado por Atmel para sus MCUs de 8 y 32 bits que necesitan de Atmel Studio para programarlas. http://www.atmel.com/products/microcontrollers/avr/xplained.aspx

Un resumen de como funciona una MCU y como agrgar un programa: http://www.electronicaestudio.com/microcontrolador.htm

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

Para ello necesitamos HW adicional para conectar nuestro ordenador a los cinco pines del In-System Programmer del microcontrolador. Por ejemplo el AVRISP mkII: http://www.digikey.com/product-detail/es/ATAVRISP2/ATAVRISP2-ND/898891 o https://www.sparkfun.com/products/8702

Más información en:  http://upvector.com/atmega/

El proceso en el IDE es el siguiente:

  • source -(compile)-> ELF -(link)-> hex
  • hex -(flash programmer)-> target board

El fichero hex es el formato usado para guardar el lenguaje del MCU codificado en formato hexadecimal. Es el que se transfiere a la RAM.

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.

Operaciones en reloj en Arduino:

  • Internamente, el reloj de entrada es dividido por cuatro.
  • Un ciclo de instrucción equivale a cuatro periodos del reloj de entrada.
  • En Q1, se lee la siguiente instrucción y en Q4 es almacenada en el registro

Captura

En el siguiente ciclo es ejecutada.

Captura

La importancia  de conocer el ciclo de ejecución de instrucciones en un micro controlador estriba en que en ocasiones es necesario calcular de forma precisa el tiempo de ejecución de los bucles para actuar en tiempo real

EEPROM

La EEPROM es una memoria no volátil que dispone el microcontrolador de Arduino que nos permite guardar datos para poder recuperar en caso de pérdida de alimentación de nuestro dispositivo.

La gran desventaja que tiene la EEPROM es que tiene un número limitado de escrituras, por lo que debemos calcular cuántas veces se va a escribir en ella para calcular su vida útil con nuestro programa.

Más información en: http://en.wikipedia.org/wiki/EEPROM

Las celdas de memoria de una EEPROM están constituidas por un transistor MOS, que tiene una compuerta flotante (estructura SAMOS), su estado normal está cortado y la salida proporciona un 1 lógico.

Aunque una EEPROM puede ser leída un número ilimitado de veces, sólo puede ser borrada y reprogramada entre 100.000 y un millón de veces.

Estos dispositivos suelen comunicarse mediante protocolos como I²C, SPI y Microwire. En otras ocasiones, se integra dentro de chips como microcontroladores y DSPs para lograr una mayor rapidez.

La memoria flash es una forma avanzada de EEPROM.

La librería EEPROM nos permite leer y escribir bytes de la EEPROM de Arduino. La EEPROM en cada MCU tiene un tamaño diferente, en nuestro caso con el Arduino UNO es de 1024 bytes. Esta librería solo me permite leer y escribir a nivel de byte, por lo que si quiero guardar variables cuyo tamaño sea mayor de 1 byte, deberemos hacer operaciones.

 Librería http://arduino.cc/en/Reference/EEPROM

Método read() – http://arduino.cc/en/Reference/EEPROMRead

Método write() – http://arduino.cc/en/Reference/EEPROMWrite

Una EEPROM tarde unos 3,3 ms en completar una escritura y para Arduino se ha especificado una vida de 100000 ciclos de escritura/borrado.

Tutorial lectura EEPROM: http://en.wikipedia.org/wiki/EEPROM

Tutorial escritura EEPROM: http://arduino.cc/en/Tutorial/EEPROMWrite

Tutorial limpiado EEPROM: http://arduino.cc/en/Tutorial/EEPROMClear

Para grabar estructuras de datos en la EEPROM. http://playground.arduino.cc/Code/EEPROMWriteAnything

Ver que AVR Libc dispone de métodos de la librería <avr/eeprom.h> para manejar la EEPROM: http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__eeprom.html

La librería EEPROMex es una extensión de la librería EEPROM que amplía sus funcionalidades:

Ejercicio35-EEPROM: Hacer un ejemplo en el que se guarde y luego se lea configuraciones de la EEPROM.

ejemplo: http://playground.arduino.cc/Code/EEPROMLoadAndSaveSettings

struct: http://www.cplusplus.com/doc/tutorial/structures/

Solución: https://github.com/jecrespo

Ejemplo: Como proteger un arduino que queremos comercializar y que no se pueda replicar el programa en otros microcontroladores Atmel.

Un ejemplo es usar una EEPROM externa usado como “mochila” donde guardamos un número único. Este mismo módulo lo podríamos usar como contador o con otras funcionalidades.

Por ejemplo : http://datasheets.maximintegrated.com/en/ds/DS2430A.pdf

Ver como trabajar con ella: http://playground.arduino.cc/Learning/OneWire

Como poner un arduino a dormir: http://playground.arduino.cc/Learning/ArduinoSleepCode

Es posible poner un arduino en un estado de sleep para reducir el consumo en usos con batería, para ello necesita el uso de interrupciones de puerto equipadas en los pines 2 y 3.

Para ello es necesario usar los métodos de la librería avr/power.h:

Ejemplo de uso: http://rubenlaguna.com/wp/2008/10/15/arduino-sleep-mode-waking-up-when-receiving-data-on-the-usart/

Listado muy interesante como comuicar Arduino mediante HW con un montón de dispositivos: http://playground.arduino.cc/Main/InterfacingWithHardware

Arduino at heart or certified program:

http://arduino.cc/en/ArduinoAtHeart/HomePage

¿Puedo fabricar y vender un producto comercial basado en arduino?

Sí­, con las siguientes condiciones:

  • Utilizar una placa Arduino dentro de un producto comercial no requiere que reveles o liberes ninguna de las partes de su diseño.
  • Diseñar un producto comercial a partir de los planos de la placa Arduino requiere que publiques los planos modificados bajo la misma licencia Creative Commons Attribution Share-Alike.
  • Cualquier modificación del núcleo y bibliotecas de Arduino debe ser publicado bajo la LGPL. Pero utilizar el núcleo y las bibliotecas de Arduino para el firmware de un producto comercial no requiere que publiques el código fuente de tu firmware, sólo los ficheros objeto. Así, en caso de actualizaciones del núcleo de  Arduino será posible una recompilación.
  • El código fuente del ambiente Arduino está cubierto bajo la GPL, que requiere que cualquier modificación sea de código libre bajo la misma licencia. No previene la venta de software derivado o su incorporación en productos comerciales.

Más información en: http://arduino.cc/en/Main/FAQ

Esquema lógico de Arduino

Diagrama de bloques de un microcontrolador AVR de Atmel.

Para el caso de un PIC:

Captura

ICSP

ICSP es un método de programar directamente los microcontroladores de AVR, PIC y otros.

Como los microcontroladores suelen ir soldados a las placas, la forma de poder programarlos en mediante el conector ICSP y para programarlos es necesario un HW adicional denominado programador.

El pineado de las señales ICSP cambia en función de cada fabricante y del microcontrolador.:

El conector ICSP tiene dos versiones:

Más información: http://en.wikipedia.org/wiki/In-circuit_serial_programming

ICSP es un conector para programar Arduino consistente en 6 señales: MOSI, MISO, SCK, RESET, VCC, GND.

Frecuentemente nos referimos como SPI, el cual se puede considerar una expansión de la salida, pero realmente ICSP es un “esclavo” del master del bus SPI.

En referencia a los integrados AVR, es la forma que tenemos de programarlos de forma in-system, conectando un programador a estos 6 pines. El programador puede mandar el fichero hex al microcontrolador.

La forma en que programamos Arduino en mediante el puerto serie gracias al bootloader que se comunica con el puerto serie. Al mandar los comandos correctos, lee los datos del puerto serie de Arduino que es convertido a USB por el ATmega8u2 o ATmega16u2 y guarda todos los datos recibidos en la memoria Flash.

Por otro lado la programación ISP primero resetea el Arduino y lo mantiene, mientras el reset esta mantenido Arduino no funciona y ningún programa que tenga. En su lugar el programa codificado en hexadecimal se comunica a través de los pines MOSI (Master Out, Slave In) and MISO (Master In, Slave Out) y temporizándolo con el CLOCK.

Por lo tanto, la programación normal solo funciona con el bootloader y la programación ISP va directamente al HW. Mediante ISP puede cargar cualquier programa, es como si quiere grabar datos en un servidor y lo puede hacer mediante una web que permite hacerlo o grabarlo directamente en el disco duro.

Un ejemplo de como usar ICSP con un PIC: http://tecbolivia.com/index.php/articulos-y-tutoriales-microcontroladores/19-icsp-como-usar-qprogramacion-serial-en-circuitoq-con-microcontroladores-pic

Como usar un programador externo: http://arduino.cc/en/Hacking/Programmer

Ejemplo de programador externo: http://www.pololu.com/product/1300

Construir un programador paralelo: http://arduino.cc/en/Hacking/ParallelProgrammer

Ejemplo: Usar un Arduino como pasarela para programar otro

Bootloader

Cuando cargamos un programa en Arduino, estamos haciendo uso del bootloader, se trata de un pequeño programa que ha sido cargado 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 comenza el sketch que está cargado en la flash de Arduino.

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 Arduino uno viene con el microcontrolador ATmega328 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: 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.

Los MCUs AVR de 8bits atmega con interfaz USB integrado como son el ATmega16U2 y ATmega8U2, vienen de fabrica 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 chip FTDI hace esa mismas función cuando no existe un interfaz USB integrado.

Avrdude es un programa para descargar y cargar las memorias de los 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

Más información sobre Avrdude en: http://www.nongnu.org/avrdude/ y https://omegav.no/wiki/index.php/AVR/avrdude y https://learn.adafruit.com/usbtinyisp/avrdude

Y aquí un manual de AVRdude: http://www.ladyada.net/learn/avr/avrdude.html

Optiboot bootloader: https://code.google.com/p/optiboot/

Auto Reset

Para cargar un nuevo sketch en un microcontrolador, es necesario hacer un reset para parar 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 se 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 todo lo que hay en la flash y luego el bootloader comienza a cargar lo que haya 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: http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection

Más información sobre el reset en Arduino:http://playground.arduino.cc/Main/ArduinoReset

Cargar el bootloader

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). un USBtinyISP (https://learn.adafruit.com/usbtinyisp), un programador parallelo (http://arduino.cc/en/Hacking/ParallelProgrammer) o 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: http://arduino.cc/en/Hacking/Bootloader

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

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, 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.

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

Un programador para AVR: https://www.sparkfun.com/products/9825

Tutorial para cargar el bootloader: https://learn.sparkfun.com/tutorials/installing-an-arduino-bootloader

Un programador ofical de Atmel: http://www.atmel.com/tools/AVRISPMKII.aspx

Y el manual: http://www.atmel.com/webdoc/avrispmkii/index.html

Atmel 328 con bootloader: http://www.adafruit.com/products/123

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

Cómo hacerlo:

Para hacerlo sobre un micro directamente sin Arduino:http://www.open-electronics.org/arduino-isp-in-system-programming-and-stand-alone-circuits/

Solución: https://github.com/jecrespo/Aprendiendo-Arduino