Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Arquitectura de Computadoras
I. Interrupciones Externas
Las interrupciones son sucesos que pueden ocurrir en cualquier momento por lo que no
podemos prever exactamente cuándo detectarlas. Por ejemplo, podemos colocar un
sensor en el frente de un vehículo para que detecte a distancia los posibles obstáculos que
encuentre en su camino y lo informe a la tarjeta cambiando el estado de un Pin.
En principio, podemos poner en determinado punto del bucle, leer el estado del pin, de
forma que el cambio de estado nos delatara la existencia del obstáculo y de encontrarlo,
cambiar la trayectoria del vehículo para esquivarlo. Si en recorrer todo el bucle se tarda
milisegundos, la cosa funcionará muy bien, pero imaginemos que en un punto del bucle
hemos puesto una función “delay” que hace detener el funcionamiento del bucle por un
tiempo, igual que hacíamos en el programa “blink”.
Ocurre entonces que el bucle no se recorre en un corto periodo de tiempo, sino que
puede tardar a lo mejor un minuto. Como Arduino tarda un minuto en volver a leer el
estado del pin, no se enterará de la existencia del obstáculo en ese tiempo, tiempo más
que suficiente para que el vehículo choque con el obstáculo. ¿Cómo resolvemos el
problema?.
Para resolver este tipo de problemas existe varios medios, pero el más sencillo es el
previsto para el manejo de interrupciones y para ello Arduino Uno tiene dos de los pines
específicos, el Pin 2 y el Pin 3, (como se explicó en el capitulo 5 de la Introducción a
Arduino , capaces de detectar interrupciones en cualquier instante, independientemente
de lo que en ese momento esté haciendo la función principal “loop”, Cuando Arduino
detecta un cambio en el estado de uno de esos pines puede parar el funcionamiento del
bucle “loop”donde se encuentre y lanzar una función asociada a esa interrupción
inmediatamente, (en el modelo Arduino UNO, para continuar posteriormente el proceso
del bucle “loop” desde donde lo parara.
Así pues en nuestro vehículo, podemos asociar el detector de obstáculos al Pin2, (o al
Pin3), y tan pronto como se detecte un obstáculo y cambie el estado del Pin2, se puede
lanzar una función que por ejemplo haga retroceder al vehículo y cambie el rumbo con el
fin de eludir el obstáculo.
Ejemplo1
void setup()
{ pinMode(2, INPUT);
Serial.begin(9600);
}
void loop()
{ bool p = digitalRead(2);
Serial.println(p);
}
El resultado seria normalmente 1, por el pull up y la lectura bajaría a 0, al pulsar el botón.
Nada nuevo en esto.
int contador = 0;
int n = contador ;
void setup()
{ Serial.begin(9600);
attachInterrupt( 0, ServicioBoton, FALLING);
}
void loop()
{
if (n != contador)
{ Serial.println(contador);
n = contador ;
}
}
void ServicioBoton()
{ contador++ ;
}
En primer lugar fijaros que hemos eliminado la definición de entrada del pin 2, porque no
vamos a usarlo como input estrictamente. Con definir la interrupción es suficiente.
Y por último el trigger es FALLING porque el estado es normalmente HIGH y baja a LOW al
pulsar el botón, utilizaremos el disparo con el flanco de bajada, o sea FALLING o LOW.
Pues como ya vimos en su día, se debe a los rebotes del pulsador que para eliminar el
rebote de los botones, tenemos que hacer el debouncing y para eso se puede hacer con
un delay de 250 ms.
Pero vamos a tener un problema. No podemos usar un delay dentro de una interrupción.
No funciona. ¿Cómo dice?
Además cuando definimos una variable global como contador, de la que depende una
función ISR, se recomienda definirla como volatile y no como una global normal.
void setup()
{ pinMode(2, INPUT);
Serial.begin(9600);
attachInterrupt( 0, ServicioBoton, LOW);
}
void loop()
{ if (n != contador)
{ Serial.println(contador);
n = contador ;
}
}
void ServicioBoton()
{
if ( millis() > T0 + 250)
{ contador++ ;
T0 = millis();
}
}
En primer lugar definimos contador como volátil, por prescripción médica, y definimos
otra variable global T0 para almacenar el tiempo a partir del cual contaremos.
Así es. Mientras una interrupción esta activa millis está congelada y su valor no cambiará,
pero sigue pudiéndose leer.
Mientras estas dentro de una interrupción, todas las demás interrupciones, son
ignoradas, por eso, nada que dependa de otras interrupciones funciona.
Por eso es importante salir pronto, para garantizar que no nos perdemos nada de
interés.
Mientras una interrupción está activa, millis() y micros()se congelan. Eso quiere
decir que si tienes unos cuantos miles de interrupciones por segundo (Como si estas
midiendo la frecuencia de una onda de audio) tu medida de tiempo con millis o
micros se puede ver distorsionada.
Por ultimo conviene saber que existen algunas otras instrucciones relativas a las
interrupciones:
Ejemplo2
Como se ha indicado hay dos pines capaces de detectar en cualquier momento una
interrupción los pines 2 y 3 y lanzar instantáneamente una tarea diseñada para hacerla
frente. Por poner otro ejemplo, en un proyecto de vigilancia domótica, puedes poner un
sensor en la puerta de la calle, asociado al Pin2 y un detector de humo, asociado al Pin3 y
según se abran la puerta de la calle o se detecte humo, lanzar dos tareas diferentes. En
tarjetas de la familia Arduino más potentes existen más pines que controlan
interrupciones, por lo que en nuestro caso podrías por otras alarmas, como para
inundaciones, viento etc.
El montaje comporta dos resistencias de 270 ohmios, un al lado del botón pulsador (así
si se pone por error el pin 2 OUPUT, no habrá desastres), la otra es la resistencia en
serie con el LED que le permite funcionar a la tensión adecuada. Los hilos verdes están
conectados a tierra (GND).
El codigo para el uso de las interrupciones será:
} // fin de setup
void loop () {
} // fin inter0
En este caso, ambas rutinas ISR simplemente llamaran a toggle () y dejaran que ella haga
el trabajo.
Ciertas funciones tales como delay () no funcionarán dentro de una función ISR así que es
una buena idea utilizar subrutinas independientes, siempre y cuando no sean demasiado
complejos o tomen mucho tiempo - otra interrupción rodando sobre una llamada de
subrutina ISR que no ha terminado podía ser interesante.
#define LED1 9
#define LED2 10
#define SW1 2
#define SW2 3
digitalWrite(pinNum, pinState);
void setup() {
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(SW1, INPUT);
pinMode(SW2, INPUT);
void loop() {
// do nothing
}
void ISR0() {
toggle(LED1);
void ISR1() {
toggle(LED2);
En adición de funciones que utilizan las interrupciones tales como delay () no funcionará si
se llama desde una rutina ISR. Por ejemplo, la versión modificada de toggle () que sigue no
va a funcionar si es llamado por un ISR, pero funciona bien si se llama desde loop () u otra
subrutina no interrupción. El LED seleccionado se encenderá durante dos segundos y
luego apagarse.
La rutina ISR mantiene el control de las interrupciones hasta que esté terminado y ejecuta
un "retorno" de comando de interrupción.
digitalWrite(pinNum, pinState);
delay(2000);
pinState = pinState ^ 1;
digitalWrite(pinNum, pinState);
void myDelay(int x) {
delayMicroseconds(1000);
#define LED1 9
#define LED2 10
#define SW1 2
#define SW2 3
digitalWrite(pinNum, pinState);
}
void setup() {
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(SW1, INPUT);
pinMode(SW2, INPUT);
void loop() {
noInterrupts();
toggle(LED2);
myDelay(2000);
toggle(LED2);
myDelay(2000);
interrupts();
} // end loop
void myDelay(int x) {
{
delayMicroseconds(1000);
void ISR0()
toggle(LED1);
void ISR1(){
toggle(LED2);
myDelay(5000); // 5 sec.
toggle(LED2);
II. Concurrencia
Ejemplo1
#define ledPin1 7
#define ledPin2 9
*lastMillis = currentMillis;
return true;
else
return false;
void setup()
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
void loop()
{
if(cycleCheck(&led1LastMillis, led1Cycle))
digitalWrite(ledPin1, led1State);
led1State = !led1State;
if(cycleCheck(&led2LastMillis, led2Cycle))
digitalWrite(ledPin2, led2State);
led2State = !led2State;
Ejemplo2
#include "mthread.h"
#define LED1 7
#define LED2 9
class Led;
public:
Led(int pin, int p1);
bool isOn;
int blinks;
protected:
bool loop();
int pin;
};
this->pin = pin;
this->blinks = p1;
this->isOn = false;
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
//pause();
this->isOn = isOn;
}
void Led::blink(int blinks) {
this->blinks = blinks;
resume();
bool Led::loop() {
if(blinks > 0) {
switchOn(!isOn);
sleep_milli(blinks);
} else {
pause();
return true;
void setup(){
main_thread_list->add_thread(led1);
main_thread_list->add_thread(led2);
}
II. LCD Touch Screen
SD Memory Supports:2GB
Overview
Ø 240 x 320 QVGA resolution, 65K true to life colors, TFT screen.
Ø Easy 5 pin interface to any host device: VCC, TX, RX, GND, RESET.
Ø Asynchronous hardware serial port, TTL interface, with 300 baud to 256K baud.
Ø On-board micro-SD memory card adapter for multimedia storage and data logging
purposes. HC card support is also available for cards 4Gb and larger.
Ø DOS compatible file access (FAT16 format) as well as low level access to card memory.
Ø Dedicated PWM Audio pin supports FAT16 audio WAV files and complex sound
generation.
Ø On-board audio amplifier with a tiny 8 Ohms speaker for sound generation and WAV
file playback.
Ø Comprehensive set of built in high level graphics functions and algorithms that can
draw lines, circles, text, and much more.
Ø Display full color images, animations, icons and video clips - supports all available
Windows fonts and characters (imported as external fonts).
Ø 16x General Purpose I/O pins. Upper 8 bits can be used as an I/O Bus for fast 8-bit
parallel data transfers.
Ø 2x 30 pin headers for I/O expansion and future plug-in daughter boards.
Library: UTFT
Basic functionality of this library was origianlly based on the demo-code provided by ITead
studio (for the ITDB02 modules) and NKC Electronics (for the RGB GLCD module/shield).
This library supports a number of 8bit, 16bit and serial graphic displays, and will work with
both Arduino and chipKit boards.
The library works great with the ITDB02 series of display modules from ITead Studio, the
TFT01 series of display modules from ElecFreaks, and the RGB LCD Shield and module
from NKC Electronics.
void setup(){
pinMode (speakerOut, OUTPUT);
}
void loop() {
for (int i = 0; i 100; i++){
digitalWrite(speakerOut,HIGH);
delayMicroseconds(1136);
digitalWrite(speakerOut, LOW);
delayMicroseconds(1136);
}
}
Arduino tiene 2 funciones diseñadas para emitir sonidos de manera correcta. La primera
es tone() la cual requiere como parametros lo siguiente:
tone(pin, frequency)
void setup(){
pinMode(kPinSpeaker, OUTPUT);
void loop() {
delay(500);
delay(500);
delay(500);
delay(500);
delay(500);
delay(500);
delay(500);
delay(500);
noTone(kPinSpeaker);
delay(2000);