Kit Arduino UNO R3

Para empezar a trabajar con la plataforma Arduino, debemos tener instalado el IDE de Arduino en nuestro ordenador. Este proceso podemos verlo con detalle en la página 15 del Libro de Proyectos de Arduino.

Si estamos usando una placa de Arduino compatible necesitamos instalar el driver del chip CH340. Podemos descargarlo aquí.

Una vez tenemos instalado el IDE, podemos ponernos manos a la obra y empezar a conocer el fantástico mundo Arduino.


El UNO y la Protoboard

Arduino UNO

La placa de Arduino UNO va a ser el cerebro de nuestros proyectos. Nos va a proporcionar la lógica necesaria para hacerlos funcionar. En sí misma no hace nada, pero con un poquito de programación conseguiremos hacer maravillas.

Aquí vemos las partes de la placa que nos interesa conocer.

Conector USB. Nos permite conectar la placa a nuestro ordenador con un cable estándar USB A/B. Se usa para programar y alimentar la placa.

Jack de alimentación. Podemos usar este conector para alimentar nuestro Arduino cuando no está conectado al ordenador. Acepta tensiones de entre 7 y 12V. Es frecuente usarlo con una pila de 9V o un alimentador.

Pines digitales. Estos pines proporcionan entradas y salidas digitales. Permiten enviar señales para activar motores, relés, leds, etc. O bien recibir señales digitales de sensores (temperatura, sonido, luminosidad, etc.)

Pines analógicos. Reciben señales analógicas.

Pines de alimentación. Podemos usar estos pines para alimentar dispositivos externos como motores, sensores u otros circuitos.

Toda la información sobre Arduino UNO podemos obtenerla en su página oficial.

La Protoboard

Es la placa sobre la que haremos todos nuestros montajes electrónicos. Se trata de una superficie de plástico en cuyas perforaciones alojaremos los distintos componentes de nuestros circuitos.

Internamente incluye ciertas conexiones entre las perforaciones que debemos conocer.

Estas conexiones internas nos permiten conectar nuestros componentes en función de dónde los coloquemos.


Encender un led

Este será nuestro primer proyecto y empezaremos por lo más sencillo. Vamos a encender y apagar un led a intervalos predefinidos.

El led es un componente electrónico emisor de luz ampliamente utilizado como indicador. Se trata de un componente con polaridad, es decir, tiene un terminal positivo y otro negativo. Generalmente los leds tienen las patitas de distinta longitud, la pata corta es la negativa. Si miramos el interior del led al trasluz, el terminal más grande es el negativo.

Lo utilizaremos siempre junto con una resistencia conectada en serie. El valor de la resistencia dependerá de la tensión con la que alimentemos el led. En este caso la tensión es de 5V (el voltaje entregado por los pines de Arduino UNO) y la resistencia será de 220Ω.

El circuito que vamos a montar es el siguiente. Prestar especial atención a la polaridad del led, la pata negativa tenemos que conectarla al pin GND de la placa de Arduino UNO y la pata positiva a la resistencia. La otra pata de la resistencia la conectamos al pin 2 de Arduino.

La imagen anterior representa el montaje más o menos realista. El esquema del circuito es el siguiente:

Ya tenemos el circuito montado. Ahora tenemos que hacerlo funcionar. Pasamos a la parte de programación.

Suponiendo que tenemos el IDE de Arduino instalado y configurado, creamos un nuevo sketch y escribimos el siguiente código (podemos copiar y pegar, por supuesto).

#define LED_PIN 2

void setup() {
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  digitalWrite(LED_PIN, HIGH);
  delay(250);
  digitalWrite(LED_PIN, LOW);
  delay(250);
}

Quizá sea esta la parte más compleja de nuestro proyecto. Si tenemos la sensación de no entender nada, que no cunda el pánico, la programación tiene su miga y tenemos que ir cogiéndole el truqui. Vamos a analizar el código por partes.

En la primera línea indicamos que nuestro led lo hemos conectado al pin 2 de Arduino.

#define LED_PIN 2

La siguiente parte del programa es la función setup()

void setup() {
  pinMode(LED_PIN, OUTPUT);
}

Esta función se ejecuta una única vez cuando se enciende el circuito. Dentro de la función setup() tenemos la instrucción

pinMode(LED_PIN, OUTPUT);

La función pinMode le está indicando a la placa de Arduino que el pin 2 (LED_PIN) debe ser tratado como un pin de salida (OUTPUT). Esto quiere decir que es la placa de Arduino la que enviará la señal de encendido.

Cuando el pin va a recibir una señal, en vez de enviarla (desde un sensor, por ejemplo) usaremos la palabra INPUT.

El siguiente bloque de código es la función loop()

void loop() {
  digitalWrite(LED_PIN, HIGH);
  delay(250);
  digitalWrite(LED_PIN, LOW);
  delay(250);
}

Esta función se ejecuta indefinidamente, después de la función setup(). El contenido de la función loop() se ejecuta una y otra vez hasta que se apaga la placa de Arduino.

La primera instrucción dentro de la función loop() es

digitalWrite(LED_PIN, HIGH);

Esta instrucción enciende el led. Le está indicando a la placa de Arduino que el pin 2 (LED_PIN) se ponga en nivel alto (HIGH), es decir, a 5V. Esto da una tensión de alimentación al led y lo enciende.

La siguiente instrucción

delay(250);

indica un tiempo de espera. El programa se detendrá durante 250 milisegundos antes de continuar.

Las dos siguientes instrucciones son las mismas que las anteriores, pero esta vez apagan el led (LOW) y el programa se detiene otros 250 milisegundos.

Estas instrucciones, al estar dentro de la función loop(), se repetirán indefinidamente por lo que el led se encenderá, se mantendrá encendido el tiempo especificado, se apagará, permanecerá apagado durante ese tiempo y el proceso se repetirá hasta que apaguemos el circuito.

Ejecutando “Subir” (”Upload”) en el IDE de Arduino cargaremos el programa en la placa y el led debería comenzar a parpadear a intervalos de 1/4 de segundo.

Podemos modificar el tiempo de parpadeo cambiando el número de milisegundos de la función delay. Podemos hacer que el led esté encendido un tiempo dado y apagado un tiempo distinto si ponemos valores distintos en las dos instrucciones delay.

Resumen

Un led siempre debe ir montado en serie con una resistencia. Si la alimentación es de 5V, la resistencia debe ser de 220Ω.
La función setup() se ejecuta una vez cuando se enciende la placa de Arduino.
La función loop() se ejecuta después de la función setup() y se repite indefinidamente mientras la placa está encendida.
La función digitalWrite() pone a nivel alto (5V) o nivel bajo (0V) un pin digital de la placa de Arduino.
La función delay() detiene el programa durante el tiempo especificado.


Brillo

El circuito del capítulo anterior junto con su código, nos ha permitido encender y apagar un led. Ahora, usando el mismo circuito pero cambiando el código, vamos a variar la intensidad con la que se enciende el led. Este código es un poquito más complejo que el anterior, así que atención.

Creamos un nuevo sketch y escribimos el siguiente código:

#define LED_PIN 3

int level = 0;

void setup() {
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  if(level == 255)
    level = 0;

  analogWrite(LED_PIN, level++);
  delay(50);
}

Echando un vistazo a este nuevo código, vemos tres diferencias importantes respecto del código anterior. Por un lado, el led lo conectamos a pin 3, no al 2. La segunda diferencia es que definimos la variable level, y además, usamos la función analogWrite en vez de usar digitalWrite como antes.

En la segunda línea del código definimos la variable level con el valor cero.

int level = 0;

Esta variable se define de tipo int para contener números enteros, y se le asigna el valor cero. Va a contener el nivel de brillo que queremos aplicar al led.

La función setup() es idéntica a la del código anterior y no requiere ninguna explicación adicional.

El contenido de la función loop() sí es diferente y requiere aclaraciones. El primer bloque de código

if(level == 255)
	level = 0;

La primera línea de este bloque usa la sentencia if (condicional) y debe entenderse como: “si level es igual a 255”. La segunda línea indica lo que debe hacerse si se cumple la condición anterior. Estas dos líneas le están diciendo a la placa de Arduino UNO que si en algún momento la variable level tiene el valor 255, se le asigne el valor cero. Ahora veremos la razón de hacer esto.

El segundo bloque de código establece el brillo del led:

analogWrite(LED_PIN, level++);
delay(50);

Así como la función digitalWrite() usada anteriormente, nos permitía poner un pin a nivel alto (5V) o nivel bajo (0V), la función analogWrite() permite indicar el voltaje que queremos poner en un pin PWM. Es necesario que el pin utilizado en esta función soporte señales PWM (los serigrafiados con ~), por eso en este caso hemos usado el pin 3 y no el pin 2 como usábamos en el capítulo anterior.

El segundo parámetro de la función analogWrite() indica el voltaje que queremos obtener. Este parámetro acepta valores enteros entre 0 y 255, de manera que el valor 0 corresponde a 0V y el 255 corresponde a 5V.

El operador ++ aplicado a la variable level en la función analogWrite() hace que level se incremente en una unidad después de ejecutar la función. Esto hace que en cada ejecución de la función loop(), la variable level se incremente en una unidad.

Ahora vemos el sentido de la sentencia if usada anteriormente. La variable level empieza con valor 0, en cada ejecución de la función loop() se incrementa en una unidad cada 50 milisegundos (delay(50)) y cuando llega a tener un valor de 255 se vuelve a poner a 0. Esto hará que el voltaje aplicado al led empiece con 0, se incremente en cada ejecución del loop() y, cuando llegue a 5V se volverá a poner a 0V. Con esto obtenemos que el led empiece apagado, vaya incrementando su brillo hasta llegar al nivel máximo, se apague de nuevo y se repita el proceso mientras el circuito esté encendido.

Resumen

Podemos definir variables que contengan valores útiles.
La función analogWrite() permite indicar el voltaje que queremos obtener de un pin PWM.
El operador ++ incrementa una variable cada vez que se ejecuta.


Semáforo

Seguimos adentrándonos en el mundo Arduino trabajando con leds. En este capítulo vamos a simular el funcionamiento de un semáforo. Para ello usaremos tres leds, uno rojo, uno amarillo y uno verde. El circuito es idéntico al de capítulos anteriores, pero por triplicado.

Como vamos a controlar el encendido y apagado de tres leds, necesitaremos usar tres pines de Arduino, por ejemplo usaremos los pines 2, 3 y 4.

El esquema del circuito a montar es el siguiente:

Montado en la protoboard, quedaría algo así:

Veamos ahora el código necesario para hacer funcionar nuestro semáforo. Ya sabemos cómo encender y apagar un led así que lo tenemos fácil. El proceso sería el siguiente:

  1. Encender el led verde durante 5 segundos.
  2. Hacer que el led ámbar parpadee 5 veces.
  3. Encender el led rojo durante 4 segundos

Analizando el proceso anterior, vemos que necesitamos 2 acciones: Encender y Parpadear.

En programación, las acciones a realizar se implementan mediante funciones. Una función es un trozo de código que podemos ejecutar cuando queramos. La función Encender podemos implementarla con el siguiente código:

void Encender(int led, int tiempo){
  digitalWrite(led, HIGH);
  delay(tiempo);
  digitalWrite(led, LOW);
}

Esta función recibe dos parámetros de tipo int: el led que queremos encender y el tiempo que queremos mantenerlo encendido. Usando las ya conocidas funciones digitalWrite y delay, lo conseguimos fácilmente.

La función Parpadear es un poquito más compleja. El código es el siguiente:

void Parpadear(int led, int veces){
  for(int i = 1; i <= veces; i++){
    Encender(led, 250);
    delay(250);
  }
}

Parpadear recibe dos parámetros: el led y el número de veces que queremos que parpadee. El parpadeo consiste en repetir el encendido. En programación, las repeticiones se implementar mediante bucles. En el código anterior hemos usado el bucle for.

for(int i = 1; i <= veces; i++){
	...
}

El bucle for se define mediante tres sentencias. La primera indica la variable que va a controlar el bucle y su valor inicial (int i = 1), la segunda indica la condición que debe cumplirse para que el bucle siga repitiéndose (i <= veces) y la tercera sentencia indica el incremento que debe darse a la variable de control en cada repetición (i++). El código incluido en el interior del bucle se repetirá mientras se cumpla la condición especificada en la segunda sentencia.

Ahora que tenemos definido cómo Encender y cómo Parpadear, el programa es sencillo:

void loop() {
  Encender(LED_VERDE, 5000);
  Parpadear(LED_AMBAR, 5);
  Encender(LED_ROJO, 4000);
}

Con todo esto, el programa completo es el siguiente:

#define LED_ROJO 2
#define LED_AMBAR 3
#define LED_VERDE 4

void setup() {
  pinMode(LED_ROJO, OUTPUT);
  pinMode(LED_AMBAR, OUTPUT);
  pinMode(LED_VERDE, OUTPUT);
}

void loop() {
  Encender(LED_VERDE, 5000);
  Parpadear(LED_AMBAR, 5);
  Encender(LED_ROJO, 4000);
}

void Encender(int led, int tiempo){
  digitalWrite(led, HIGH);
  delay(tiempo);
  digitalWrite(led, LOW);
}

void Parpadear(int led, int veces){
  for(int i = 1; i <= veces; i++){
    Encender(led, 250);
    delay(250);
  }
}

Resumen

Podemos definir funciones para realizar acciones.
Si necesitamos repetir un cierto código podemos usar un bucle.


Pulsador

Hasta ahora hemos trabajado con leds. Hemos visto cómo encenderlos y apagarlos, así como controlar el tiempo de encendido. Ahora vamos a introducir un nuevo elemento: el pulsador. Un pulsador es un interruptor momentáneo, mantiene el circuito cerrado cuando lo pulsamos y abierto cuando dejamos de pulsar.

Para encender un led usábamos un pin digital de Arduino que actuaba como pin de salida, es decir, era la placa de Arduino la que daba la orden de encendido. Ahora queremos que la placa de Arduino reciba la señal generada por el pulsador, es decir, vamos a usar un pin digital de Arduino como pin de entrada.

Esta distinción es importante, más adelante veremos cómo indicarlo en el código.

Queremos construir un circuito que al pulsar un pulsador encienda un led y al volverlo a pulsar lo apague. El circuito que tenemos que montar es el siguiente:

En el esquema anterior, la parte izquierda formada por le led y R1 ya la conocemos, nada que comentar. Nos centraremos en la parte derecha del esquema, la formada por el pulsador y R2.

Un pin digital de entrada, en este caso el D3, debe estar en un estado bien definido, puede estar a nivel bajo (0V, conectado a GND) o a nivel alto (5V, conectado al pin 5V) pero no vale tenerlo “al aire” sin conectar a ningún sitio, en este caso podríamos tener resultados inesperados.

En el esquema anterior, si el pulsador está pulsado, el pin D3 está conectado a 5V, es un estado bien definido. Si el pulsador está sin pulsar, el pin D3 está conectado a GND a través de la resistencia R2 de 10KΩ, también está bien definido. Así, cuando pulsamos el pulsador, el pin D3 recibe una señal de 5V y cuando dejamos de pulsar, recibe una señal de 0V. Estos dos estados podemos reconocerlos en el código y saber si el pulsador está pulsado o no.

Para saber si un pin de entrada está a nivel alto o bajo, usaremos la función digitalRead(PIN). Esta función devuelve HIGH si el pin PIN está a nivel alto y LOW si está a nivel bajo. Así pues, si digitalRead(PIN) devuelve HIGH es que el pulsador está pulsado, si devuelve LOW es que no está pulsado.

Podemos definir la función PulsadorPulsado que nos indique si se ha pulsado el pulsador. Entenderemos por pulsación el acto de presionar y soltar el pulsador. Esta función devolverá el valor true (verdadero) si se ha pulsado el pulsador y false (falso) si no se ha pulsado.

bool PulsadorPulsado(){
  if(digitalRead(SW_PIN) == HIGH){
    while(digitalRead(SW_PIN) == HIGH){
      delay(100);
    }
    return true;
  }
  return false;
}

La función se define de tipo bool para indicar que devuelve un valor booleano (true o false, verdadero o falso). Lo primero que hace la función es comprobar si el pin SW_PIN está a nivel alto o bajo.

if(digitalRead(SW_PIN) == HIGH)

La sentencia if(condición){código} ejecuta el código sólo si la condición es verdadera. En este caso, la condición es digitalRead(SW_PIN) == HIGH, es decir, el pin SW_PIN está a nivel alto, osea, el pulsador está pulsado. El operador == es un operador de comparación y se usa para comparar dos valores, no confundir con el operador = que es un operador de asignación.

Si el pulsador está pulsado, se ejecutará el código que hay en el interior de la sentencia if, si no está pulsado, no se ejecutará. Si el pulsador no está pulsado, la siguiente instrucción que se ejecuta es return false y la función PulsadorPulsado devuelve el valor false.

Si el pulsador está pulsado, se ejecuta el código interno a la función if:

 while(digitalRead(SW_PIN) == HIGH){
    delay(100);
 }
 return true;

Este código espera hasta que se deje de pulsar el pulsador y devuelve true. El bucle while(condición) se repite mientras la condición sea verdadera. En este caso, se repetirá delay(100) hasta que dejemos de pulsar el pulsador. Cuando dejemos de pulsar, el bucle termina y la función PulsadorPulsado devuelve true.

Ya tenemos controlado el pulsador, ahora queremos que cada vez que se pulsa, cambie el estado del led. Definimos la función CambiaEstadoLed:

void CambiaEstadoLed(){
  if(EstadoLed == false){
    digitalWrite(LED_PIN, HIGH);
    EstadoLed = true;
  }
  else{
    digitalWrite(LED_PIN, LOW);
    EstadoLed = false;
  }
}

Esta función es sencilla y usa la variable EstadoLed de tipo bool. Esta variable la ponemos a true cuando el led está encendido y a false cuando está apagado. Usamos la sentencia if(condición){código1}else{código2} que ejecuta código1 si condición es verdadera y código2 si es falsa. Por tanto, si EstadoLed es falso, encendemos el led y ponemos EstadoLed en verdadero, si no, apagamos el led y ponemos EstadoLed en falso.

Por último, sólo comentar que el pin que usemos para saber el estado del pulsador tenemos que declararlo como pin de entrada y el pin que usemos para controlar el led será un pin de salida. Esto lo hacemos en la función setup:

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(SW_PIN, INPUT);
}

Con todo esto, el código completo es el siguiente:

#define LED_PIN 2
#define SW_PIN 3

bool EstadoLed = false;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(SW_PIN, INPUT);
}

void loop() {
  if(PulsadorPulsado())
    CambiaEstadoLed();
}

bool PulsadorPulsado(){
  if(digitalRead(SW_PIN) == HIGH){
    while(digitalRead(SW_PIN) == HIGH){
      delay(100);
    }
    return true;
  }
  return false;
} 

void CambiaEstadoLed(){
  if(EstadoLed == false){
    digitalWrite(LED_PIN, HIGH);
    EstadoLed = true;
  }
  else{
    digitalWrite(LED_PIN, LOW);
    EstadoLed = false;
  }
}

LDR

Una LDR (light dependent resistor) o célula fotoeléctrica es un componente electrónico cuya resistencia depende de la intensidad de la luz que recibe, decimos que es un sensor de luminosidad.

Vamos a construir un circuito que simule una lámpara nocturna. Si es de día (mucha luz ambiental) la lámpara estará apagada, a medida que anochece, la lámpara se irá encendiendo, alcanzando su máxima luminosidad cuando es de noche (poca luz ambiental).

Dado que tenemos que variar la luminosidad del led de manera continua, como hicimos en el capítulo Brillo, para controlar el led necesitaremos un pin con salida PWM (los serigrafiados con ~), por ejemplo el pin D3.

Para leer el valor de la resistencia ofrecida por la LDR (ya sabemos que depende de la luminosidad ambiental) necesitamos un pin analógico, por ejemplo el A0. Los pines analógicos pueden leer voltajes comprendidos entre 0 y 5V. Nuestro circuito tiene que ser capaz de transformar la resistencia variable de la LDR en un voltaje variable que podamos leer con un pin analógico.

Este es el circuito que vamos a montar:

La parte izquierda del esquema formada por la resistencia R1 y el Led ya la conocemos. Vamos a ver la parte derecha formada por la resistencia R2 y la LDR. El circuito formado por R2 y LDR es muy conocido y tiene el nombre de “Divisor de tensión”.

Un divisor de tensión está formado por dos resistencias en serie cuyos extremos se conectan a GND y 5V. La tensión obtenida en el punto central dependerá de los valores de ambas resistencias.

Vo = Vcc * R2/(R2 + Rldr)

Donde Vo es la tensión en el punto central A0, VCC es la tensión total del divisor de tensión, 5V en este caso, y Rldr es la resistencia de la LDR. Despejando Rldr tenemos

Rldr = R2(Vcc/Vo -1)

Es decir, midiendo V0 podemos saber la resistencia que tiene la LDR, y por tanto, la luminosidad que recibe. La relación entre la resistencia y la luminosidad depende del tipo de material con que está construida la LDR y de la temperatura, no vamos a entrar en esto. Lo importante aquí es tener claro que la tensión que midamos en A0 dependerá de la luminosidad que recibe la LDR.

Para medir la tensión presente en un pin analógico se usa la función analogRead(Pin). La placa de Arduino UNO tiene una resolución en sus pines analógicos de 10 bits, lo que significa que esta función devuelve valores comprendidos entre 0 y 1023 donde 0 corresponde a 0 voltios y 1023 a 5V. Por tanto, podemos definir la función

int LeeLdr(){
  int v0 = analogRead(LDR_PIN);
  if(v0 > MaxLuz) v0 = MaxLuz;
  return v0;
} 

LeeLdr() lee el valor del voltaje presente en LDR_PIN (A0) mediante la función analogRead(pin). Este valor está comprendido entre 0 y 1023. No queremos que el led se encienda hasta que la luminosidad baje de cierto umbral, por eso usamos la variable MaxLuz que representa la luminosidad máxima por debajo de la cual empezará a encenderse el led, los valores mayores que MaxLuz los ignoramos con if(v0 > MaxLuz) v0 = MaxLuz;. Por tanto, la función LeeLdr() devuelve un valor comprendido entre 0 y MaxLuz.

Para encender el led definimos la función EnciendeLed(int luminosidad) que ya la conocemos del capítulo Brillo.

void EnciendeLed(int intensidad){
  analogWrite(LED_PIN, intensidad);
}

Para poder relacionar estas dos funciones, debemos tener en cuenta que ambas trabajan en rangos de valores distintos. LeeLdr() devuelve valores entre 0 y MaxLuz, EnciendeLed() acepta valores entre 0 y 255. No podemos pasar a EnciendeLed() el valor devuelto por LeeLdr() sin más.

Para transformar una valor de un rango a otro se usa la función map(). Esta función es un cambio de escala, la sintaxis es la siguiente:

xz = map(xy, ymin, ymax, zmin, zmax)

Esta función convierte un valor xy en el rango (ymin, ymax) a un valor xz en el rango (zmin, zmax). En nuestro caso, queremos convertir un valor en el rango (0, MaxLuz) a un valor en el rango (0, 255), además, queremos que cuanto mayor sea la luminosidad ambiental, menor sea la intensidad en el led. Por tanto, el cambio de escala será el siguiente

map(v0, 0, MaxLuz, 255, 0);

Con todo esto, el programa completo es el siguiente:

#define LED_PIN 3
#define LDR_PIN A0

int MaxLuz = 850;

void setup() {
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  int v0 = LeeLdr();
  EnciendeLed(map(v0, 0, MaxLuz, 255, 0));
  delay(50);
}

int LeeLdr(){
  int v0 = analogRead(LDR_PIN);
  if(v0 > MaxLuz) v0 = MaxLuz;
  return v0;
} 

void EnciendeLed(int intensidad){
  analogWrite(LED_PIN, intensidad);
}

También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *