RETO 8: EL POTENCIÓMETRO, UN INPUT ANALÓGICO.

En esta robótica ocasión vamos a trabajar las ENTRADAS ANALÓGICAS o ANALOG INPUTS (AI).

El protagonista indiscutible de este reto va a ser el POTENCIÓMETRO y, al igual que para llegar a construir muy alto hay que empezar por unos buenos cimientos, vamos a iniciar nuestro reto por entender el funcionamiento básico de este resistor variable (y no fijo, como los que usamos en el reto de encender un led, aquí).

Un potenciómetro o resistor variable presenta un contacto móvil que se desplaza a lo largo de una pista resistiva. De esta forma, al mover el potenciómetro, linealmente o girándolo, movemos el contacto a lo largo de la pista por lo que variamos la longitud del tramo de pista con el que estamos en contacto y, por tanto, variamos el valor de su resistencia.

.

¿Cómo funciona un potenciómetro en arduino?

.

Normalmente un potenciómetro tiene tres terminales, dos fijos: uno conectado a 5V, otro a masa o GND, y el tercer terminal, variable y situado en el medio, será quien vaya conectado a nuestra entrada analógica.

.

partes de un potenciómetro en arduino

.

Los dos terminales extremos (en el esquema superior el nº 1 y 3) están unidos a ambos lados de la pista, por lo que siempre registrarán la resistencia máxima a su paso entre ellos, Rmax. El terminal restante corresponde al contacto móvil (en esquema el nº 2). Este terminal varia su resistencia respecto a los otros dos terminales a medida que accionamos el potenciómetro, siendo la suma de la resistencia a los otros dos terminales igual a Rmax (es decir, de 1 a 2 + de 2 a 3 = Rmax).

En el mercado podemos encontrar potenciómetros de tipo lineal o rotativo. Los lineales presentan una proporcionalidad entre resistencia y desplazamiento, lo cuál significa un comportamiento más intuitivo. Mientras, los exponenciales permiten mayor precisión en valores de resistencia bajos, por lo que resultan adecuados cuando hace falta un ajuste fino en un amplio rango.

.

POTENCIÓMETROS DE TIPO LINEAL

potenciometro lineal arduino potenciometro lineal arduino

POTENCIÓMETROS DE TIPO ROTATIVO

potenciometro arduino tipo rotativo potenciometro arduino tipo rotativo

.

En Arduino podemos encontrar 6 pines o entradas analógicas (A0-A5). Internamente, Arduino tiene un conversor analógico-digital que mapea la tensión recibida a un número entero. Los valores van desde 0V igual a 0, hasta 5V igual a 1023. El resto de los valores se calculan de manera proporcional.

Vamos a realizar un montaje del potenciómetro y comprobaremos a través del monitor de puerto serie cómo van variando los valores desde 0 a 1023.

El esquema de montaje sería como se puede ver a continuación:

.

esquema montaje potenciómetro arduino

 

.

Una vez realizado el montaje, procederemos a cargar desde el IDE el programa que podemos encontrar en Ejemplos>Basics>AnalogReadSerial.

La instrucción que utilizamos dentro de la funcicón loop (); para leer un valor análogico conectado al pin analógico A0, en nuestro programa es la siguiente:

int sensorValue = analogRead(A0);

Por supuesto no podremos olvidar en la sección previa, en la función setup (); la siguiente instrucción, que nos permitirá configurar la comunicación serie entre nuestro arduino y el ordenador a 9600 bits de información por segundo:

Serial.begin(9600);

Con la creación de la variable sensorValue, de tipo entero (integer), leeremos la entrada analógica AO y guardaremos su valor en dicha variable, que posteriormente vamos a utilizar para visualizarla a través del puerto serie con una pausa entre valores de 1 milisegundo. En el siguiente código:

Serial.println(sensorValue);  // print out the value you read
delay(1);                     // delay in between reads for stability

Abriremos el monitor del puerto serie y comprobaremos cómo van variando los valores de 0 a 1023 en función de cómo vamos girando nuestro potenciómetro.

Podemos ver la información completa de la guía oficial en este enlace.

EXTRA BALL 1 – JUGANDO CON LA VELOCIDAD DE PARPADEO

El objetivo de este reto es montar un led de tal forma que varíe la velocidad de parpadeo en función de cómo utilicemos nuestro potenciómetro. El esquema de montaje sería el siguiente:

.

potenciómetro + 1 led arduino esquema montaje

.

A continuación cargamos el programa desde Ejemplos>Analog>AnalogInput. La instrucción que utilizamos para leer un valor análogico en nuestro programa es la siguiente:

sensorValue = analogRead(sensorPin);

de esta forma leeremos la entrada analógica A0 y guardaremos su valor en la variable sensorValue, que posteriormente vamos a utilizar entre las dos instrucciones digitalWrite para establecer la pausa entre el encendido y el apagado del led. A mayor valor del potenciómetro, mayor será la espera entre el encendido y el apagado, y por lo tanto, más lento el cambio de estado. Lo podemos ver en el siguiente trozo de código:

digitalWrite(ledPin, HIGH);     // turn the ledPin on
delay(sensorValue);             // stop the program for milliseconds
digitalWrite(ledPin, LOW);      // turn the ledPin off
delay(sensorValue);             // stop the program for for milliseconds

La guía oficial la podemos encontrar en el siguiente enlace.

 

EXTRA BALL 2 – JUGANDO CON EL BRILLO DEL LED 

En este reto, manteniendo el mismo montaje, vamos a variar el código para que la intensidad de brillo de nuestro led esté en función de los valores del potenciómetro. Para ello cargaremos el programa de la librería ejemplos desde la ruta Ejemplos>Analag>AnalogInOutSerial. En este código merece la pena destacar dos instrucciones especialmente:

outputValue = map(sensorValue, 0, 1023, 0, 255);  // map it to the range of the analog out
analogWrite(analogOutPin, outputValue);           // change the analog out value

Con la función map() lo que hacemos es partiendo del valor de nuestro potenciómetro, y sabiendo que se puede mover entre los valores 0 y 1023, hacer una regla de tres a los valores que puede recibir un led para que brille «más o menos» y que van desde el 0 al 255. De esta forma cuando el mando del potenciómetro esté a la mitad de su recorrido, por ejemplo, la salida PWM estará proporcionando una señal cuadrada con el mismo tiempo a nivel alto (HIGH) que a nivel bajo (LOW). Esto ocurrirá de forma proporcional con cualquiera de las posiciones en las que pongamos el control del potenciómetro.

Este cambio de rango suele ser bastante habitual en los programas. La sintaxis de la función map() es la siguiente:

map(valor, minEntrada, maxEntrada, minSalida, maxSalida)

Donde:

valor: número (entero. La función map sólo trabaja con números enteros) que queremos cambiar de rango.

minEntrada: valor mínimo del rango de entrada.

maxEntrada: valor máximo del rango de entrada.

minSalida: valor mínimo del rango de salida.

maxSalida: valor máximo del rango de salida.

Con la función analogWrite() lo que hacemos es poner ese valor calculado en el led indicado, lo que finalmente se traduce en una tensión para dar más o menos brillo al led.

La guía oficial la podemos encontrar aquí. Hay que prestar especial atención en este reto a que el pin digital del led es de lectrua PWM, PulseWidth Modulation (PWM) para configurarlo como output analógico, más información al respecto del funcionamiento de las salidas PWM en el Reto10: LED RGB, JUGANDO CON LOS COLORES PRIMARIOS DE LA LUZ

El esquema de montaje sería el siguiente:

.

 

potenciómetro + 1 led pwm

.

El código completo sería el siguiente:

// These constants won't change. They're used to give names
// to the pins used:
const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to

int sensorValue = 0; // value read from the pot
int outputValue = 0; // value output to the PWM (analog out)

void setup() {
 // initialize serial communications at 9600 bps:
 Serial.begin(9600); 
}

void loop() {
 // read the analog in value:
 sensorValue = analogRead(analogInPin); 
 // map it to the range of the analog out:
 outputValue = map(sensorValue, 0, 1023, 0, 255); 
 // change the analog out value:
 analogWrite(analogOutPin, outputValue);

// print the results to the serial monitor:
 Serial.print("sensor = " ); 
 Serial.print(sensorValue); 
 Serial.print("\t output = "); 
 Serial.println(outputValue);

// wait 2 milliseconds before the next loop
 // for the analog-to-digital converter to settle
 // after the last reading:
 delay(2); 
}

.

EXTRA BALL 2.1 – OPTIMIZANDO EL CONTROL DEL BRILLO DEL LED 

Ahora te propongo que determines el valor mínimo de salida del led (pindigital con salida PWM) al que empieza a iluminarse, y el valor máximo a partir del cual ya no apreciamos que luzca más.

Una vez que hayas determinado estos dos valores (pista: los tendrás que encontrar lógicamente observando los valores por el monitor serie) tendrás que modificar el código para poder usar todo el rango del potenciómetro para controlar el brillo del led. Como si quisiéramos optimizar todo el rango de recorrido del potenciómetro.

EXTRA BALL 2.2 – CONTROLANDO UN SERVO DE 180º EN FUNCIÓN DEL POTENCIÓMETRO 

Una de las aplicaciones más interesantes, consiste en controlar un servomotor de 180º (OUTPUT) en función de los valores del potenciómetro (INPUT). Es interesante entender cómo realiza un mapeo de los valores del input analógico (servo) -desde 0 a 1023- y los adapta al rango de valores del servomotor -de 0 a 180º-.

La ruta para abrir este ejemplo dentro de la librería de archivos del Software de Arduino es: Archivo > Ejemplos > Servo > Knob

Conviene atender la función map(); en este caso map(val, 0, 1023, 0, 180) vemos los 5 parámetros que definen el intervalo. El efecto que consigue no es otro sino escalar un valor determinado (val) en un rango concreto y convertirlo en un nuevo valor dentro de un rango diferente. No es más que una regla de tres.

  • val: variable de almacenamiento del dato leído por el potenciómetro (sensor analógico) la cual convertimos y escalamos a un nuevo rango.
  • 0: valor inicial del sensor dentro del primer rango (0, 1023).
  • 1023: valor final del sensor dentro del primer rango (0, 1023).
  • 0: valor inicial de conversión dentro del segundo rango (0, 180).
  • 180: valor final de conversión dentro del segundo rango (0, 180).
#include <Servo.h>

Servo myservo; // create servo object to control a servo

int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin

void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}

void loop() {
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180)
myservo.write(val); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
}

EXTRA BALL 3 – JUGANDO CON EL ENCENDIDO DE 6 LEDS SEGÚN NUESTRO POTENCIÓMETRO 

Para finalizar, un reto algo exigente a estas alturas: montaje de 6 leds para que se vayan encendiendo led a led a media que aumentamos el valor que transmite el potenciómetro. Quedaría algo parecido al siguiente esquema:

.

potenciómetro + 6 leds digitales

.

A partir de aquí tendremos que añadir el siguiente código a nuestro nuevo programa que cargaremos en Arduino:

int i = 0;

int pinPotenciometro = A0;
int valorPotenciometro = 0;
int pinLed1 = 8;
int pinLed2 = 9;
int pinLed3 = 10;
int pinLed4 = 11;
int pinLed5 = 12;
int pinLed6 = 13;

void setup()
 {
 pinMode(pinPotenciometro, INPUT);
 pinMode(pinLed1, OUTPUT);
 pinMode(pinLed2, OUTPUT);
 pinMode(pinLed3, OUTPUT);
 pinMode(pinLed4, OUTPUT);
 pinMode(pinLed5, OUTPUT);
 pinMode(pinLed6, OUTPUT);
 Serial.begin(9600);
 }

void loop()
 {
valorPotenciometro = analogRead(pinPotenciometro);
Serial.println(valorPotenciometro, DEC);
delay(100);

//preguntamos y en función del valor del potenciómetro encendemos el pin correspondiente
if (valorPotenciometro >= 10 && valorPotenciometro < 200) digitalWrite(pinLed2, HIGH);
if (valorPotenciometro >= 200 && valorPotenciometro < 400) digitalWrite(pinLed3, HIGH);
if (valorPotenciometro >= 400 && valorPotenciometro < 600) digitalWrite(pinLed4, HIGH);
if (valorPotenciometro >= 600 && valorPotenciometro < 800) digitalWrite(pinLed5, HIGH);
if (valorPotenciometro >= 800 && valorPotenciometro < 900) digitalWrite(pinLed6, HIGH);
if (valorPotenciometro >= 900) digitalWrite(pinLed7, HIGH);

//si el valor es menor de diez, ordenamos apagar todos los leds con una función que llamaremos apagarLeds()
if (valorPotenciometro < 10 ) apagarLeds();
 }

//la siguiente función tiene una estructura de control for o bucle que ejecutará 6 veces la instrucción de apagar el led correspondiente
//se sabe el led que tiene que apagar por la variable “i” que tendrá valores desde el inicial 8 hasta el final 13
//esta estructura de control for la trabajamos en el RETO 1 ENCENDER Y APAGAR UN LED: https://educarparaelcambio.com/arduino/reto-1-encender-y-apagar-un-led/

void apagarLeds() 
 {
 for (i = 8; i < 14; i++)
  digitalWrite(i, LOW);
 }

Como os podréis fijar los leds se van encendiendo conforme nuestro potenciómetro va subiendo de valores, sin embargo para apagarlos tengo que bajar a un valor < 10, para que se apaguen todos a la vez.

Te lanzo el siguiente reto: ¿¿Serías capaz de programarlo para que fueran apagándose conforme el potenciómetro fuera bajando de valores??