Mecatrónica
Arduino
1
¿Qué es Arduino?
• Placa microcontroladora Open hardware
basado en micros Atmel
• Se programa fácilmente en lenguajes de alto
nivel mediante el entorno de desarrollo
integrado.
• Multitud de proyectos y desarrollos en la red:
[Link]
2
Arduino Duemilanove (2009)
3
4
Arduino UNO
5
Arduino Mega 2560
6
Arduino Uno
• Atmega 328
• 32 kbyte memoria flash
programable
• 2 Kbyte memoria RAM
• Reloj 16MHz
• Entradas y Salidas
– 14 entradas y salidas digitales
– 6 entradas analógicas (también
salidas *)
– Total 20 entradas/salidas
• Puede funcionar de modo
independiente sin necesidad de
ordenador una vez programado
* [Link] 7
Arduino UNO
Test Led
Pin 13 Pins de entradas/salidas digitales
Led
Encendido
Interface
USB
Leds Botón
Tx/Rx Atmega 328 Reset
Alimentación
8
Externa Pins de entradas analógicas
Entorno de desarrollo
Verificar
(Compilar)
Cargar a
Tarjeta
Área de estado
9
Descarga en: [Link]
Instalación
Guia Instalación:
[Link]
10
Estructura de un Programa
Comentarios.
Qué hace el programa
Incialización. Definición
de E/S, etc.
Cuerpo del programa.
Bucle infinito.
11
Comentarios
• Pueden ir en cualquier sitio del código
• Se crean con:
• // (comenta línea entera)
• /* comentarios que pueden afectar varias lineas*/
• Los comentarios no afectan al código
• Indispensables para entender que hace el
programa y que otros lo entiendan!
12
Tipos de Datos
• byte: enteros de 8 bits 0 a 255 sin puntos decimales
byte someVariable = 180; //declara 'someVariable' como un tipo byte
• int: enteros de 16 bits con un rango de -32,768 a 32,767,
Puede tener el modificador unsigned para almacenar solo
enteros positivos. (unsigned int)
int someVariable = 1500; //declara 'someVariable' como tipo int
unsigned int ledPin = 13;
• long: enteros largos de 32 bits con un rango de -2,146,483,648
a 2,147,483,647. (Puede tener modificador unsigned)
long someVariable = 90000; //declara 'someVariable' como tipo long
• char: Ocupa un byte de memoria y almacena un valor de
carácter. Los caracteres literales se escriben con comillas
simples
char miChar = 'A'; 13
char miChar = 65; // los dos son equivalentes
Tipos de Datos
• float: flotantes de 32 bits con un rango de -3.4028235E+38 a
3.4028235E+38.
float someVariable = 3.14; //declara 'someVariable' como tipo float
• string: Los strings se representan como arrays de caracteres
(tipo char) que terminan con el caracter NULL.
char Str1[15];
char Str2[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o'};
char Str3[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o', '\0'};
char Str4[ ] = "arduino";
char Str5[8] = "arduino";
char Str6[15] = "arduino";
14
Tipos de Datos
• Arrays: colección de valores que son accedidos con un índice
numérico
Declaración:
int myArray[] = {value0, value1, value2...}; // declara e inicializa
int myArray[5]; //declara un array de enteros con 6 posiciones
Asignación:
myArray[3] = 10; //asigna a la cuarta posición del índice el valor 10
x = myArray[3]; //x ahora es igual a 10
15
Operadores
Operadores aritméticos
• Realizan operaciones aritméticas sobre
sus operandos.
•+ suma
•- resta
•/ división
•* producto
y = y+3;
x = x-7;
i = j*6;
r = r/5;
16
Operadores
Operadores relacionales de comparación
• Sirven para comparar dos variables o
expresiones. Estos operadores, al igual que los
lógicos, sirven para formar expresiones cuyas
condiciones pueden ser ciertas o falsas.
•> mayor que
•>= mayor o igual que
•< menor que
•<= menor o igual que
•== igual que
•!= distinto que
x == y; //x es igual a y
x != y; //x no es igual a y
x < y; //x es menor que y
x > y; //x es mayor que y
x <= y; //x es menor o igual que y 17
x >= y; //x es mayor o igual que y
Operadores
Operadores relacionales lógicos
• Los resultados de las operaciones lógicas
siempre adoptan los valores TRUE ó FALSE
//AND logico:
if(x>0 && x<5) //verdadero sólo si las dos
expresiones son ciertas
//OR logico:
if(x>0 || y>0) //verdadero si al menos una expresion
es cierta
//NOT logico:
if(!(x>0)) //verdadero sólo si la expresión es falsa
18
Constantes
Constantes predefinidas en Arduino
• TRUE/FALSE
Estas son constantes Booleanas que definen niveles
lógicos. FALSE se define como 0 (cero) mientras
TRUE es 1 o un valor distinto de 0.
if(b == TRUE)
{
doSomething;
}
19
Constantes
Constantes predefinidas en Arduino
• HIGH/LOW
Estas constantes definen los niveles de pin como HIGH
o LOW y se usan cuando se leen o se escriben los
pines digitales. HIGH esta definido como el nivel 1
lógico, ON ó 5 V, mientras que LOW es el nivel lógico
0, OFF ó 0 V.
digitalWrite(13, HIGH);
20
Constantes
Constantes predefinidas en Arduino
• INPUT/OUTPUT
Constantes usadas con la función pinMode() para
definir el modo de un pin digital como INPUT u
OUTPUT.
pinMode(13, OUTPUT);
21
E/S Digital
pinMode(pin, mode) Se usa en void setup() para configurar un
pin específico para que se comporte o como INPUT o como OUTPUT.
pintMode(pin, OUTPUT); //ajusta 'pin' como salida
• Por defecto los pines digitales están ajustados como INPUT
• Los pines configurados como INPUT se dice que están e un estado
de alta impedancia.
• Se dispone de resistencias de pull-up de 20KOhm, integradas en el
chip Atmega que pueden ser accedidas por software, muy útiles
para conectar entradas como interruptores.
pinMode(pin, INPUT); //ajusta 'pin' como entrada
digitalWrite(pin, HIGH); //activa la resistencia de pull-up
22
E/S Digital
digitalRead(pin) Lee el valor desde un pin digital
especificado con el resultado HIGH o LOW. El pin puede
ser especificado o como una variable o como una
constante (0 - 13).
value = digitalRead(Pin); //ajusta 'value' igual al pin de
entrada
digitalWrite(pin, value) Si pin está definido como
OUTPUT pone en este el valor HIGH o LOW (poniendo en
1 o 0 la salida). El pin se puede especificar ya sea como
una variable o como una constante (0-13). (Si pin está
definido como entrada activa/desactiva resistencia pull-up)
digitalWrite(pin, HIGH); //ajusta 'pin' a HIGH
23
E/S Digital
//Ejemplo de programa
int led = 13; //conecta 'led' al pin 13
int pin = 7; //conecta 'pushbutton' al pin 7
int value = 0; //variable para almacenar el valor leído
void setup()
{
pinMode(led, OUTPUT); //ajusta el pin 13 como salida
pinMode(pin, INPUT); //ajusta el pin 7 como entrada
}
void loop()
{
value = digitalRead(pin); //ajusta 'value' igual al pin de
entrada
digitalWrite(led, value); //ajusta 'led' al valor del boton
24
}
E/S Analógica
analogRead(pin) Lee el valor desde un pin analógico
especificado con una resolución de 10 bits. Esta función
sólo trabaja en los pines analógicos (0 - 5). Los valores
enteros devueltos están en el rango de 0 a 1023.
value = analogRead(pin); //ajusta 'value' igual a 'pin‘
Nota: Los pines analógicos al contrario que los digitales,
no necesitan ser declarados al principio
como INPUT u OUTPUT.
25
E/S Analógica
analogWrite(pin, value) Escribe un valor pseudo
analógico usando modulación por ancho de pulso (PWM
en inglés) a un pin de salida marcado como PWM.
Esta función se puede utilizar en los pines 3, 5, 6, 9, 10 y
11. El valor puede ser especificado como una variable o
constante con un valor de 0 a 255.
analogWrite(pin, value); //escribe 'value' al 'pin' analogico
26
E/S Analógica
analogWrite(pin, value)
El valor de salida varía de 0 a 5 V según el valor de entrada (de 0 a
255) en función del tiempo de pulso. Si t es el tiempo de pulso,
muestra la equivalencia entre el valor y la salida en función del tiempo.
Se genera una onda estática después de una llamada a analogWrite
en segundo plano hasta la siguiente llamada a analogWrite (o una
llamada a digitalRead o digitalWrite en el mismo pin). 27
E/S Analógica
//Ejemplo analogWrite control PWM
int led = 10; //LED con una resistencia de 220ohm en el
pin 10
int pin = 0; //potenciómetro en el pin analógico 0
int value; //valor para lectura
void setup(){} //setup no es necesario
void loop()
{
value = analogRead(pin); //ajusta 'value' igual a 'pin'
value /= 4; //convierte 0-1023 a 0-255
analogWrite(led, value); //saca la señal PWM al led
}
28
Tiempo
delay(ms) Pausa programa por la cantidad de tiempo
especificada en milisegundos, donde 1000 es igual a 1
segundo.
delay(1000); //espera por un segundo
unsigned long millis() Devuelve el número de
milisegundos desde que la placa Arduino empezó a
ejecutar el programa actual como un valor long sin signo.
value = millis(); //ajusta 'value' igual a millis()
Nota: Este número se desbordará (resetear de nuevo a
cero), después de aproximadamente 9 horas.
29
Aleatorio
randomSeed(seed) Asigna un valor, o semilla (seed en inglés), como
el punto de partida para a función random().
randomSeed(value); //asigna 'value' como la semilla aleatoria
Se pueden crear semillas a partir de función millis() o incluso
analogRead() para leer ruido eléctrico a través de un pin analógico.
random(max)
random(min, max)
La función random te permite devolver números pseudo aleatorios en
un rango especicado por los valores min y max.
value = random(100, 200); //asigna a 'value' un número aleatorio
//entre 100 y 200.
30
Aleatorio
int randNumber; //variable para almacenar el valor aleatorio
int led = 10; //LED con una resistencia de 220ohm en el pin 10
void setup(){
randomSeed(millis()); //asigna millis() como semilla
} void loop()
{
randNumber = random(255); //numero aleatorio de 0 a 255
analogWrite(led, randNumber); //salida de la señal PWM
delay(500);
}
31
Conversión Valores
map(value, fromLow, fromHigh, toLow, toHigh)
Re-mapea un número de un rango a otro. El valor value comprendido
entre fromLow y fromHigh lo mapea en un número comprendido
entre toLow y toHigh.
Example
/* Convierte un valor analógico a un valor de 8 bits (0 to 255) */
void setup() {}
void loop() {
int val = analogRead(0);
val = map(val, 0, 1023, 0, 255);
analogWrite(9, val);
}
32
Comunicación Serie
• Se utiliza para la comunicación entre la placa Arduino y un ordenador u
otros dispositivos.
• Todas las placas Arduino tienen al menos un puerto serie (también
conocido como UART o USART).
• Se comunica a través de los pines digitales 0 (RX) y 1 (TX), así como con
el ordenador mediante USB.
• Si se utilizan funciones de comunicación funciones, no se pueden usar los
pines 0 y 1 como entrada o salida digital.
• Se puede utilizar el monitor del puerto serie incorporado en el entorno
Arduino para comunicarte con la placa Arduino. Hacer clic en el botón del
monitor de puerto serie en la barra de herramientas y selecciona la misma
velocidad en baudios utilizada en la llamada a begin().
33
Comunicación Serie
[Link](rate) Abre el puerto serie y asigna la tasa de baudios
para la transmisión de datos serie. La típica tasa de baudios para
comunicarse con el ordenador es 9600 aunque se pueden poner otras
velocidades.
void setup()
{
[Link](9600); //abre el puerto serie
//ajusta la tasa de datos a 9600 bps
}
Nota: Cuando se usa la comunicación serie, los pines digitales 0 (Rx)
y 1 (Tx) no pueden ser usados al mismo tiempo.
if (Serial) Indica si el puerto serie especificado está preparado. 34
Comunicación Serie
available() Permite obtener el número de bytes disponibles para su
lectura en el puerto serie. Sintaxis: [Link]()
read() Lee datos del puerto serie. Sintaxis: [Link](val),[Link](val,fmt)
print() Imprime datos en el puerto serie en modo texto. Sintaxis [Link]()
[Link](78) muestra"78"
[Link](1.23) muestra "1.23"
[Link]('N') muestra "N"
[Link]("Hello world.") muestra "Hello world.“
Se puede utilizar un parámetro opccional para especificar el formato
[Link](78, BIN) muestra "1001110"
[Link](78, OCT) muestra "116"
[Link](78, DEC) muestra "78"
[Link](78, HEX) muestra "4E"
[Link](1.23456, 0) muestra s "1"
[Link](1.23456, 2) muestra "1.23"
35
println() Igual que print() pero imprime un fin de linea al final
Comunicación Serie
Ejemplo
[Link](analogValue); //envía el valor de 'analogValue'
//Ejemplo de aplicacion
void setup()
{
[Link](9600); //ajusta velocidad serie a 9600 bps
}
void loop()
{
[Link](analogRead(0)); //envía valor analógico
delay(1000); //pausa por 1 segundo
}
36
Comunicación Serie
Ejemplo:
int incomingByte = 0; // para los datos de entrada leidos
void setup() {
[Link](9600); // abre puerto serie, establece velocidad a 9600
bps
}
void loop() {
// envia datos dolo cuando se reciben los datos:
if ([Link]() > 0) {
// leer byte que llega:
incomingByte = [Link]();
// escribe lo que lee:
[Link](“He recibido;");
[Link](incomingByte, DEC);
}
} 37
Comunicación con Matlab
// Programa lectura potenciómetro Arduino
int potenciometro_pin=0; //Analog 0
int valor_potenciometro=0;
void setup(){
[Link](9600);
}
void loop(){
valor_potenciometro=analogRead(potenciometro_pin);
[Link](valor_potenciometro);
delay(100);
}
Ejecutar el programa y comprobar que se reciben los valores en la consola serie
Veamos un programa en matlab para capturar y graficar los valores recibidos
38
Comunicación con Matlab
function Matlab_Arduino(numero_muestras)
% Matlab + Arduino Serial Port communication
close all;
clc;
y=zeros(1,1000); %Vector donde se guardarán los datos
%Inicializo el puerto serial que utilizaré
delete(instrfind({'Port'},{'COM15'}));
puerto_serial=serial('COM15');
puerto_serial.BaudRate=9600;
warning('off','MATLAB:serial:fscanf:unsuccessfulRead');
%Abro el puerto serial
fopen(puerto_serial);
%Declaro un contador del número de muestras ya tomadas
contador_muestras=1;
%Creo una ventana para la gráfica
figure('Name','Serial communication: Matlab + Arduino.')
title('SERIAL COMMUNICATION MATLAB+ARDUINO');
xlabel('Número de muestra');
ylabel('Voltaje (V)');
grid on;
hold on;
39
Comunicación con Matlab
%Bucle while para que tome y dibuje las muestras que queremos
while contador_muestras<=numero_muestras
ylim([0 5.1]);
xlim([contador_muestras-20 contador_muestras+5]);
valor_potenciometro=fscanf(puerto_serial,'%d')';
y(contador_muestras)=(valor_potenciometro(1))*5/1024;
plot(contador_muestras,y(contador_muestras),'X-r');
drawnow
contador_muestras=contador_muestras+1;
end
%Cierro la conexión con el puerto serial y elimino las variables
fclose(puerto_serial);
delete(puerto_serial);
clear all;
end
40
Tiempo
/* Example 37.1 - millis() demonstration
[Link] > chapter 37 John Boxall | CC
by-sa-nc */
unsigned long start, finished, elapsed;
void setup() {
[Link](9600);
}
void loop() {
[Link]("Start...");
start=millis();
delay(1000);
finished=millis(); [Link]("Finished");
elapsed=finished-start;
[Link](elapsed);
[Link](" milliseconds elapsed");
[Link](); delay(500); 41
}
Interrupciones
attachInterrupt(interrupcion, funcion, modo) Especifica
la función a la que invocar cuando se produce una
interrupción externa.
• Remplaza cualquier función previa que estuviera
enlazada a la interrupción.
• La mayoría de las placas Arduino tienen dos
interrupciones externas: Las número 0 (en el pin digital
2) y la 1 (en el pin digital 3).
• La Arduino Mega tiene otras cuatro: Las número 2 (pin
21), 3 (pin 20), 4 (pin 19) y 5 (pin 18).
42
Interrupciones
Parámetros
interrupcion: el número de la interrupción (int)
funcion: la función a la que invocar cuando la interrupción tiene lugar;
esta función no debe tener parámetros ni devolver nada. Esta función
es a veces referenciada como rutina de interrupción de servicio
modo: define cuando la interrupción debe ser disparada. Hay cuatro
constantes predefinidas como valores válidos:
• LOW para disparar la interrupción en cualquier momento que el pin se
encuentre a valor bajo(LOW).
• CHANGE para disparar la interrupción en cualquier momento que el
pin cambie de valor.
• RISING para disparar la interrupción cuando el pin pase de valor bajo
(LOW) a alto (HIGH).
• FALLING para cuando el pin cambie de valor alto (HIGH) a bajo (LOW)
43
Interrupciones
detachInterrupt(interrupt) Apaga la interrupción dada.
Parámetros
interrupt: el número de interrupción a invalidar (0 o 1).
44
Interrupciones
int pin = 13;
volatile int state = LOW;
void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE);
}
void loop()
{
digitalWrite(pin, state);
}
void blink()
{
state = !state; 45
}
Contar Pulsos Encoder
#define encoder0PinA 2
#define encoder0PinB 3
#define encoder0Index 18
volatile unsigned int encoder0Pos = 0;
unsigned int tmp_Pos = 1;
boolean doPrint = false;
int valR = 0;
void setup() {
pinMode(encoder0PinA, INPUT);
pinMode(encoder0PinB, INPUT);
pinMode(encoder0Index, INPUT);
pinMode(13, OUTPUT);
attachInterrupt(0, doEncoderA, CHANGE); // Canal A encoder en
interrupcción 0 (pin 2)
attachInterrupt(1, doEncoderB, CHANGE); // Canal A encoder en
interrupcción 1 (pin 3)
attachInterrupt(5, doEncoderIndex, CHANGE);// encoder pin on interrupt 5 (pin 18)
[Link] (9600);
} 46
Contar Pulsos Encoder
void loop(){
// Solo Imprime valor cuando cambia de valor
if (tmp_Pos != encoder0Pos) {
tmp_Pos = encoder0Pos;
[Link](encoder0Pos, DEC);
}
if (doPrint == true) {
[Link]("R:");
[Link](encoder0Pos, DEC);
doPrint = false;
}
}
47
Contar Pulsos Encoder
// Interrupción cambio estado en canal A
void doEncoderA(){ // mira flanco de subida en canal A
if (digitalRead(encoder0PinA) == HIGH) { // mira canal B para ver sentido de giro
if (digitalRead(encoder0PinB) == LOW)
encoder0Pos += 1; // CW
else encoder0Pos = encoder0Pos - 1; // CCW
}
else { // Debe haber flanco de bajada en canal A
// mira canal B para ver sentido de giro canal B
if (digitalRead(encoder0PinB) == HIGH)
encoder0Pos = encoder0Pos + 1; // CW
else encoder0Pos = encoder0Pos - 1; // CCW
}
}
48
Contar Pulsos Encoder
// Interrupción cambio estado en canal B
void doEncoderB(){
if (digitalRead(encoder0PinB) == HIGH) { // mira flanco de subida en canal B
if (digitalRead(encoder0PinA) == HIGH) // mira canal A para ver
sentido de giro
encoder0Pos = encoder0Pos + 1; // CW
else encoder0Pos = encoder0Pos - 1; // CCW
else { // Debe haber flanco de bajada en canal B
// mira canal B para ver sentido de giro canal B
if (digitalRead(encoder0PinA) == LOW)
encoder0Pos = encoder0Pos + 1; // CW
else encoder0Pos = encoder0Pos - 1; // CCW
}
}
void doEncoderIndex(){
doPrint = true;
valR = encoder0Pos;
}
49