Archivo de la categoría: Avanzado

Itinerario Formación Raspberry Pi

En un acercamiento a esta disciplina, se busca aprender a manejar Raspberry Pi, una placa de desarrollo basada en linux, pero a efectos de todos se trata de un ordenador con linux completo. Así, se presenta el siguiente itinerario con un curso de Iniciación, uno Intermedio y uno avanzado:

Raspberry Pi Iniciación (Nivel 1)20 h
Raspberry Pi Intermedio (Nivel 2)20 h
Raspberry Pi Avanzado (Nivel 3) – EN DESARROLLO20 h

Ver Anexo I con el material necesario para impartir los cursos de este itinerario. 

Raspberry Pi Iniciación (Nivel 1)

Objetivo

El objetivo de este curso es que el alumno obtenga un conocimiento inicial de la placa de desarrollo basada en linux y sea capaz de instalar, configurar y realizar proyectos sencillos.

Toda la documentación del curso y el código usado es libre y accesible desde https://www.aprendiendoarduino.com/.

Al finalizar el curso el alumno será capaz de:

  • Conocer el HW Raspberry Pi
  • Instalar Raspbian
  • Realizar configuraciones básicas
  • Conocer comandos básicos de Linux
  • Saber cuándo Raspberry Pi es una buena solución a un proyecto o idea.
  • Conocer de forma básica es lenguaje de programación Python
  • Aprender a usar el GPIO de Raspberry Pi
  • Manejar sensores y periféricos con Raspberry Pi

Requisitos Alumnos

No son necesarios requisitos previos de los alumnos para asistir a este curso

Contenido del Curso

  • Qué es Raspberry Pi
  • HW Raspberry Pi
  • Tipos de Placas y Hats Raspberry Pi
  • GPIO
  • Instalación Raspbian
  • Conexión a Internet
  • Conceptos básicos de Linux
  • Programación Básica en Python
  • Entradas y Salidas Digitales
  • Manejo de Sensores y periféricos

Raspberry Pi Intermedio (Nivel 2)

Objetivo

El objetivo de este curso es que el alumno con experiencia básica es Raspberry Pi, amplíe y afiance sus conocimientos y sea capaz de configurar servicios y realizar proyectos más complejos.

Toda la documentación del curso y el código usado es libre y accesible desde https://www.aprendiendoarduino.com/.

Al finalizar el curso el alumno será capaz de:

  • Conocer el HW de Raspberry Pi a fondo
  • Configurar servicios en Raspberry Pi
  • Manejar Linux desde consola
  • Realizar programas en Python de cierta dificultad
  • Usar de forma básica otros lenguajes de programación en Raspberry Pi
  • Usar el GPIO de Raspberry Pi con soltura

Requisitos Alumnos

Es necesario tener una experiencia básica en el manejo de Raspberry Pi para asistir a este curso

Contenido del Curso

  • Repaso básico de Raspberry Pi
  • Modelos de Raspberry Pi
  • Instalación y Configuración Raspbian
  • Instalación de Servidores/Servicios en Raspbian
  • Comunicaciones Raspberry Pi
  • Programación Python
  • Uso de puertos serie e I2C en Raspberry Pi
  • Uso de cámara en Raspberry Pi

Itinerario Formación Arduino

Con este escenario, en un acercamiento a esta disciplina, se busca el desarrollo de hardware abierto como Arduino permiten construir dispositivos digitales y dispositivos interactivos para controlar objetos del mundo real. Así, se presenta el siguiente itinerario desde un nivel básico para ir paso a paso profundizando en sus contenidos para luego pasar a otros cursos más específicos como programación o gestión de proyectos:

Arduino Iniciación (Nivel 1)20 h
Arduino Intermedio (Nivel 2)20 h
Programación Arduino (Nivel 3)20 h
Proyectos con Arduino (Nivel 4)20 h
Arduino Avanzado (Nivel 5)20 h

Ver Anexo I con el material necesario para impartir los cursos de este itinerario.

Arduino Iniciación (Nivel 1)

Objetivo

El objetivo de este curso es que el alumno obtenga un conocimiento inicial de la plataforma Arduino y sea capaz de realizar proyectos de dificultad media con cualquiera de las diferentes placas Arduino o compatibles.

Toda la documentación del curso y el código usado es libre y accesible desde https://www.aprendiendoarduino.com/

Al finalizar el curso el alumno será capaz de:

  • Conocer el HW Arduino
  • Manejar la plataforma Arduino
  • Saber cuándo Arduino es una buena solución a un proyecto o idea.
  • Conocer el lenguaje de programación
  • Conocer el potencial de Arduino para usar aplicación sencillas
  • Aprender a usar las entradas analógicas y digitales
  • Aprender a usar las salidas analógicas y digitales
  • Manejar sensores y periféricos con Arduino

Requisitos Alumnos

No son necesarios requisitos previos de los alumnos para asistir a este curso

Contenido del Curso

  • Primeros Pasos con Arduino
  • IDE Arduino
  • Simuladores Arduino
  • Tipos de Placas y Shields Arduino
  • Herramientas de Programación Visual
  • Programación Básica Arduino
  • Componentes Electrónicos
  • Entradas y Salidas Digitales
  • Entradas Analógicas
  • PWM
  • Manejo de Sensores

Arduino Intermedio (Nivel 2)

Objetivo

El objetivo de este curso es que el alumno obtenga un conocimiento intermedio de la plataforma Arduino y sea capaz de realizar proyectos de cierta dificultad con cualquiera de las diferentes placas Arduino o compatibles. Este curso es complemento al curso de Iniciación.

Toda la documentación del curso y el código usado es libre y accesible desde https://www.aprendiendoarduino.com/

Al finalizar el curso el alumno será capaz de:

  • Uso de Memoria en Arduino
  • Manejar librerías Arduino
  • Programar y ejecutar programas en la plataforma Arduino y compatibles
  • Usar eficazmente el entorno de programación
  • Manejar motores y actuadores con Arduino para interactuar
  • Manejar sensores y periféricos complejos
  • Usar comunicaciones serie.

Requisitos Alumnos

Será necesario haber realizado el curso de Iniciación a Arduino o tener unos conocimientos básicos de Arduino..

Contenido del Curso

  • Repaso Arduino Básico
  • Simuladores Arduino
  • Uso de Librerías Arduino
  • Programación Arduino
  • Uso de Memoria en Arduino
  • Manejo de Sensores y periféricos
  • Manejo de Motores 
  • Comunicación Serie
  • Bus I2C
  • Protocolo TCP/IP en Arduino
  • Conexión Arduino a Internet

Curso Programación Arduino (Nivel 3)

Objetivos

El objetivo de este curso es que el alumno aprenda los principales conceptos de la programación de Arduino en particular y por extensión los principios y técnicas de programación general que podrían aplicarse a casi cualquier lenguaje de programación.

Este curso está diseñado para personas que ya conocen Arduino y el mundo de los microcontroladores y la electrónica pero no tienen conocimientos o solo básicos de programación.

Toda la documentación del curso y el código usado es libre y accesible desde https://www.aprendiendoarduino.com/

Al finalizar el curso el alumno será capaz de:

  • Programar Arduino con soltura
  • Uso básico de un sistema de control de versiones
  • Conocer estructuras complejas de programación
  • Manejar y crear librerias Arduino
  • Programas placas y microntroladores compatibles con Arduino
  • Hacer debug de programas
  • Programar comunicaciones serie.

Requisitos Alumnos

Para realizar este curso, el alumno debe haber asistido a alguno de los cursos de iniciación o intermedio de Arduino o tener experiencia en la plataforma de hardware libre Arduino y tener conocimientos básicos de electrónica. 

Contenido del Curso

  • Repaso Conceptos Arduino 
  • Programación Avanzada Arduino
  • Clases y Objetos en Arduino
  • Manejar y Crear Librerias Arduino
  • Comunicaciones Arduino
  • Manejo Avanzado de Strings
  • Multitarea en Arduino

Curso Proyectos Arduino (Nivel 4)

Objetivos

El objetivo de este curso es que el alumno aprenda a realizar proyectos con Arduino y a documentar adecuadamente los proyectos. Aprenderá a usar el entorno de programación utilizado por Arduino, el lenguaje de programación usado, realizar proyectos, ejecutarlos sobre la plataforma y documentarlos.

Toda la documentación del curso y el código usado es libre y accesible desde https://www.aprendiendoarduino.com/

Al finalizar el curso el alumno será capaz de:

  • Diseñar, planificar y ejecutar un proyecto con Arduino
  • Usar eficazmente herramientas de documentación
  • Manejar un sistema de control de versiones
  • Hacer testeo y depuración de errores
  • Programas placas y microcontroladores compatibles con Arduino

Requisitos Alumnos

Para realizar este curso, el alumno debe haber asistido a alguno de los cursos de iniciación o intermedio de Arduino o tener experiencia en la plataforma de hardware libre Arduino y tener conocimientos básicos de electrónica. 

Contenido del Curso

  • Repaso Conceptos Arduino 
  • Primer Proyecto con Arduino
  • Programación Arduino
  • Manejo de Sensores Actuadores y periféricos
  • Planificación y Diseño de Proyectos
  • Documentación de Hardware
  • Documentación del Código y Control de Versiones
  • Testeo y Depuración de Errores
  • Plataformas de Publicación de Proyectos
  • Proyectos Final de Curso.

Curso Arduino Avanzado (Nivel 5)

Objetivo

El objetivo de este curso es ampliar conocimientos sobre la plataforma Arduino para poder abordar proyectos complejos y usar usar otra placas compatibles con Arduino.

Toda la documentación del curso y el código usado es libre y accesible desde https://www.aprendiendoarduino.com/

Al finalizar el curso el alumno será capaz de:

  • Realizar proyectos complejos
  • Conocer la programación de Arduino más allá del core de Arduino
  • Interactuar con el mundo exterior a través de órdenes enviadas desde un ordenador o desde un dispositivo móvil y comunicarse a través de Internet.
  • Crear librerías propias o modificar las existentes para mejorar las funcionalidades.

Requisitos Alumnos

Para la realización de este curso es necesario haber realizado el curso de iniciación de Arduino y el curso de programación o tener conocimientos y experiencia en la creación de proyectos con Arduino. También es necesario conocimientos de programación (especialmente C++), redes TCP/IP y protocolos de comunicación, microcontroladores, electrónica, uso de sensores, actuadores, motores, etc…

Contenido del Curso

  • Repaso Conceptos Básicos Arduino
  • Hardware Avanzado Arduino (Alimentacion, Memoria, I/O Ports, etc…)
  • Programación Avanzada Arduino (Librerías, Clases y Objetos, Punteros, Debug, etc…) 
  • Manejo Avanzado Arduino (Buses, Interrupciones, Watchdog, etc…)
  • Comunicaciones Arduino (Bluetooth, Serie, Ethernet y WiFi.
  • Programación de Placas Compatibles Arduino.

Tratamiento Avanzado de Strings

Como ya se ha visto anteriormente el tratamiento de strings es un parte muy importante en Arduino puesto que se usa muy frecuentemente y principalmente usamos en las comunicaciones, ya sea puerto serie, bluetooth, XBee, http, etc…

El uso de strings hace un uso intensivo de memoria lo que hace que podamos tener comportamientos extraños en los sketchs o incluso tengamos desbordamiento de memoria.

A la hora de usar strings en Arduino, podemos hacer uso de la clase String https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/ que nos ofrece unos métodos y es muy sencilla de usar, a cambio de ser poco eficiente a nivel de SRAM o usar los stringshttps://arduino.cc/reference/en/language/variables/data-types/string/ como arrays de chars https://arduino.cc/reference/en/language/variables/data-types/char/ que es más complejo de manejar pero más potente y tenemos más control del uso de memoria y pueden usarse muchas de las funciones estandard de C++.

String (Objeto)

Arduino nos ofrece una clase llamada String que facilita el uso de de las cadenas de caracteres con unos métodos muy sencillos de usar y poder usar los operadores que conocemos para los Strings.

Se trata de una clase que permite usar y manipular cadenas de texto de una forma más sencilla que los strings. Puedes concatenar, añadir, buscar, etc… usando los métodos/funciones que ofrece esta clase.

Los Strings tienen un uso intensivo de memoria, pero son muy útiles y se van a utilizar mucho en el apartado de comunicación, por ese motivo es importante aprender a manejar los Strings.

Tener en cuenta que al no ser un tipo de dato propiamente dicho sino una clase, tienes unas funciones asociadas (métodos), operadores y unas propiedades. Es una abstracción del dato y para aprender a usarlo hay que leerse la documentación correspondiente.

Toda la información de la clase String está en: https://arduino.cc/reference/en/language/variables/data-types/stringobject/

Ver documentación de Arduino sobre la clase String:

Tutoriales de uso de String:https://arduino.cc/en/Tutorial/BuiltInExamples#strings

Prácticas Manejo de Strings

Ejecutar el ejemplo https://arduino.cc/en/Tutorial/StringLengthTrim donde se hace uso de las funciones length() y trim().

Ejecutar el ejemplo https://arduino.cc/en/Tutorial/StringStartsWithEndsWith donde se hace uso de las funciones StartsWith() y EndsWith().

Ejecutar el ejemplo https://arduino.cc/en/Tutorial/StringSubstring donde se hace uso de la función substring().

Ejecutar el ejemplo https://arduino.cc/en/Tutorial/StringToInt donde se hace uso de la función toInt()

Otra de las funciones más útiles de String es IndexOf() con ejemplos en https://www.arduino.cc/en/Tutorial/StringIndexOf

Ejercicio: Conectarse a www.aprendiendoarduino.com y analizar el texto descargado. El texto descargado es una página web que contiene datos de una música a tocar por el buzzer

Hacerlo usando la clase String.

Obtener y sacar por el puerto serie:

  • Tamaño de la web (número de caracteres)
  • Localizar las cadenas: “Inicio Notas”, “Fin Notas”, “Inicio Duración” y “Fin Duración”
  • Obtener las notas (frecuencia) y la duración de las notas. Luego reproducirlo.

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino/tree/master/Ejercicio16-Strings_Avanzado

string (Array de chars)

Un string es un array de chars. Cuando se trabaja con grandes cantidades de texto, es conveniente usar un array de strings. Puesto que los strings son en si mismo arrays. En el reference de Arduino https://arduino.cc/reference/en/language/variables/data-types/string/

La notación de un string como array de chars es char*

El core de Arduino me ofrece varias funciones de análisis de caracteres: https://arduino.cc/reference/en/language/variables/data-types/string/

Una cadena en C++ es un conjunto de caracteres, o valores de tipo char, terminados con el carácter nulo, es decir el valor numérico 0 (\0). Internamente, en el ordenador, se almacenan en posiciones consecutivas de memoria. Este tipo de estructuras recibe un tratamiento muy especial, ya que es de gran utilidad y su uso es continuo. La manera de definir una cadena es la siguiente: char <identificador> [<longitud máxima>];

Cuando se declara una cadena hay que tener en cuenta que tendremos que reservar una posición para almacenar el carácter nulo terminador, de modo que si queremos almacenar la cadena “HOLA”, tendremos que declarar la cadena como: char Saludo[5]; Las cuatro primeras posiciones se usan para almacenar los caracteres “HOLA” y la posición extra, para el carácter nulo.

También nos será posible hacer referencia a cada uno de los caracteres individuales que componen la cadena, simplemente indicando la posición. Por ejemplo el tercer carácter de nuestra cadena de ejemplo será la ‘L’, podemos hacer referencia a él como Saludo[2].

Se puede manipular las cadenas de caracteres de la misma manera en que manipula cualquier otro tipo de array, sin embargo, es preferible hacer uso de una librería estándar especialmente escrita para manipulación de cadenas de caracteres, se trata de la librería <string.h> y que viene incluida con todo compilador de C, C++.

Reference de C++ para la clase string http://cplusplus.com/reference/string/string/ y http://cplusplus.com/reference/cstring/ con funciones como strcpy para strings null-terminated.

Los compiladores de C, C++ dan soporte a la biblioteca de funciones <string.h>, a la que accede por medio de la directiva #include <string.h>. No veremos en detalle todas las funciones contenidas en dicha biblioteca, y nos limitaremos a mostrar algunos ejemplos de ciertas funciones importantes.

  • strlen(): Obtener longitud de cadenas. Sintaxis: size_t strlen(const char *s);
  • strcpy(): Copiar cadenas. Sintaxis: char *stpcpy(char *dest, const char *src);
  • strcat(): Concatenar cadenas. Sintaxis: char *strcat(char *dest, const char *src);
  • strlwr(): Convertir a minúsculas. Sintaxis: char *strlwr(char *dest);
  • strupr(): Convertir a mayúsculas. Sintaxis: char *strupr(char *dest);
  • strchr(): Buscar carácter (hacia adelante). Sintaxis: char *strchr(char *s, int c);
  • strrchr(): Buscar carácter (hacia atras). Sintaxis: char *strrchr(char *s, int c);
  • strstr(): Buscar subcadena. Sintaxis: char *strstr(const char *s1, char *s2);
  • memset(): Establece el primer num bytes del bloque de memoria apuntado por ptr al valor especificado en value (interpretado como un unsigned char).. Sintaxis: void * memset ( void * ptr, int value, size_t num );

Reference:

En C++ también tenemos soporte a la clase cstring, que no debe confundirse con la <string.h>. Una de las ventajas que ofrece la clase cstring es que, a diferencia de las cadenas estándar, ésta posee la capacidad de crecer o disminuir su tamaño en tiempo de ejecución. Además, entre otras características destacables, la clase string soporta operaciones de asignación tales como: =, +, +=, etc.; y de comparación tales como: ==, <=, etc.

Documentacíon de la librería <string.h>: http://www.cplusplus.com/reference/cstring/

Clase string de C++: http://www.cplusplus.com/reference/string/string/

Ejercicio Strings_vs_strings: Partiendo de la base del ejercicio StringsComparisonOperators intentar hacer las operaciones de comparación de igualdad y distinto de los StringOne y StringTwo con string en lugar de String. Ver como es más complicado y para iniciarse en la programación es mejor usar String (objeto) que string (char array).

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio18-strings/_5-String_vs_string

Más información:

Ejercicios Avanzados  Strings

Ejercicio: Mandar un SMS mediante un módulo SIM800L, donde pido por consola el número y el mensaje en formato” <numero_telefono>-<mensaje>!”. Analizar esta cadena y separar en teléfono y mensaje y mandar mediante la función bool sendSms(char* number,char* text);

El primer análisis hacerlo con la clase String y luego pasar las variables teléfono y mensaje a char* que es lo que pide la librería.

Librería disponible en el gestor de librerías: https://github.com/VittorioEsposito/Sim800L-Arduino-Library-revised

HW: https://es.aliexpress.com/item/SIM800L-V2-0-5V-Wireless-GSM-GPRS-MODULE-Quad-Band-W-Antenna-Cable-Cap/32465895576.html

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio68-toCharArray

Ejercicio: Manejo de JSON mediante la librería disponible en el gestor de librerías ArduinoJson https://arduinojson.org y repositorio https://github.com/bblanchon/ArduinoJson

JSON: https://es.wikipedia.org/wiki/JSON

Abrir el ejemplo JsonParserExample de la librería y probarlo.

PROGMEM

El uso de strings como cadena de caracteres en Arduino, en lugar de usar la clase String, nos permite también almacenar los strings en la memoria flash en lugar de la SRAM gracias a PROGMEM https://arduino.cc/reference/en/language/variables/utilities/progmem/

A menudo es conveniente cuando se trabaja con grandes cantidades de texto, como un proyecto con una pantalla LCD o en comunicaciones, usar PROGMEM con arrays de strings.  Estos tienden a ser grandes estructuras, así que ponerlas en memoria de programa (flash) es a menudo deseable. El código siguiente ilustra la idea.

 
#include <avr/pgmspace.h>
const char string_0[] PROGMEM = "String 0";   // "String 0" etc are strings to store - change to suit.
const char string_1[] PROGMEM = "String 1";
const char string_2[] PROGMEM = "String 2";
const char string_3[] PROGMEM = "String 3";
const char string_4[] PROGMEM = "String 4";
const char string_5[] PROGMEM = "String 5";

// Then set up a table to refer to your strings.

const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};

char buffer[30];    // make sure this is large enough for the largest string it must hold

void setup()
{
  Serial.begin(9600);
  while(!Serial);
  Serial.println("OK");
}

void loop()
{
   for (int i = 0; i < 6; i++)
  {
    strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
    Serial.println(buffer);
    delay( 500 );
  }
}

Utilidades de PROGMEM: https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html

Usar la tabla de cadenas en la memoria de programa (flash) requiere el uso de funciones especiales para recuperar los datos. La función strcpy_P copia un string desde el espacio del programa (flash) en un string en la memoria RAM (“buffer”). Debemos asegurarnos de que la cadena de recepción en la memoria RAM es lo suficientemente grande como para alojar cualquier string que está recuperando desde el espacio del programa

Las funciones para manejar PROGMEM están en http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html que podemos ver son iguales que las de <string.h>, pero seguidas de “_P”

Tener en cuenta que las variables deben ser definidas de forma global y como constantes, o definido con la palabra clave static, con el fin de trabajar con PROGMEM.

Recordar que podemos usar la macro F() junto con el métodos print y println de forma que todo lo que hay dentro de los métodos se guarda en la memoria flash.

Ejemplo: Serial.println(F(“This string will be stored in flash memory”));

Para saber como funciona PROGMEM ver  la pagina 347 y 354 de http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf y donde lo metes lo de MEMPROG

Microcontroladores Arduino a Fondo

Un microcontrolador es un integrado capaz de ser programado desde un ordenador y seguir la secuencia programada.

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 y también microcontroladores Atmel ARM Cortex-M0+ o Intel http://www.intel.com/content/dam/support/us/en/documents/boardsandkits/curie/intel-curie-module-datasheet.pdf, y un hardware con ese MCU donde acceder físicamente a sus puertos.

Pero también Arduino y su entorno de programación se está convirtiendo en un estándar de facto para la programación de cualquier tipo de placas de desarrollo y prototipado, es decir, de otro tipo de microcontroladores no incluidos en los productos de Arduino. Gracias a la comunidad es posible programar otros microcontroladores de ST microelectronics o los ESP8266 y ESP32 de espressif http://espressif.com/ que podemos comprar con placas como la nodeMCU http://nodemcu.com/index_en.html o la bluepill http://wiki.stm32duino.com/index.php?title=Blue_Pill.

Puesto que Arduino es una plataforma open source disponemos de toda la documentación de los microcontroladores usados.

Por ejemplo, el microcontrolador de Arduino UNO es el ATmega328p y toda la documentación la tenemos en http://www.microchip.com/wwwproducts/en/ATmega328p. El data sheet completo es un documento de 442 páginas que podemos ver en http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf. Cuando necesitemos más información o cómo funciona este microcontrolador debemos ir a este documento.

Como muestra de la documentación que tenemos disponible:

  • Página 34 tenemos el detalle de cómo se distribuye la memoria en el ATmega328p
  • Página 97 tiene en detalle los puertos digitales I/O y página 100 donde da el código para definir un pines a high y low y también como input pullup.
  • Página 436 tenemos los 3 encapsulados posibles para este microcontrolador
  • Página 316 nos muestra que este microcontrolador tiene un sensor de temperatura integrado y que es posible habilitarlo para leer su temperatura.
  • Página 378 se pueden ver los consumos de Arduino y la dependencia entre la frecuencia máxima de reloj y el Vcc.
  • Página 428 hay un resumen de todos los registros del microcontrolador y su dirección de memoria.

Cuando el microcontrolador ejecuta una instrucción que definimos en el sketch, internamente hace muchas operaciones y cada una de esas operaciones se ejecuta en un ciclo de reloj. Para el ATmega 328p que tiene una frecuencia de 16 MHz, es decir, cada ciclo tarda 0,0000000625 segundos = 0,0625 microsegundos = 62,5 nanosegundos

Así se ejecutaría una instrucción, en cada ciclo de reloj se ejecuta cada subinstrucción.

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

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

El método para calcular estas tablas está en http://forum.arduino.cc/index.php?topic=200585.0

Diferencia entre los microcontroladores de 8 bits, 16, y 32 bits, es tamaño de palabra que manejan e influye en los registros y direccionamiento de memoria: http://es.wikipedia.org/wiki/Palabra_(inform%C3%A1tica)

Este mismo análisis hecho con el ATmega328P, podemos hacerlo con otros microcontroladores:

Dentro de los microcontroladores, la tendencia es a usar MCUs de 32 bits con arquitectura ARM. La arquitectura ARM es el conjunto de instrucciones de 32 y 64 bits más ampliamente utilizado en unidades producidas. Concebida originalmente por Acorn Computers para su uso en ordenadores personales, los primeros productos basados ​​en ARM eran los Acorn Archimedes, lanzados en 1987.

La relativa simplicidad de los procesadores ARM los hace ideales para aplicaciones de baja potencia. Como resultado, se han convertido en dominante en el mercado de la electrónica móvil e integrada, encarnados en microprocesadores y microcontroladores pequeños, de bajo consumo y relativamente bajo costo. En 2005, alrededor del 98% de los más de mil millones de teléfonos móviles vendidos utilizaban al menos un procesador ARM. Desde 2009, los procesadores ARM son aproximadamente el 90% de todos los procesadores RISC de 32 bits integrados.

La arquitectura ARM es licenciable. Esto significa que el negocio principal de ARM Holdings es la venta de núcleos IP, estas licencias se utilizan para crear microcontroladores y CPUs basados ​​en este núcleo. ARM Cortex M es un grupo de procesadores RISC de 32 bits licenciados por ARM Holdings. La web oficial es http://www.arm.com/products/processors/cortex-m. Además existen otras familias de ARM: https://en.wikipedia.org/wiki/List_of_ARM_microarchitectures

Más información:

Para saber más de microcontroladores, ver estos recursos:

AVR vs PIC:

Esquema lógico de Arduino

El funcionamiento interno de un microcontrolador se puede explicar con un diagrama de bloques o esquema lógico, donde se ven en cada bloque cada unidad interna del microcontrolador y cómo se comunica con el restos de unidades.

Arquitectura de microcontroladores: http://sistdig.wikidot.com/wiki:arquitectura

Diagrama de bloques simplificado de un microcontrolador. Se compone de tres bloques fundamentales: la CPU ( central Processing Unit), memoria (RAM y ROM) y las entrada y salidas. Los bloques se conectan entre sí mediante grupos de líneas eléctricas denominadas buses o pistas. Los buses pueden ser de direcciones (si transportan direcciones de memoria o entrada y salida), de datos (si transportan datos o instrucciones) o de control (si transportan señales de control diversas). La CPU es el cerebro central del microprocesador y actúa bajo control del programa almacenado en la memoria. La CPU se ocupa básicamente de traer las instrucciones del programa desde la memoria, interpretarlas y hacer que se ejecuten. La CPU también incluye los circuitos para realizar operaciones aritméticas y lógicas elementales con los datos binarios, en la denominada Unidad Aritmética y Lógica (ALU: Aritmetic and Logic Unit).

Diagramas de bloques de un microcontrolador PIC:

Diagrama de bloques de un microcontrolador AVR de Atmel, incluido el ATmega328p:

El sistema de reloj determina la velocidad de trabajo del microcontrolador. Con 16 MHZ se ejecuta una instrucción en 62,5 nanosegundos (1/16 Mhz), correspondiente a 1 ciclo de máquina. El microcontrolador tiene diferentes opciones de circuito de reloj tal como lo muestra la siguiente imagen:

En un registro interno del microcontrolador se encuentran 5 opciones diferentes de reloj que son seleccionadas por medio de un Multiplexor. De este multiplexor sale la señal de reloj, la cual pasa a través de un prescaler, este prescaler se puede utilizar para reducir la frecuencia, reducir el consumo de energía y mejorar la estabilidad de la señal de reloj.El factor del prescaler va de 1 a 256, en potencias de 2. En Arduino, por defecto está desactivado, por consiguiente trabaja a la frecuencia del oscilador externo.

La señal de reloj es distribuida por la unidad de control a los diferentes bloques existentes: la CPU, las memorias, los módulos de entrada/salida, los contadores/timers, el SPI y la USART, al igual que el conversor Análogo Digital ADC.

El microcontrolador ATmega328  tiene tres timers (timer 0, timer 1, timer 2) que también se pueden usar como contadores. Los timers 0 y 2 son de 8 bits y el timer 1 de 16. Estos timers tienen un módulo de preescalado para su propia señal de reloj que puede provenir de su sistema de reloj interno o por pines externos (modo contador).

Son módulos que funcionan en paralelo a la CPU y de forma independiente a ella. El funcionamiento básico consiste en aumentar el valor del registro del contador al ritmo que marca su señal de reloj.

Usando el reloj interno o un cristal externo puede ser utilizado para medir tiempos puesto que utiliza una señal periódica, precisa y de frecuencia conocida; mientras que si la señal viene de un pin externo puede contar eventos que se produzcan en el exterior y que se reflejen en cambios de nivel de tensión de los pines.

Estos contadores también forman parte del generador de señales PWM y permiten configurar tanto la frecuencia como el ciclo de trabajo.

Registros de memoria

Todos los microcontroladores tienen un conjunto de instrucciones que suele ser un conjunto pequeño al tratarse de arquitectura RISC. La CPU cuenta con ese número de instrucciones que sabe ejecutar.

El conjunto de instrucciones para los microcontroladores Atmel de 8 bits es: http://www.atmel.com/Images/Atmel-0856-AVR-Instruction-Set-Manual.pdf

En el caso del ATmega328p, tiene una arquitectura RISC con 131 instrucciones, la mayoría de ellas ejecutadas en un solo ciclo de reloj.

Más información sobre la ALU del Atmega328p en la página 25 de http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf  

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 directamente y de forma más rápida.

Trabajar con registros de memoria puede ser difícil si sólo se escribe un programa en lenguaje ensamblador. Al utilizar el lenguaje de programación de alto nivel como es C basta con escribir el nombre del registro y su dirección de memoria, a partir de esa información, el compilador selecciona el registro necesario. Las instrucciones apropiadas para la selección del registro serán incorporadas en el código durante el proceso de la compilación.

Más información: https://en.wikipedia.org/wiki/Processor_register

La memoria RAM en el ATmega328p se divide en varias partes, todos los grupos de registros se ponen a cero al apagar la fuente de alimentación. La SRAM del 328p se distribuye de la siguiente forma:

Las primeras 32 localizaciones de la memoria son el fichero de registros (Register File). Las siguientes 64 localizaciones de memoria es la standard I/O memory y después las 160 siguientes localizaciones son la Extended I/O memory. Por último las siguientes 2K localizaciones son la memoria interna SRAM.

Las 5 diferentes modos de direccionamiento para los datos de memoria son:

  • Direct – The direct addressing reaches the entire data space.
  • Indirect with Displacement – The Indirect with Displacement mode reaches 63 address locations from the base address given by the Y- or Z-register.
  • Indirect – In the Register File, registers R26 to R31 feature the indirect addressing pointer registers.
  • Indirect with Pre-decrement – The address registers X, Y, and Z are decremented.
  • Indirect with Post-increment – The address registers X, Y, and Z are incremented.

Los 32 registros de propósito general, los 64 I/O Registers, los 160 Extended I/O Registers y los 2K bytes de SRAM interna en el dispositivo son todos accesibles mediante estos modos de direccionamiento.

Los registros de propósito general se utilizan para almacenar los datos temporales y los resultados creados durante el funcionamiento de la ALU. Los 32 General Purpose Working Registers están directamente conectados a la ALU, permitiendo ser accedidos dos registros de forma independiente en una sola instrucción ejecutada en un ciclo de reloj.

Seis de los 32 registros de propósito general pueden ser usados como 3 punteros de registros de 16-bit de acceso indirecto para direccionamiento del espacio de datos, habilitando cálculos eficientes de direcciones. Uno de estos punteros de dirección puede ser usado como un puntero de dirección para búsqueda en las memoria Flash del microcontrolador. Estos registros con funciones añadidas con los registros de 16-bit X-, Y- y Z-. Más información en la página 28 de http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf

Para más información ver página 35 de http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf

Los I/O registers localizados en las direcciones 0x20 a 0xFF, a diferencia de los registros de propósito general, su propósito es predeterminado durante el proceso de fabricación y no se pueden cambiar. Como los bits están conectados a los circuitos particulares en el chip (convertidor A/D, módulo de comunicación serial, etc), cualquier cambio de su contenido afecta directamente al funcionamiento del microcontrolador o de alguno de los circuitos. Esta es la forma en que a bajo nivel se interactúa por ejemplo con los pines del microcontrolador.

Un resumen de todos los registros I/O del ATmega328p se puede ver en la página 428 de http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf

Registros para:

Más información sobre registros y su uso en:

Práctica: Registros Arduino

Veamos algunos valores de los registros de Arduino con el sketch ShowInfo de http://playground.arduino.cc/Main/ShowInfo

Este sketch dispone de un menú que nos permite hacer varias operaciones, pulsar opción i (Show Information) y t (Timer Register Dump) para ver datos de los registros.

Este sketch es bastante complejo pero puede servir como plantilla cuando queramos acceder desde un sketch a un registro concreto.

Algunos detalles del sketch:

Solución Ejercicio 05: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_Avanzado_2017/tree/master/Ejercicio05-showInfo

Práctica: Temperatura Interna Microcontrolador

La mayoría de los nuevos chips AVR (utilizados en el Arduino) tiene un sensor de temperatura interno. No suele utilizarse, ya que no es exacta. Sin embargo, hay varias situaciones en las que se puede utilizar este sensor.

La temperatura interna es la temperatura dentro del chip, al igual que la temperatura de la CPU de un ordenador. Si el Arduino no está durmiendo, esta temperatura aumentará. Si los pines de salida se utilizan para dar corriente (por ejemplo encender leds) la temperatura interna aumenta más. Esta temperatura no puede usarse para medir la temperatura ambiente.

En situaciones con altas temperaturas una lectura de temperatura calibrada podría evitar daños. La mayoría de los chips AVR más recientes tienen un rango de temperatura de hasta 85 grados Celsius. Esta funcionalidad podría utilizarse para apagarse a 80 grados Celsius.

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

Ejecutar el sketch leer y entender lo que hace y probarlo. Comparar con otros Arduinos y calibrar.

Ver en la página 306 y 316 de la documentación del microcontrolador: http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf

La función GetTemp() es la que calcula la temperatura. Para ello configura la referencia interna del conversor analógico digital y lo habilita. Luego lee el dato del ADC mediante el registro ADCW y hace el cálculo para obtener la temperatura.

Como el offset puede variar de una MCU a otra, para calibrar, lo mejor es leer la temperatura de una placa fría y comparar con la temperatura exterior.

Solución Ejercicio 06: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_Avanzado_2017/tree/master/Ejercicio06-InternalTemperature

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/