Taller de Interrupciones

Anuncio
Taller de Interrupciones
Organización del Computador 1
Verano 2016
Introducción
Para este taller se propone utilizar un ArduinoUNO como unidad de procesamiento principal para controlar un
robot que sea capaz de seguir una lı́nea blanca sobre un fondo negro.
El desarrollo del mismo se realizará utilizando el simulador web www.123d.circuits.io.
El robot
El robot que se va a utilizar posee un ArduinoUNO, dos sensores infrarrojos, un pulsador y dos motores controlados
por un driver (ver Fig. 1):
El ArduinoUNO: es una placa de desarrollo que tiene como unidad de procesamiento un microcontrolador
ATmega328. Esta placa cuenta con terminales (o pines) a las que podemos conectar sensores, motores, LEDs,
etc. El ArduinoUNO cuenta también con un LED incorporado en la placa que está asociado al pin 13, este LED
puede ser utilizado, por ejemplo, para debuguear el código.
Los motores: sirven para mover el robot en lı́nea recta (los dos motores con igual velocidad) o doblando en
algún sentido (diferentes velocidades en cada motor).
El driver: manejan la corriente que necesitan los motores. En nuestra simulación los motores seleccionados
cuentan con drivers internos, por lo que no es necesario incluirlos en el circuito.
Los sensores infrarrojos: permiten medir cambios de color en el suelo. Cuando detectan un cambio de
color estos sensores dispararán una interrupción.
El pulsador: es un dispositivo de entrada que se deberá leer por polling.
Sensores
Infrarrojos
Motores
Arduino UNO
Driver
Bumper o
Boton
Figura 1: El robot
El simulador
Para simular el robot se utilizarán componentes similares a los del mismo en un el simulador web www.123d.circuits.io.
Pero antes es necesario hacer una introducción a los componentes que se utilizarán.
1
Figura 2: Protoboard
El Protoboard es una plataforma de pruebas que permite interconectar componentes electrónicos sin la necesidad
de utilizar soldadura. Las conexiones se hacen por medio de láminas metálicas internas que ejercen presión
sobre los terminales de los componentes. Algunos agujeros se encuentran conectados horizontalmente y otros
verticalmente (ver Fig. 2).
Los cables son los elementos por los cuales circula la corriente eléctrica. Utilizaremos la siguiente convención de
colores:
rojo para los cables de 5V
negro para los cables de 0V (masa)
amarillo para las conexiones de entradas al ArduinoUNO
naranja para las conexiones con los motores
verde para conexiones internas del protoboard
Las resistencias sirven para limitar la corriente que circula por un circuito y ası́ evitar que se queme un componente.
Los botones o switches no son más que simples interruptores. Existen dos tipos, dependiendo si mantienen el
valor una vez que se sueltan (funcionamiento similar al de una llave de luz) o no (funcionamiento similar al de
un timbre).
Antes de empezar
Para poder utilizar el simulador se debe ingresar a la página web www.123d.circuits.io y crear una cuenta. Al
ingresar, hacer click en + New y elegir la opción New Electronics Lab. Esto nos llevará a una página similar a la de
la Fig. 3. En dicha Fig. se puede observar la interfaz del simulador. El mismo posee un protoboard y distintos controles
que permiten agregar componentes en la pestaña + Components. Para este taller utilizaremos los componentes que
figura en la sección Arduino Basic Kit.
Cuando se agrega un ArduinoUNO en el simulador se habilita la opción de editar, cargar y ejecutar código desde
la pestaña Code Editor. Además en la ventana Code Editor se puede acceder al Serial Monitor donde podremos
ver salida de debug.
Para comenzar la simulación es necesario tocar el botón Start Simulation.
Funciones importantes
El lenguaje Arduino está basado en C/C++. Referencia en www.arduino.cc/en/Reference/HomePage. Las funciones relevantes para este taller son:
unsigned long millis() devuelve el número de milisegundos desde que el arduino comenzó a correr el programa.
void attachInterrupt(digitalPinToInterrupt(pin), ISR, mode) : permite setear una interrupción, pin es la
entrada del arduino a la cual está conectada la interrupción. ISR es el nombre de la función que va a atender
la interrupción, mode es el tipo de interrupción, en este taller siempre se utilizará CHANGE.
void analogWrite(pin, value) es el mecanismo que cuenta el ArduinoUNO para tener una salida analógica. En
pin se emite el valor value en el formato PWM (Pulse Width Modulation, en español: Modulación por ancho
de pulsos). La señal analógica que se emite puede variar entre el valor mı́nimo 0 (que corresponde a 0V) y
el máximo 255 (que corresponde a 5V). En el caso del taller el 0 corresponde a el motor detenido y el 255 a
máxima potencia.
2
Figura 3: Interfaz del simulador
int digitalRead(pin) lee el valor de una entrada digital pin, puede ser un 1 ó un 0.
Serial.begin(speed) configura e inicializa la comunicación serial a la velocidad dada por speed. En el taller
utilizaremos speed=9600
Serial.println(‘‘Esto es una salida de debug’’) imprime texto en el puerto serial.
Consigna
1) a) Construir el circuito que se muestra en la Fig. 4 y testear que los LEDs se prendan cuando se pulsan o activan
los botones (no hace falta cargar código en el ArduinoUNO para esto). Nota: no usar el protoboard que viene
originalmente.
ArduinoUNO
led
pulsador
motor left
resistencia
motor right
botón 1
botón 2
Figura 4: Circuito completo
Observaciones:
las resistencias deben ser configuradas como de 220Ω (220 Ohms).
el pulsador solo mantiene el valor mientras lo tenemos presionado
los botones 1 y 2 mantienen su valor una vez que los soltamos
algunos componentes tienen polaridad, con lo cual no son reversibles. Prestar especial atención a como se
deben conectar.
3
Utilizaremos el pulsador para simular el pulsador del robot y los botones 1 y 2 para simular el comportamiento
de los sensores infrarrojos.
b) Utilizar el código de ejemplo anexo a este enunciado para testear la simulación.
2) Se deberán programar 3 comportamientos distintos de un robot siguiendo una lı́nea. En todos los casos el robot
siempre deberá tener guardado lo que está haciendo, llamaremos a esto estado interno.
Las configuraciones posibles de los motores son:
Avanzando ambos motores deben ser configurados con potencia 75
Girando izquierda se debe configurar el motor izquierdo con potencia 35 y el derecho con potencia 130
Girando derecha igual al anterior pero intercambiando los motores
Detenido ambos motores reciben cero como potencia
Los pines del ArduinoUNO están conectados de la siguiente manera:
pin
2
3
5
6
9
10
12
Conexión
Sensor izquierdo
Sensor derecho
Potencia motor derecho
Masa motor derecho
Masa motor izquierdo
Potencia motor izquierdo
Pulsador
Los pines que van a masa de un motor deben setearse inicialmente en cero y no modificarse.
Por último, el control de los motores se debe realizar en la rutina principal y no en una rutina de atención de
una interrupción.
Comportamiento 1 Utilizando 1 sensor infrarrojo (Sensor izquierdo) y el pulsador programar el ArduinoUNO
para lograr el siguiente comportamiento:
El robot deberá alternar entra las dos configuraciones de los motores: Girando izquierda y Girando derecha para poder seguir la lı́nea. Se inicia en Girando derecha y se mantiena hasta que el
sensor detecte un cambio (y produzca una interrupción). En ese momento debe cambiar a Girando
izquierdahasta la próxima interrupción. Y ası́ sucesivamente.
El pulsador debe comportarse como interruptor ON/OFF, es decir, cuando el pulsador esté apretado el
robot debe detenerse (configurado como Detenido) y cuando se suelta el robot debe seguir en el estado
que estaba (siguiendo la lı́nea).
A continuación se muestran las dos máquinas de estados (ver Fig. 5) que reflejan el comportamiento esperado.
Figura 5: Comportamiento 1
Comportamiento 2 Utilizando los 2 sensores infrarrojos y el pulsador programar el ArduinoUNO para lograr el
siguiente comportamiento:
4
El robot arrancará configurado en Avanzando. Cuando detecte que se desvı́a de la lı́nea deberá corregir
su rumbo. Para ello, si el sensor izquierdo empieza a sensar blanco (lo cual produce una interrupción),
se debe modificar a girando izquierda hasta que el mismo sensor vuelve a sensar negro (produciendo
nuevamente una interrupción). Lo mismo sucede si el sensor que provoca una interrupción es el sensor
derecho.
El pulsador debe comportarse como interruptor ON/OFF, es decir, cuando el pulsador esté apretado el
robot debe detenerse (configurado como Detenido) y cuando se suelta el robot debe seguir en el estado
que estaba (siguiendo la lı́nea).
A continuación se muestra las dos máquinas de estados (ver Fig. 6) que reflejan el comportamiento esperado.
Figura 6: Comportamiento 2
Comportamiento 3 Utilizando los 2 sensores infrarrojos y el pulsador programar el ArduinoUNO para lograr el
siguiente comportamiento:
El robot arrancará configurado en Avanzando. Cuando detecte que se desvı́a de la lı́nea deberá corregir
su rumbo. Para ello, si el sensor izquierdo empieza a sensar blanco (lo cual produce una interrupción),
se debe modificar a girando izquierda hasta que el mismo sensor vuelve a sensar negro (produciendo
nuevamente una interrupción). Lo mismo sucede si el sensor que provoca una interrupción es el sensor
derecho.
el pulsador debe comportarse como una pausa de 3 segundos, es decir, que cuando el pulsador es activado
el robot configurarse como Detenido por 3 segundos y luego continuar con su comportamiento anterior.
A continuación se muestra las dos máquinas de estados (ver Fig. 7) que reflejan el comportamiento esperado.
Figura 7: Comportamiento 3
Anexo
Código de ejemplo
1
2
3
4
5
/ * Constantes que no cambian y son usadas para setear el numero de los pines * /
# define motorPinA 5
// el numero del pin de uno de los cables de motor
# define motorPinB 6
// el numero del pin del otro cable del motor
# define sensorInt 3
// el numero del pin del sensor que i n t e r r u m p e
5
6
# define sensorPoll 2
// el numero del pin del p u l s a d o r
7
8
9
10
11
/ * variables que cambian su valor : * /
bool andando = true ;
bool nitro
= false ;
12
13
14
15
16
17
18
19
/ * setup inicial * /
void setup () {
pinMode ( sensorPoll , INPUT_PULLUP ) ; / / i n i c i a l i z o e l p i n p u l s a d o r c o m o u n a e n t r a d a
pinMode ( motorPinA , OUTPUT ) ;
// i n i c i a l i z o el pin A del motor como una salida
analogWrite ( motorPinA ,0) ;
// pongo en 0 el pin A del motor
pinMode ( motorPinB , OUTPUT ) ;
// i n i c i a l i z o el pin B del motor como una salida
Serial . begin (9600) ;
// c o n f i g u r o e i n i c i a l i z o la c o m u n i c a c i o n serial a
9600 baudios
// c o n f i g u r o la i n t e r r u p c i o n del pin
meInterrumpieron
// cuando se p r o d u c e un cambio
20
21
para que llame a la f u n c i o n
attachInterrupt ( digi talP inToI nter rupt ( sensorInt ) , meInterrumpieron , CHANGE ) ;
22
23
sensorInt
}
24
25
26
27
28
29
/ * loop del programa * /
void loop () {
if ( andando ) {
if ( digitalRead ( sensorPoll ) ) {
nitro = true ;
// P r e g u n t o si estoy en estado a n d a n d o
// P r e g u n t o si el p u l s a d o r esta a p r e t a d o
// Si estoy en estos e s t a d o s pongo seteo el estado
nitro
Serial . println ( " nitro = true " ) ; / /
}
else {
//
nitro = false ;
//
Serial . println ( " nitro = false " ) ; / /
}
30
31
32
33
34
35
}
actualizarEstado () ;
36
37
motores
38
dependiendo
del estado
M u e s t r o por serial que cambie de estado
Si el p u l s a d o r no esta a p r e t a d o
p o n g o n i t r o c o m o false
M u e s t r o por serial que cambie de estado
// llamo a la f u n c i o n que manda
definido
potencia a los
}
39
40
41
42
43
44
45
46
47
/ * funcion que actualiza la velocidad de los motores dependiendo del estado * /
void actualizarEstado () {
if ( andando ) {
// Si el estado es a n d a n d o
if ( nitro ) {
// y nitro es v e r d a d e r o
analogWrite ( motorPinB ,250) ;
// Seteo la v e l o c i d a d de el motor a 250
}
else {
analogWrite ( motorPinB ,30) ;
// Si nitro == 0 e n t o n c e s pongo v e l o c i d a d de 30 a
los motores
}
}
else {
analogWrite ( motorPinB ,0) ;
}
48
49
50
51
52
53
// Si a n d a n d o no es v e r d a d e r o
// freno el motor p o n i e n d o v e l o c i d a d 0
}
54
55
56
57
58
59
60
61
62
63
64
65
66
/ * funcion que se llama cuando se produce una interrupcion * /
void meInterrumpieron () {
Serial . println ( " Interrupcion " ) ;
// m u e s t r o por serial que hubo una i n t e r r u p c i o n
if ( andando ) {
// si estoy a n d a n d o
andando = false ;
// e n t o n c e s freno
Serial . println ( " andando = false " ) ; / / y m u e s t r o p o r s e r i a l q u e f r e n e
}
else {
// Si estoy f r e n a d o
andando = true ;
// c o m i e n z o a andar
Serial . println ( " andando = true " ) ; / / y m u e s t r o p o r s e r i a l q u e c o m e n z e a a n d a r
}
}
6
Descargar