Archivo por años: 2016

Entradas y Salidas Arduino

La mayoría de los pines de los microcontroladores son multipropósito, es decir, en función de su configuración se comportan de una forma u otra, tal y como se muestra en la figura.

El ATmega328p como cualquier otro microcontrolador tiene registros, algunos de estos registros están relacionados con los puertos de entrada/salida, cada puerto tiene un nombre específico y sus registros asociados, de hecho, el 328p tiene el puerto B, C y D, y cada puerto un diferente número de pines (Esta es una restricción del paquete de 28 pines PDIP y no desde el microcontrolador, ya que un PDIP 40 pines, por ejemplo, tiene 4 puertos con los 8 bits cada uno), el único puerto que tiene el total de sus 8 pines de entradas/salidas es PORTD.

Cada pin puede tener múltiples funciones, como la generación de PWM, o las capacidades de ADC, los pines 6 y 7 del PORTB son los pines de entrada para el oscilador de cristal, y pin 6 del PORTC le corresponde al botón de reinicio.  En esta imagen se puede ver todas las funciones alternativas que cada pin puede tener.

Entradas y Salidas Digitales a Fondo

Para interactuar con los pines digitales de Arduino ya conocemos las funciones que nos ofrece Arduino en https://www.arduino.cc/en/Tutorial/DigitalPins como digitalRead() y digitalWrite().

Pero a bajo nivel estas funciones están manejando registros. Para empezar hay un registro dedicado para cada puerto que define si cada pin es una entrada o una salida, que es el registro de DDRX, donde x es la letra del puerto que queremos configurar, en el caso de la Arduino hay DDRB, DDRC y DDRD. Como toda variable lógica, cada bit en los registros DDRX puede ser 1 ó 0, poner un bit específico de DDRX a 1 configura el pin como salida y ponerla a 0 configura el pin como una entrada.

Los pines usados en la placa Arduino poseen tres puertos en el caso de ATmega328p (Arduino Uno):

  • B (pines digitales del 8 al 13)
  • C (entradas analógicas)
  • D (pines digitales del 0 al 7)

El Arduino Mega presenta varios puertos B,C,D,E,F, etc.

Cada puerto es controlado por tres registros, los cuales también están definidos como variables en el lenguaje del Arduino.

  • El registro DDR, determina si el pin es una entrada o una salida (1 salida, 0 entrada).
  • El registro PORT controla si el pin está en nivel alto (1) o en nivel bajo (0).
  • El registro PIN permite leer el estado de un pin. (solo lectura)

Cada bit de estos registros corresponden con un solo pin; por ejemplo el bit menos significativo de los registros DDRB, PORTB, y PINB hace referencia al pin PB0 (pin digital 8)

Dentro de la avr-libc tenemos un fichero de definición de los registros para cada microcontrolador. Estos fichero se pueden encontrar en la ruta: C:\Program Files (x86)\Arduino\hardware\tools\avr\avr\include\avr

Para ATmega328p ver el fichero iom328p.h donde se encuentran las definiciones para el microcontrolador. Ver que las direcciones de los registros van desplazados 0x20 posiciones de memoria por los registros de propósito general.

Probar con este código (Ejercicio 59):

void setup() {
  //PORTD maps to Arduino digital pins 0 to 7
  pinMode(2, INPUT_PULLUP);
  pinMode(3, OUTPUT);
  digitalWrite(3, HIGH);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, OUTPUT);
  digitalWrite(5, HIGH);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, OUTPUT);
  digitalWrite(7, HIGH);
  Serial.begin(9600);
}
void loop() {
  Serial.println("PIND - The Port D Input Pins Register. Lectura INPUT");
  Serial.println(PIND, DEC);
  Serial.println(PIND, HEX);
  Serial.println(PIND, BIN);
  Serial.println("DDRD - The Port D Data Direction Register. DDRX 1 OUTPUT 0 INPUT");
  Serial.println(DDRD, DEC);
  Serial.println(DDRD, HEX);
  Serial.println(DDRD, BIN);
  Serial.println("PORTD - The Port D Data Register. Escritura OUTPUT");
  Serial.println(PORTD, DEC);
  Serial.println(PORTD, HEX);
  Serial.println(PORTD, BIN);
  delay(10000);
}

El fichero <avr/sfr_defs.h> está incluido en todos los ficheros <avr/ioxxxx.h> que usan unas macros definidas en sfr_defs.h que hacen que los special function registers parezcan variables de C a las que podemos llamar para obtener su valor:

#define PORTA   _SFR_IO8(0x02)
#define EEAR    _SFR_IO16(0x21)
#define UDR0    _SFR_MEM8(0xC6)
#define TCNT3   _SFR_MEM16(0x94)
#define CANIDT  _SFR_MEM32(0xF0)

Referencia de <avr/sfr_defs.h> Special Function Registers:

Las limitaciones eléctricas en el microcontrolador son por puerto y por pin:

Un ejemplo que configura pines 0,1,2,3 como entradas digitales y los pines 4,5,6,7 como salidas digitales: DDRD = 0b11110000; y todos los pin como salidas: DDRD = 0b11111111;

Al utilizar Registros DDR tenemos la ventaja de que con solo una instrucción podemos declarar el pin como entrada o salida, sin embargo con pinMode() necesitaríamos 8 instrucciones.

Ya podemos decir al Atmega cómo serán utilizados sus pines, pero queremos saber cómo leer y escribir datos en dichos pines, de modo que para escribir datos en un determinado puerto, se utiliza el registro PORTx, éste es fácil de recordar, donde x es el nombre del puerto, y después de la configuración de un pin como salida es sólo una cuestión de poner 0 o 1 en el registro PORTx para controlar que el pin de este en estado alta o baja.

Un ejemplo sería:

DDRD = 0b11111111; // Todos los pines de PORTD son salidas.
PORTD = 0b11111111; // Todos los pines de PORTD están en estado alto.
DDRD = 0b11111111; // Todos los pines de PORTD son salidas.
PORTD = 0b00000000; // Todos los pines de PORTD están estado bajo.

Se debe tener cuidado cuando se utiliza PORTD y el puerto serie porque los pines 0 y 1 del PORTD son los utilizados por la USART y si se pone estos dos como entradas o salidas, la USART será incapaz de leer o escribir datos en los pines. Este es un ejemplo de cuidado que se debe tener al usar esta programación en lugar de la capa de programación que nos ofrece Arduino.

Para leer en el pin y poder leer los datos de los sensores o cuando se pulsa un botón de un pin digital configurado como entrada, vamos a utilizar un tercer registro llamado PINX, donde de nuevo x es el nombre del puerto donde se encuentra el pin, así que primero con DDRX decimos al microcontrolador que queremos algunos pines como entradas digitales, y luego usando PINX leemos sus valores

Ejemplo:

DDRD = 0b00000000; // Todos los pines del PORTD son entradas
char my_var = 0; // variable para guardar la información leída en PORTD
my_var = PIND; // Lee PORTD y pone la información en la variable

Es casi tan fácil como puede ser usar el digitalWrite o digitalRead de Arduino, pero con acceso directo al puerto se puede ahorrar espacio en el la memoria flash y también puede ganar mucha velocidad, porque las funciones Arduino puede tomar más de 40 ciclos de reloj para leer o escribir un solo bit en un puerto, además para leer un solo bit el código es bastante complejo con un montón de líneas que ocupan por lo menos unos 40 bytes, que podría ser un pequeño ahorro en flash y es un gran paso para acelerar cualquier programa.

No es normal que se necesite leer o escribir en un puerto completo en cada momento, por ejemplo, si queremos encender un LED, o leer un botón sólo tendrá que utilizar un pin, y escribir todos los bits uno a uno cada vez que queremos cambiar un valor en un puerto, es una tarea aburrida, pero la librería C de AVR tiene algunas pocas palabras definidas como Px(0..7), donde x es de nuevo el puerto que desea utilizar y 0..7 es el valor del pin individual de dicho puerto, por lo que para iluminar un LED debemos hacer algo como esto:

DDRD = (1<<PD2); // Configura el pin 2 de PORTD como salida.
PORTD = (1<<PD2); // El pin 2 de PORTD tiene ahora un valor lógico 1.

La operación << es un operador binario que desplaza hacia la izquierda el número de posiciones especificadas.

Para leer el estado de un botón:

DDRD = 0b11111101; //Configura pin 1 de PORTD como entrada y el resto salida
char my_var = 0; //Variable para guardar la información leída en PORTD
my_var = (PIND & (1<<PD1)); /* Le el pin 1 de PORTD y lo coloca en la variable. */

Explicación de la operación binaria bit a bit: https://www.arduino.cc/en/Reference/Bitshift

También se puede utilizar la macro Px0..7 varias veces en una misma instrucción, por ejemplo, en este código, se ejecutará algo de código sólo si se pulsa dos botones al mismo tiempo:

DDRD = 0b11111100; // Los pines 0 y 1 de PORTD son entradas, y el resto salidas.
if (PIND & ((1<<PD0) | (1<<PD1))) {
/* Algún código dentro del if() que se ejecutará solo si los dos botones se
  encuentran activados. */
}

Ver ejemplo Leer_pin en https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio59-Puertos_Digitales/

Mediante los registros también podemos controlar las resistencias internas de pullup. Cuando hay un botón que puede tener dos estados, uno es desconectado, y cuando se presiona hará una conexión entre los pines del microcontrolador y permite por ejemplo, conectarse a masa, pero cuando se desconecta, no hay nada que fuerce un valor estable en el pin de entrada, y el pin puede leer 1 ó 0 ya que el pin es muy sensible al ruido electromagnético, como una pequeña antena. Se puede resolver este problema de dos maneras similares, una es para conectar una resistencia de 10 Kohms o más entre el Vcc (+5 v) y el pin de entrada, o usar los pull-ups del microcontrolador que tienen integrados, también hace más simples los circuitos.

Para habilitar las resistencias pullup tenemos que hacer algo que puede resultar un poco extraño, no existe un registro dedicado para activar o desactivar el pull-ups, estos son activados o desactivados escribiendo 1 o 0 respectivamente en el registro PORTx cuando el registro DDRX se configuran como entradas. Ejemplo:

DDRD = 0b00000000; // Todos los pines de PORTD son entradas.
PORTD = 0b00001111; // Habilito las Pull-ups de los pines 0,1,2 y 3
char my_var = 0; // Creo una variable para guardar la información leída en PORTD.
my_var = PIND; // Leo PORTD y colocó la información en la variable.

Si se ejecuta este código, sin tener nada conectado a PORTD, los cuatro bits más altos de la variable my_var puede ser 0 ó 1, cualquier combinación posible de ellos porque son flotantes (actúan como pequeñas antenas), pero los cuatro bits más bajos leerá todos un 1 debido a que el pull-ups imponen una señal de 5V débil que se lee como un valor lógico 1.

En un sentido básico esto es todo lo que se necesita saber para dominar la manipulación directa de los puertos. La manipulación de bits enseña cosas más ingeniosas como las máscaras de bits, las operaciones AND, OR, NOT y XOR y cómo configurar y limpiar los bits en un registro y algunos buenos trucos con los operaciones de desplazamiento derecho e izquierdo, todas cosas bueno a saber, ya que puede acelerar un sketch y son muy útiles cuando se utilizan los puertos digitales.

Debemos ser conscientes de que un botón no da una buena y transición limpia entre 0 a 1 o de 1 a 0, pero en su lugar la señal puede tener problemas de rebote, esto es debido a las propiedades mecánicas del botón y no un defecto de diseño. Hay dos maneras, mediante un condensador pequeño cerca de la botón para el rebote del valor, o que esta eliminación de rebotes esté en el mismo código, que es más fácil de hacer cuando tenemos un montón de botones y es más barato que la adición de una gran cantidad de componentes a nuestro circuito. La forma más simple de de hacer esto es sólo insertar un pequeño retraso entre las consecutivas lecturas de un botón, esto es un método de bloqueo, porque el microcontrolador se detendrá por algunos milisegundos, hay otras formas más inteligentes que usar temporizadores, pero para proyectos de 2 ó 3 botones que no requieren una sincronización muy precisa se trata de una método de uso común. 

Ventajas y Desventajas que nos ofrece al utilizar los registros:

  • Desventajas:
    • El código es mucho más difícil de depurar y mantener, y es mucho más difícil de entender. Solo lleva algunos microsegundos al procesador ejecutar código, pero podría llevar horas descubrir por qué no funciona y arreglarlo.
    • Es mucho más fácil causar mal funcionamiento no intencionado usando el acceso directo a un puerto. Con DDRD = B11111110, el pin 0 se debe dejar como una entrada. El pin 0 la línea de recepción (RX) en el puerto serial. Podría ser muy fácil causar el puerto serial deje de funcionar por cambiar el pin 0 a una salida.
  • Ventajas:
    • Se puede cambiar los pines de estado muy rápido, en fracciones de microsegundos. Las funciones digitalRead() y digitalWrite() se componen cada una de ellas de cerca de una docena de líneas de código, lo cual se convierte en unas cuantas instrucciones máquina.
    • Cada instrucción máquina necesita un ciclo de reloj a 16MHz, lo cual puede sumar mucho tiempo en aplicaciones muy dependientes del tiempo. El Registro PORT (Puerto) puede hacer el mismo trabajo en muchos menos ciclos de trabajo.
    • Algunas veces necesitamos configurar muchos pines exactamente al mismo tiempo. Por lo que usar las funciones digitalWrite (10,HIGH), seguida de la función digitalWrite (11,HIGH), causará que el pin 10 se ponga en nivel alto varios microsegundos después que el pin 11, lo cual puede confundir circuitos digitales conectados al Arduino, cuyo funcionamiento dependa del tiempo preciso del cambio de esos bits.
    • Si te estás quedando sin memoria, se pueden usar estos trucos para hacer que tu código sea más pequeño. Usando este método se necesitan muchos menos bytes de código compilado que si se hace un bucle para que se vaya cambiando cada pin uno por uno.

En las librerías podemos ver que usan la manipulación de registros en lugar de las instrucciones que nos ofrece el core de Arduino lo que las hace más rápidas.

Más información en:

Ejercicio Entradas y Salidas Digitales

Ver ejercicio simple con los registros PORT, PIN y DDR y sacarlos por pantalla.

Ejercicio Registros_PORT_simple y leer_pin de https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio59-Puertos_Digitales/

Para demostrar que la operación digitalRead() es lenta hacer un ejercicio que lea 1000, 10000 y 100000 veces el puerto 9 configurado como entrada, mediante digitalRead() y mediante PIND y saque el tiempo que ha costado cada operación.

Solución: ejercicio Velocidad_Read de https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio59-Puertos_Digitales/

Entradas y Salidas Analógicas a Fondo

Ya hemos visto cómo manejar con registros las entradas y salidas de Arduino, pero nos centrado en las digitales. Para el caso de las entradas y salidas analógicas hay algunos detalles adicionales que no se han visto. La forma de manejar con registros las entradas analógicas correspondientes al puerto C con POR y PIN es para usar esos pines como I/O digitales, puesto que los pines de los microcontroladores son multipropósito como se ha dicho anteriormente.

En las entradas analógicas entran en juego los conversores Analógico Digital (ADC) y en las salidas analógicas entra el PWM que usa uno de los timers de microcontrolador para hacer la forma de onda PWM.

Toda la información de ADC para entradas analógicas se encuentra en la página 305 y la información de PWM para salidas analógicas está en la página 125, 149 y 189 de http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf

PWM

Las Salidas PWM (Pulse Width Modulation) permiten generar salidas analógicas desde pines digitales. Arduino Uno no posee salidas analógicas puras. El arduino due, posee dos salidas analógicas puras mediante dos conversores digital a analógico. Estos pines pueden usarse para crear salidas de audio usando la librería correspondiente.

Definición de PWM en la web de Arduino: http://arduino.cc/en/Tutorial/PWM

La modulación por ancho de pulsos (también conocida como PWM, siglas en inglés de pulse-width modulation) de una señal o fuente de energía es una técnica en la que se modifica el ciclo de trabajo de una señal periódica (una senoidal o una cuadrada, por ejemplo), ya sea para transmitir información a través de un canal de comunicaciones o para controlar la cantidad de energía que se envía a una carga.

El ciclo de trabajo de una señal periódica es el ancho relativo de su parte positiva en relación con el período. duty cycle = (tiempo que la salida está a uno o HIGH)/ (periodo de la función)

En Arduino la frecuencia de PWM es de 500Hz. Pero es un valor que puede modificarse en caso que lo necesitemos.

PWM tiene varios usos en los microcontroladores:

  • Dimming un LED
  • Obtener una salida analógica
  • Ofrecer un voltaje analógico entre el 0% y el 100% de Vcc
  • Generar señales de audio
  • Controlar velocidad de motores
  • Generar una señal modulada, por ejemplo para manejar un LED infrarrojo de un mando a distancia.

Para generar la señal PWM se utiliza los timers configurándose varias formas de trabajo. La forma de onda PWM, en el modo de trabajo más sencillo (Fast PWM), se genera de la  forma mostrada en la siguiente gráfica:

  1. El registro del contador se pone en marcha desde cero y cuenta de modo ascendente. En el momento de empezar la cuenta se activa el pin de salida del PWM.
  2. Cuando el valor de este registro se iguala al de otro registro de comparación se conmuta el pin de salida. El registro del contador sigue contando en forma normal.
  3. Cuando el valor del registro del contador llega al final (TOP) vuelve a comenzar (BOTTOM). El pin de salida vuelve a cambiar.
  4. El tiempo que tarda el contador en llegar al final fija el periodo de la señal.

Los microcontroladores usan varios modos de PWM, uno de ellos el el Fast PWM que puede ser generado con 8, 9 y 10 bits, una resolución mayor de 8 bits solo es posible usando un timer de 16 bits. Otro modo de PWM es Phase Correct PWM que es el que debería usarse para el control de motores. Otro modo es Frequency and Phase Correct PWM.

Esta imagen explica cómo funciona el phase correct PWM, en este caso el timer cuenta hacia arriba y luego hacia abajo:

En los microcontroladores AVR, el PWM está disponible con todos los timers. Timer 0 y timer 2 dan una resolución de 8 bit mientras que el timer 1 ofrece una resolución de 16 bits. Con 8 bits hay 256 pasos individuales y en 16 bit hay una resolución de 65536 pasos.

La forma de generar la onda PWM es diferente en cada uno de los modos y la señal obtenida es diferente.

Puesto que las ondas generadas son diferentes, el centro de la parte en HIGH no es constante en el fast PWM y sí en el phase correct PWM, esa es la principal diferencia entre ambos modos y la razón de porque para control de motores es mejor usar el phase correct PWM.

El modo PWM en el AVR se controla por hardware. Esto significa que todo, se lleva a cabo por la CPU AVR. Todo lo que necesita hacer es inicializar e iniciar el temporizador, y establecer el ciclo de trabajo. El ATmega328p tiene 3 timers PWM para controlar 6 salidas PWM. Estos temporizadores generan interrupciones cuando alcanzan el overflow o cuando alcanzan el registro de comparación. Los registros de control del timer/counter n (n va de 0  a 2) son TCCRnA y TCCRnB y tienen los principales controles de los temporizadores.

Estos registros tienen varios grupos de bits:

  • Waveform Generation Mode bits (WGM): these control the overall mode of the timer. (These bits are split between TCCRnA and TCCRnB.)
  • Clock Select bits (CS): these control the clock prescaler
  • Compare Match Output A Mode bits (COMnA): these enable/disable/invert output A
  • Compare Match Output B Mode bits (COMnB): these enable/disable/invert output B

Los registros de comparación de salida OCRnA y OCRnB establece los niveles en los que las salidas A y B se verán afectados. Cuando el valor del temporizador coincide con el valor del registro, la salida correspondiente será modificado como se especifica en el modo.

TCCR0B – Timer/counter0 Control Register

Los registros para el control de PWM  con el timer 0 son TCCR0A y TCCR0B y dentro de ellos los bits WGM02, WGM01 y WGM00:

Para utilizar fast PWM rápido dos modos para elegir, los modos 3 y 7, la principal diferencia entre estos dos modos es que en el modo 3 TOP se fija en 0xFF y en el modo de 7 TOP es definido por el registro TOP, esto significa que si existe la necesidad, podemos cambiar el número máximo que el temporizador hará hasta que haga overflow, así que esto significa que podemos controlar la frecuencia y el ciclo de trabajo.

Más información sobre PWM:

Para cambiar la frecuencia de PWM que por defecto en Arduino UNO está a 500 HZ, se puede usar la función definida en http://playground.arduino.cc/Code/PwmFrequency, donde indicando el pin y el divisor de frecuencia. Esta función cambia los registros TCCRnB en el timer correspondiente en función del pin, con el divisor que queramos.

O simplemente en el setup() del sketch inicializar los bits CS00, CS01 y CS02 como se indica en este enlace: https://arduino-info.wikispaces.com/Arduino-PWM-Frequency, pero teniendo en cuenta que estos cambios en los timers 0, 1 y 2 puede tener efectos en otras funciones que usen los timers como delay(), millis() o la librería servo:

  • Changes on pins 3, 5, 6, or 11 may cause the delay() and millis() functions to stop working. Other timing-related functions may also be affected.
  • Changes on pins 9 or 10 will cause the Servo library to function incorrectly.

La frecuencia resultante de PWM es la resultante de la división de la frecuencia base entre el divisor.

  • The base frequency for pins 3, 9, 10, and 11 is 31250 Hz.
  • The base frequency for pins 5 and 6 is 62500 Hz.
  • The divisors available on pins 5, 6, 9 and 10 are: 1, 8, 64, 256, and 1024.
  • The divisors available on pins 3 and 11 are: 1, 8, 32, 64, 128, 256, and 1024.

También se puede hacer PWM en todos los pins, programando nosotros en lugar de dejarlo a la CPU del microcontrolador: http://playground.arduino.cc/Main/PWMallPins

ADC

El microcontrolador de Arduino UNO contiene en la placa un conversor analógico a digital de 6 canales. El conversor tiene una resolución de 10 bits, devolviendo enteros entre 0 y 1023. Los pines analógicos de Arduino también tienen todas las funcionalidades de los pines digitales. Por lo tanto, si necesitamos más pines digitales podemos usar los pines analógicos.

En arduino los pines analógicos se definen y tienen las propiedades siguientes: http://arduino.cc/en/Tutorial/AnalogInputPins

El datasheet de ATmega advierte de hacer lecturas rápidas entre pines analógicos (analogRead). Esto puede causar ruido eléctrico e introducir jitter en el sistema analógico. Se aconseja que después de manipular pines analógicos (en modo digital), añadir un pequeño retraso antes de usar analogRead () para leer otros pines analógicos.

Un microcontrolador solo entiende señales digitales (1’s y 0’s), por lo tanto para poder leer señales analógicas necesitamos los convertidores Analógico a Digital (ADC). Esta conversión consiste en la transcripción de señales analógicas en señal digital, con el propósito de facilitar su procesamiento (codificación, compresión, etcétera) y hacer la señal resultante (digital) más inmune al ruido y otras interferencias a las que son más sensibles las señales analógicas.

Para el ATMega328p toda la información del conversor analógico a digital se encuentra en la página 305 de http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf

El ATMega328p, al igual que toda la gama ATMega de Atmel y otros microcontroladores, tienen un ADC integrado y no necesita ningún hardware adicional, esto nos permite simplemente conectar un sensor analógico. El ADC interno del microcontrolador tiene una resolución de 10 bits, esto significa que la tensión analógica de entrada se convierte en un valor numérico entre 0 y 1023.

Aunque el ATmega328P tiene 6 pines que son capaces de ser utilizados como pines de entrada analógicos (Port C), sólo hay un ADC en el microcontrolador, pero entre el ADC y los pines hay un multiplexor analógico, esto permite que podamos elegir qué pin está conectado al ADC, esto significa que aunque podemos utilizar todos los pines, sólo se puede leer el valor de uno de ellos a la vez, para casi todas las aplicaciones esto es más que suficiente, pero en algunos casos limitados que necesitan lecturas ADC de alta velocidad se podría necesitar el uso de ADC externos. En el caso de la ATmega328P los pines que se pueden utilizar una entrada analógica son todos los del puerto C.

También se puede cambiar la tensión máxima (siempre por debajo de Vcc) que utiliza el ADC, es la  llamada tensión de referencia y es la tensión contra la que todas las entradas analógicas hacen las conversiones. Esta tensión de referencia se toma del pin Aref. Reducir el voltaje máximo del ADC tiene sentido para mejorar la resolución del ADC. Con 5V la resolución es de 5/1023 = 4,88 mV para cada valor, pero para un sensor que no pasa de 3.3V la resolución es de 3.3/1023 = 3.22mV.

El ADC interno también se puede utilizar en un modo de 8 bits, donde sólo se utilizan los 8 bits más significativos de la resolución de 10 bits completa, esto podría ser útil cuando se trabaja en ambientes ruidosos y sólo necesita 8 bits de resolución, el uso de este modo es un plus debido a que no es necesario dedicar más tiempo de CPU calculando los 10 bits completos. El ADC también puede configurarse para que lleve a cabo una conversión y detenerse o puede ser configurado para funcionar en un modo de funcionamiento libre, la primera opción es la mejor opción cuando queremos leer diferentes pines, y el segundo es mejor cuando sólo tenemos que leer un pin y esto puede ahorrar algo de tiempo entre las conversiones.

También tenemos que tener cuidado de la frecuencia máxima de trabajo del ADC, este valor se especifica en la ficha técnica y es de 200 kHz, este es el valor del reloj interno de la circuitería del ADC y se genera dividiendo el reloj principal ATmega, que en el caso del UNO es 16 MHz, este divisor del reloj se realiza mediante pre-escaladores y sólo hay un rango limitado de valores, por lo que la frecuencia máxima que podemos utilizar y estar dentro de la frecuencia máxima de trabajo es 125 kHz. El siguiente pre-escalador supone usar el ADC a 250 kHz, en este caso no se puede garantizar la resolución de 10 bits, pero si una resolución de 8 bits. De todas formas en caso de necesitar un ADC más rápido se podría usar uno externo.

El ADC puede trabajar en dos modos: single conversion mode y free running mode. En modo single conversion el ADC hace una sola conversión y para, pero en modo free running el ADC está continuamente convirtiendo, es decir, hace una conversión y luego comienza con la siguiente.

El ADC en microcontroladores AVR utiliza una técnica conocida como aproximación sucesiva mediante la comparación de la tensión de entrada con la mitad de la tensión de referencia generada internamente. La comparación continúa dividiendo de nuevo la tensión y actualizando cada bit del registro ADC a 1 si el voltaje es HIGH en la comparación o 0 en el otro caso. Este proceso tiene dura 10 veces (por cada bit de resolución del ADC) y genera como resultado la salida binaria.

Los registros utilizados en el manejo de las entradas analógicas son:

  • ADMUX: ADC Multiplexer Selection Register. Selector del canal del multiplexor del ADC y el voltaje de referencia.
  • ADCSRA: ADC Control and Status Register A. Control del ADC y su estado.
  • ADCSRB: ADC Control and Status Register B.
  • ADCL: ADC Data Register Low. Cuando la conversión ADC ha finalizado, el resultado se deja en estos dos registros.
  • ADCH: Data Register High
  • DIDR0: Digital Input Disable Register 0. Para deshabilitar la entrada digital de los pines analógicos.

Más información:

Otros IDEs

La forma habitual de trabajar con Arduino es usar el propio entorno de programación de Arduino, por su sencillez y facilidad de uso. Ya hemos visto anteriormente y con bastante detalle como es el IDE de Arduino, como instalarlo y como configurarlo:

Pero es posible que por unas razones u otras queramos usar otro IDE, para ello vamos a plantear varias opciones.

Arduino Create

Además del IDE original, los creadores de Arduino están trabajando en un IDE on-line llamado Arduino Create.

Es un IDE online que actualmente está accesible desde https://create.arduino.cc/.

Un IDE online te permite tener siempre la versión actualizada del propio IDE, librerías y cores de las MCUs, así como guardar online los sketches en la nube.

Más información de Arduino Create:

Para usarlo es necesario usar un agente e instalarlo en el ordenador. Código fuente del agente: https://github.com/arduino/arduino-create-agent

Además el entorno de Arduino Create no solo tiene un IDE online, sino que también está disponible el “Arduino Project Hub” https://create.arduino.cc/projecthub apoyado por la plataforma https://www.hackster.io/ donde podemos encontrar proyectos de Arduino.

También en el entorno Arduino create hay una plataforma para IoT https://create.arduino.cc/iot/ con una herramienta para conectar dispositivos  a la nube llamada Arduino Cloud https://create.arduino.cc/iot/ que aun está en beta.

Arduino Studio

Por su parte arduino.org también está trabajando en un rediseño desde cero del clásico IDE llamado Arduino Studio.

Es un nuevo entorno de desarrollo open source, se encuentra en versión Alpha. Es totalmente diferente al IDE original y creado desde cero. Está escrito en Javascript y basado en Brackets: http://brackets.io/  

De momento es una versión en prueba, pero habrá que seguir su evolución. Su filosofía es: “Just one editor for all the environments”

Esta imagen define la estrategia de arduino.org en cuanto a los IDEs:

Con la nueva unificación de arduino.org y arduino.cc, veremos si estos IDEs se unifican.

Herramientas de desarrollo e IDEs no oficiales

Notepad++

El IDE de arduino es muy sencillo y fácil de manejar, pero cuando los proyectos se hacen más complejos, es posible que necesitemos algo más.

El IDE de Arduino no es el único entorno de trabajo ni posiblemente tampoco sea el mejor aunque sea una herramienta muy buena.

Una herramienta de programación es notepad++ sencilla y alternativa al IDE de Arduino. Es una herramienta muy interesante por los complementos que tiene.

Además podemos añadir al uso de notepad++ las herramientas avr-gcc y avrdude para compilar y cargar el sketch en Arduino, e incluso el uso de makefiles.

Ejercicio: Instalacion de notepad++ y complementos

Pasos:

  • Instalar notepad++
  • Instalar los complementos: compare y narduino.
  • Activar la opción de autocompletar.
  • Ejecutar los programas de notepad++ con el IDE de Arduino.

Enlaces:

Sublime Text

Otra opción al Arduino (IDE) es el famoso editor Sublime Text.

Web oficial: https://www.sublimetext.com/

Uso de Sublime Text con Arduino: http://panamahitek.com/sublime-text-y-stino-una-opcion-para-programar-en-arduino/

Si se usa sublime, hay un astyle formattter para C y C++: https://github.com/timonwong/SublimeAStyleFormatter

Eclipse

Eclipse es uno de los IDE más utilizados y conocidos en el mundo y también podemos usarlo para trabajar con Arduino, solo recomendado para usuarios avanzados.

Web oficial: https://eclipse.org/

Uso de eclipse:

Para más información: http://playground.arduino.cc/Code/Eclipse

Sloeber

Se trata de una versión de Eclipse paquetizada para usar con Arduino totalmente libre.

Web oficial: http://www.baeyens.it/eclipse/

Visual Micro

Visual Micro, es una extensión o plugin para microsoft Visual Studio y Atmel Studio

Otros IDEs

Interesante, como programar Arduino desde Android: http://www.instructables.com/id/Program-your-Arduino-with-a-Android-device/

Y más alternativas en http://playground.arduino.cc/Main/DevelopmentTools

Artículos con más alternativas al IDE de Arduino:

ICSP

En resumidas cuentas, el núcleo de cualquier placa Arduino se compone simplemente de un microcontrolador AVR. En el caso de la placa Arduino UNO, su microcontrolador es el ATMega328.

Conforme uno se va adentrando en el mundo de Arduino y los proyectos se vayan haciendo cada vez más grandes y complicados, puede presentarse la necesidad de recurrir al uso de un segundo microcontrolador, para lo cual, es mejor conseguir un microcontrolador AVR por separado puesto que es mucho más barato y/o rentable que volver a comprar una nueva placa Arduino.

Un inconveniente de comprar un nuevo microcontrolador AVR es que éste vendrá de fábrica completamente “limpio” (sin ningún programa cargado), como consecuencia, habrá que grabar por primera vez el Bootloader (Gestor de arranque) para que éste pueda cargar y hacer funcionar los sketches programados con el software de Arduino.

La placa Arduino posee una entrada ICSP (In Chip Serial Programmer) que tiene acceso a la memoria de programa del AVR (Flash), ésto es, que puede grabar directamente desde el PC al microcontrolador cualquier programa sin usar el puerto USB. Uno de ellos, el mismo Bootloader de Arduino.

Programación serial en circuito (ICSP por las siglas del inglés : In-Circuit Serial Programming), es la habilidad de algunos dispositivos lógicos programables, microcontroladores y otros circuitos electrónicos, de ser programados mientras están instalados en un sistema completo, en lugar de requerir que el chip sea programado antes de ser instalado dentro del sistema.

Típicamente, los chips que soportan ISP tienen circuitería interna que les permite generar el voltaje de programación necesario desde la línea de alimentación convencional y comunicarse con el dispositivo programador mediante un protocolo serie. Muchos dispositivos lógicos programables usan una variante del protocolo JTAG para el ISP, esto es para facilitar la integración con procedimientos de prueba automatizada. Otros dispositivos usan protocolos propietarios o protocolos definidos por antiguos estándares.

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

En el caso de ATMega328p:

En el caso de Arduino va al conector:

Estos pines sirven para la programación del ATMEGA328P-PU a través del puerto serie, de ahí las siglas ICSP (In Circuit Serial Programming), se utilizan para grabar el bootloader en el microcontrolador o modificar el programa a través de este puerto sin necesidad de sacarlo del zócalo. El bootloader ya viene grabado de fábrica en este microcontrolador. Podemos identificar el pin1 del ISCP en la placa fijándonos el pequeño punto blanco que está grabado sobre ella, ese punto nos indica que se trata del pin número 1, igual ocurre en los chips, microcontroladores y otros circuitos integrados.

El conector ICSP tiene dos versiones:

Más información:

Pero no solo se puede programar Arduino mediante USB o como acabamos de ver por el puerto ICSP, sino que también es posible hacerlo mediante un cable FTDI conectado al puerto serie de Arduino. Este tema se explicará profundamente en siguientes capítulos.

ICSP es un conector consistente en 6 señales: MOSI, MISO, SCK, RESET, VCC, GND y además de ser un puerto para programar Arduino, también es el conector de expansión del bus SPI mediante el que también podemos comunicar periféricos y es usado en algunos casos para comunicar Arduino con los shields. Se puede considerar el ICSP como un “esclavo” del master del bus SPI del microcontrolador.

En referencia a los microcontroladores AVR, el ICSP es la forma que tenemos de programarlos de forma in-system, conectando un programador a estos 6 pines. El programador manda el fichero hex ya compilador al microcontrolador mediante un protocolo concreto como puede ser el STK500.

La forma en que programamos Arduino generalmente es mediante el puerto serie gracias al bootloader cargado en el microcontrolador que se comunica con el puerto serie para copiar el fichero compilado en la flash. 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 este motivo necesitamos un bootloader para programar Arduino a través del USB.

Por otro lado la programación ISP primero resetea el Arduino y lo mantiene, mientras el reset está mantenido Arduino no funciona y ningún programa que tenga. En su lugar el programa codificado en hexadecimal se transmite a través de los pines MOSI (Master Out, Slave In) and MISO (Master In, Slave Out) y temporizado con el CLOCK. por lo tanto en este caso no necesitamos del bootloader.

Más información: http://www.vwlowen.co.uk/arduino/icsp/page3.htm

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

En el caso de usar un programador externo en lugar de USB para cargar un sketch, el procedimiento es el mismo pero seleccionando el programador adecuado en el IDE.

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

En la ruta C:\Program Files (x86)\Arduino\hardware\arduino\avr\programmers.txt, tenemos la configuración de los programadores que podemos usar con el IDE de Arduino. En este fichero se especifica la comunicación, protocolo, herramienta y parámetros. Esto sirve para decir al la herramienta de programación avrdude qué parámetros usar para cargar el programa.

Ejemplo de uso de un Arduino nano como programador ISP: http://www.martyncurrey.com/arduino-nano-as-an-isp-programmer/

HW Arduino a Fondo

Los Arduino y en general los microcontroladores tienen puertos de entrada y salida y de comunicación. En Arduino podemos acceder a esos puertos a través de los pines.

Otro aspecto importante es la memoria, Arduino tiene tres tipos de memoria:

  • SRAM: donde Arduino 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 o apagado. Las EEPROMs tienen un número limitado de lecturas/escrituras, tener en cuenta a la hora de usarla.
  • Flash: Memoria de programa. Usualmente desde 1 Kb a 4 Mb (controladores de familias grandes). Donde se guarda el sketch.

Más información en:

Placa Arduino Uno a fondo:

Especificaciones detalladas de Arduino UNO: http://arduino.cc/en/Main/ArduinoBoardUno

Microcontroller & USB-to-serial converter ATmega328P & Atmega16U2
Operating Voltage 5V
Input Voltage (recommended) 7-12V
Input Voltage (limits) 6-20V
Digital I/O Pins 14 (of which 6 provide PWM output)
Analog Input Pins 6
DC Current per I/O Pin 40 mA
DC Current for 3.3V Pin 50 mA
Flash Memory 32 KB (ATmega328) of which 0.5 KB used by bootloader
SRAM 2 KB (ATmega328)
EEPROM 1 KB (ATmega328)
Clock Speed 16 MHz

Veamos todos los componentes del Arduino UNO:

Pin mapping Arduino UNO:

Componentes en la placa:

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

Componentes:

  • No necesita de un cable FTDI para conectarse al MCU, en su lugar uso una MCU ATMEGA16U2 especialmente programado para trabajar como conversor de USB a serie.
  • Alimentación: vía USB, batería o adaptador AC/DC a 5V, seleccionado automáticamente. Arduino puede trabajar entre 6 y 20V, pero es recomendado trabajar entre 7 y 12V por las características del regulador de tensión.
  • Puerto Serie en los pines 0 y 1.
  • Interrupciones externas en los pines 2 y 3.
  • Built-in LED en el pin 13.
  • Bus TWI o I2C en los pines A4 y A5 etiquetados como SDA y SCL o pines específicos
  • El MCU ATmega328P tiene un bootloader precargado que permite cargar en la memoria flash el nuevo programa o sketch sin necesidad de un HW externo.
  • Fusible rearmable de intensidad máxima 500mA. Aunque la mayoría de pc’s ya ofrecen protección interna se incorpora un fusible con la intención de proteger tanto la placa Arduino como el bus USB de sobrecargas y cortocircuitos. Si circula una intensidad mayor a 500mA por el bus USB(Intensidad máxima de funcionamiento), el fusible salta rompiendo la conexión de la alimentación.
  • Regulador de voltaje LP2985 de 5V a 3.3V que proporciona una corriente de alimentación máxima de 150 mA.
  • Regulador de voltaje NCP1117 que proporciona un valor estable de 5V a la placa y soporta por encima de 1 A de corriente. Datasheet:  http://www.onsemi.com/pub_link/Collateral/NCP1117-D.PDF
  • ATMEGA16U2 => Es el chip encargado de convertir la comunicación del puerto USB a serie.
  • Condensadores de 47µF de capacidad
  • Diodo M7 en la entrada de alimentación de la placa. Con este diodo conseguimos establecer el sentido de circulación de la intensidad, de esta forma si se produce una contracorriente debido a la apertura de un relé u otros mecanismos eléctricos, el diodo bloquea dicha corriente impidiendo que afecte a la fuente de alimentación.
  • DFU-ICSP. Puerto ICSP para el microcontrolador ATMEGA16U2, como en el caso del ATMEGA328P-PU se emplea para comunicarnos con el microcontrolador por el serial, para reflashearlo con el bootloader, hacer algunas modificaciones, ponerlo en modo DFU, etc..
  • JP2. Pines libres del ATMEGA16U2, dos entradas y dos salidas para futuras ampliaciones.
  • Encapsulados de resistencias.
  • RESET-EN: Significa Reset enabled o reset habilitado. Está habilitado el auto-reset, para deshabilitar por cualquier tipo de seguridad (por ejemplo un proyecto que tenemos funcionando y no queremos que nadie lo reinicie al conectar un USB y detecte un stream de datos) debemos desoldar los pads RESET-EN y limpiarlos de forma que estén aislados el uno del otro.
  • Cristal oscilador de 16MHz necesario para el funcionamiento del reloj del microcontrolador ATMEGA16U2.
  • Resonador cerámico de 16 Mhz para el microcontrolador ATMEGA328P-PU. Los resonadores cerámicos son menos precisos que los cristales osciladores, pero para el caso hace perfectamente la función y ahorramos bastante espacio en la placa. Se trata del pequeño, porque el cristal grande es para el 16U2

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

Más información:

MCU ATmega16u2 en Arduino

Si nos fijamos en el pequeño integrado que hay en la placa de Arduino UNO junto al conector USB, se trata de un ATmega16u2 cuya misión es dar el interfaz USB al Arduino UNO y comunicar los datos con el ATmega328p mediante el puerto serie. Se podría usar como microcontrolador completamente funcional y no solo un conversor de USB a Serial con ciertas modificaciones. Podríamos usar ambas 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

atmega16u2

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

Esquemático Arduino UNO

En este pdf podemos ver el esquema de un Arduino UNO, muy importante conocerlo para evitar hacer maniobras que lo dañen: http://arduino.cc/en/uploads/Main/Arduino_Uno_Rev3-schematic.pdf

Los dos microcontroladores:

Partes del esquemático:

Conexión de los puertos serie de loas os MCUs de un Arduino UNO

También es importante conocer cómo están distribuidos los pines del MCU en Arduino:

Para saber todo sobre el HW de Arduino ver este tutorial donde desglosa todo el HW de Arduino para construir un Arduino UNO desde cero y crear tu propio clon: https://rheingoldheavy.com/category/education/fundamentals/arduino-from-scratch-series/

Diseño PCB Arduino

La placa de Arduino:

Están disponible los esquemas y diseño en formato Eagle para Arduino UNO en http://arduino.cc/en/uploads/Main/arduino_Uno_Rev3-02-TH.zip. Por supuesto para el resto de Arduinos también disponemos de sus diseños de PCB.

Para ver los esquemas podemos usar Eagle, se trata de un programa de diseño de diagramas y PCBs con autoenrutador:

La versión freeware de Eagle es perfecta para diseños pequeños y sencillos, se trata de una licencia para uso no comercial y gratuita para todos. La versión freeware tienen todas las funcionalidades de la versión de pago pero tiene ciertas limitaciones:

  • El área de la placa está limitada a 100 x 80 mm
  • Solo pueden usarse dos capas (Top y Bottom)
  • El editor del esquemático solo puede tener dos hojas.
  • Soporte solo disponible vía email o foro
  • Su uso está limitado a aplicaciones no comerciales o para evaluación
  • Se puede cargar, ver e imprimir diseños que superen esos límites.

Una opción opensource para diseño de PCB es kicad: http://kicad-pcb.org/

Microcontroladores Arduino

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+, Intel http://www.intel.com/content/dam/support/us/en/documents/boardsandkits/curie/intel-curie-module-datasheet.pdf y con la aparición de arduino.org también microcontroladores de ST microelectronics.

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.

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

Por ejemplo, el microcontroaldor de Arduino UNO es el ATmega 328p y toda la documentación la tenemos en http://www.atmel.com/devices/atmega328p.aspx. El data sheet completo es un documento de 444 páginas que podemos ver en http://www.atmel.com/Images/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, al igual que los procesadores de nuestros ordenadores.
  • 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 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.

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 resonador 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://www.atmel.com/Images/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:

ram-map

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.

The 32 general purpose working registers, 64 I/O Registers, 160 Extended I/O Registers, and the 2K bytes of internal data SRAM in the device are all accessible through all these addressing modes.

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.

Six of the 32 registers can be used as three 16-bit indirect address register pointers for Data Space addressing – enabling efficient address calculations. One of the these address pointers can also be used as an address pointer for look up tables in Flash program memory. These added function registers are the 16-bit X-, Y-, and Z-register. 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

register-file

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

All I/O locations may be accessed by the LD/LDS/LDD and ST/STS/STD instructions, transferring data between the 32 general purpose working registers and the I/O space. I/O Registers within the address range 0x00-0x1F are directly bit-accessible using the SBI and CBI instructions. In these registers, the value of single bits can be checked by using the SBIS and SBIC instructions

Los I/O registers localizados en las direcciones 0x20 a 0xFF y 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:

Ejercicio: 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.

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio58-Manipular_Registros

La mayoría de los nuevos chips AVR (utilizados en el Arduino) tienen 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. El Arduino 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

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio58-Manipular_Registros

Microcontrolador vs Microprocesador

Diferencia principal entre un microcontrolador (Arduino) y un microprocesador (Raspberry Pi) son las capacidades de entradas y salidas, así como el rendimiento de la CPU.

Analogía: Arduino es un Autómata programable, Raspberry Pi es un Ordenador, así que a la hora de decidirse que utilizar para un proyecto pensar que usaríamos un autómata o un Ordenador.

Un resumen de como funciona una MCU y como agregar un programa: http://www.electronicaestudio.com/microcontrolador.htm que es diferente a como funciona un microprocesador como los que tenemos en nuestro ordenador o portatil.

Para programación en tiempo real el HW a utilizar es el Arduino, para programación intensiva con gran cantidad de datos usaríamos una Raspberry Pi o un PC.

En un proyecto grande la elección es usar ambos, cada uno en la tarea que mejor hace. Por ejemplo, la recolección de datos, supervisión del entorno, envío de alarmas, accionar motores, etc.. lo dejaremos para el arduino, el tratamiento de los datos recogidos, el interfaz gráfico de usuario, envío de correos, etc… lo dejaremos para un ordenador o una raspberry pi o similar.

Diferencias entre el microprocesador y el microcontrolador, características al usarlos en la implementación de sistemas digitales programables:

  • CPU
  • Memorias RAM y ROM
  • Velocidad de Operación
  • Tamaño
  • Costes
  • Interferencias (ruido)
  • Tiempo de desarrollo

El uso de una u otra tecnología depende del fin que se espera, pues debido a sus características propias, los microcontroladores y los microprocesadores pueden adquirir variados y diferentes espacios de implementación, por ejemplo, los microprocesadores se han desarrollado fundamentalmente orientados al mercado de los ordenadores personales y las estaciones de trabajo, pues allí se requiere una elevada potencia de cálculo, el manejo de gran cantidad de memoria y una gran velocidad de procesamiento. Mientras que los microcontroladores están concebidos fundamentalmente para ser utilizados en aplicaciones puntuales, es decir, aplicaciones donde el microcontrolador debe realizar un pequeño número de tareas, al menor costo posible. En estas aplicaciones el microcontrolador ejecuta un programa almacenado permanentemente en su memoria, el cual trabaja con algunos datos almacenados temporalmente e interactúa con el exterior a través de las líneas de entrada y salida de que dispone.

Microprocesadores Microcontroladores
CPU El microprocesador tiene mucha más potencia de cálculo, por lo cual solamente realiza sus funciones con lo que tiene (datos) y su algoritmo o programa establecida. Es una de sus partes principales, la cual se encarga de dirigir sus operaciones.
Memorias RAM y ROM Son dispositivos externos que lo complementan para su óptimo funcionamiento. Las incluye en un solo circuito integrado.
Velocidad de Operación Rápida Lenta en comparación con la de un microprocesador
Tamaño La configuración mínima básica de un Microprocesador está constituida por un Microprocesador, una memoria RAM, una memoria ROM, un decodificador de direcciones, lo cual lo convierte en un circuito bastante engorroso. El Microcontrolador incluye todo estos elementos en un solo Circuito Integrado por lo que implica una gran ventaja en varios factores,  como por ejemplo, la disminución en el tamaño del circuito impreso por la reducción de los circuitos externos.
Costos Para el Microprocesador, el costo es muy alto en la actualidad. El costo para un sistema basado en Microcontrolador es mucho menor.
Interferencias Son más susceptibles a la interferencia electromagnética debido a su tamaño y a su cableado externo que lo hace más propenso al ruido. El alto nivel de integración reduce los niveles de interferencia electromagnética
Tiempo de desarrollo El tiempo de desarrollo de un microprocesador es lento. Por el contrario, el de un microcontrolador es rápido.

Un buen curso sobre microcontroladores es accesible desde http://www.itescam.edu.mx/portal/asignatura.php?clave_asig=MTF-1021&carrera=IMCT-2010-229&id_d=206. Se trata de una asignatura de microcontroladores.

Más información sobre microcontroladores: https://sites.google.com/site/electronicscience20/Micro/pic-asembler/2-microcontroladores

Raspberry Pi es un ordenador de placa reducida o (placa única) (SBC) de bajo coste, desarrollado en Reino Unido por la Fundación Raspberry Pi. El diseño incluye un System-on-a-chip Broadcom BCM2835, que contiene un procesador central (CPU) ARM1176JZF-S a 700 MHz, un procesador gráfico (GPU) VideoCore IV, y 512 MiB de memoria RAM.

Los sistemas operativos soportados son distribuciones Linux para arquitectura ARM, Raspbian (derivada de Debian), RISC OS 5, Arch Linux ARM (derivado de Arch Linux) y Pidora (derivado de Fedora)

Web principal: http://www.raspberrypi.org/

Especificaciones técnicas: http://es.wikipedia.org/wiki/Raspberry_Pi#Especificaciones_t.C3.A9cnicas

El System-on-a-chip Broadcom BCM2835: http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf

GPIO:

También intel saca su alternativa a raspberry: http://www.intel.es/content/www/es/es/do-it-yourself/edison.html

Más información: https://aprendiendoarduino.wordpress.com/2016/06/25/arduino-vs-raspberry-pi-2/

Un sketch de Arduino no es un sistema operativo: https://es.wikipedia.org/wiki/Sistema_operativo. Un sistema operativo es un programa o conjunto de programas de un sistema informático que gestiona los recursos de hardware y provee servicios a los programas de aplicación de software, ejecutándose en modo privilegiado respecto de los restantes (aunque puede que parte de él se ejecute en espacio de usuario)

Se puede decir que el sketch de Arduino es la aplicación que gestiona directamente los recursos de HW sin necesidad de un SO o un kernel intermedio.

En el caso de raspberry Pi, el programa o sketch se ejecuta como una aplicación sobre un sistema operativo y para interaccionar con el HW necesita de la interacción con el sistema operativo.

Para entender qué es el microcontrolador dentro de Arduino, leer: https://aprendiendoarduino.wordpress.com/2015/02/25/como-conseguir-un-arduino-gratis/

¿Podría convertir un arduino en un ordenador? ¿Cómo? ¿Es práctico?. Arduino como un ordenador:

También es posible convertir un ordenador en un microcontrolador http://www.instructables.com/id/HackTurn-PC-into-a-microcontroller-for-free/?ALLSTEPS

Microcontroladores 8 bits, 16 bits, 32 bits

El tamaño de la palabra es un aspecto importante en la arquitectura de procesadores.

La mayoría de los registros de un Microprocesador/Microcontrolador tienen el tamaño de la palabra y las operaciones que hace la ALU es manejando operandos cuyo tamaño es el tamaño de la palabra, así como la cantidad de datos transferidos a memoria y dirección utilizada para designar una localización de memoria a menudo ocupa una palabra.

El tamaño de palabra de un microprocesador/microcontrolador influye principalmente en el tamaño de datos que puede manejar y la cantidad de memoria RAM que puede usar, así como la velocidad de procesamiento.

También los valores que pueden tomar las variables dependen del tamaño de la palabra: http://es.wikipedia.org/wiki/Palabra_%28inform%C3%A1tica%29

Arduinos con procesadores de 8 bits:

Arduinos con procesadores de 32 bits: