Archivo

Posts Tagged ‘Señales analógicas’

Proyecto Arduino I: Lectura limpia de potenciómetro para control de servomotor.

30 abril, 2011 8 comentarios

Banner Arduino Proyecto I

Después de un largo tiempo de no escribir una entrada en el blog (o como menos, terminar una ya que tengo unos cuantos temas en los borradores), vuelvo a darle vida dando inicio a una serie de artículos que tratarán sobre proyectos hechos o basados en la plataforma de Hardware Libre “Arduino”. Éstos estarán dirigidos como guía o referencia para aquellos que comienzan a experimentar con dicha plataforma o simplemente para conocer otras distintas maneras de llevar a cabo una función.

Sobre señales analógicas y potenciómetros.

Señal analógica continua

Señal analógica uniforme.

Por definición, las señales analógicas generan lecturas eléctricas que varían constantemente en amplitud y/o en periodo en función del tiempo, mismas que pueden ser erráticas y altamente variables o bien, pueden mostrar un patrón estable de cambio.

Al ocupar un potenciómetro para variar la intensidad de corriente, obtenemos una lectura analógica de cambio que depende mucho de la fabricación de dicho componente, ya que existen potenciómetros lineales, logarítmicos, senoidales y antilogarítmicos.

Por lo que respecta a éste proyecto, se utilizará un potenciómetro logarítmico dada su facilidad para conseguir uno debido a su muy bajo precio y su amplia distribución que permite encontrarlo en cualquier tienda de electrónica; además que permite ilustrar mediante el uso de la placa Arduino el cómo estabilizar una señal cuando ésta posee demasiado “ruido”.

Señal analógica con ruido

Señal analógica con ruido.

Proyecto.

El proyecto consiste en poder utilizar un potenciómetro como perilla de control de giro de un servomotor.

Existen por lo menos dos problemas a resolver para que el giro del servomotor sea equivalente al giro de un potenciómetro:

  1. La escala logarítmica del potenciómetro hay que transformarla a una escala de cambio lineal.
  2. El potenciómetro tiene como valor resistivo máximo hasta 10,000 Ω. Valores resistivos grandes llegan a generar “ruido” en la línea de entrada analógica, por lo que habrá que emplear una especie de “filtro” capaz de reducir dichas interferencias.

Material utilizado.

  • 1 x Placa Arduino UNO (Cualquier otra que utilice ATMega168 o ATMega328 funciona bien).
  • 1 x Potenciómetro logarítmico 10 KΩ.
  • 1 x Servomotor Hitec HS-322HD.
  • 1 x Protoboard.

Circuito.

Circuito Proyecto I Arduino

Click para agrandar.

Esquema.

Esquema Proyecto I Arduino

Click para agrandar.

Gráficos creados usando Fritzing.

Código.

  • Primer código.

En este primer código recibimos la lectura de la señal analógica (A0), los niveles de intensidad de corriente son automáticamente mapeados a 1024 niveles (Los valores por defecto de las entradas analógicas del ATMega328), pero éstos tienen que ser re-mapeados nuevamente para asignarles una equivalencia hasta 180 niveles (que son los valores de giro de un servomotor) mediante la función Map.

#include <Servo.h>
Servo MiServo;
int Senal;

void setup(){
MiServo.attach(9); Serial.begin(9600);
}

void loop() {
//  Lee la señal del potenciómetro por el pin A0 (Pin 23 del ATMega328).
Senal = analogRead(A0);
//  Adapta la lectura de 1024 niveles a 180 niveles para el Servomotor.
Senal = map(Senal, 0, 1023, 0, 179);
//  Manda la señal corregida al Servomotor y a la Consola Serial.
MiServo.write(Senal);
Serial.println(Senal, DEC);
//  Pequeño retardo para apreciar mejor las variaciones de la señal.
delay(30);
}

La desventaja en éste código radica en que asigna todos y cada uno de los valores remapeados de la señal analógica, incluídos los movimientos erráticos debido al “ruido” generado en el circuito.

  • Segundo código (Supresión de ruido)

En ésta revisión del código se realizan las mismas operaciones que en el anterior, agregando un pequeño “filtro” basado en una simple operación que coloca en un vector de 10 elementos los valores de 10 lecturas de la entrada analógica y realiza un cálculo promedio de los mismos.

#include <Servo.h>

int Lecturas[10]; //Vector de lecturas.
int Val, i = 0, Total = 0, Promedio = 0;
Servo MiServo;

void setup(){
MiServo.attach(9);
Serial.begin(9600);
for(i=0; i< 10; i++) //Inicialización del vector.
Lecturas[i] = 0;
i=0;
}

void loop(){
//Sustrae el total con la lectura inmediata anterior
Total = Total – Lecturas[i];
//Agrega una lectura a la posición actual dentro del vector
Lecturas[i] = analogRead(A0);
//Realiza la sumatoria entre lecturas
Total = Total + Lecturas[i];
i = i + 1;
//Calcula el promedio y envía el resultado al servomotor
if (i >= 10){
i = 0;
Promedio = Total / 10;
Val = map(Promedio, 0, 1023, 0, 179);
MiServo.write(Val);
Serial.println(Val, DEC);
}
}

Mientras más capacidad de elementos contenga el vector (Por ejemplo, int Lecturas[30]) más exacto será el promedio y disminuirá considerablemente aún más el ruido, aunque un número muy elevado hará que el almacenamiento de lecturas requiera más tiempo de procesamiento haciendo que el desplazamiento del servomotor en vez de ser fluído, haga giros “a saltos”.

En ambos códigos se utiliza el envío de datos por comunicación serial, ésta parte del código puede ser eliminado sin mayor problema, únicamente está presente para darle seguimiento a las lecturas utilizando la consola “Serial Monitor” de Arduino.

Serial Monitor

Ubicación del botón "Serial Monitor" en la ventana de Arduino.

Video del proyecto.

En este video se muestra la implementación de ambos códigos, sus repercusiones en el movimiento del servomotor y se muestra las variaciones de la lectura de la señal analógica en la consola “Serial Monitor”.

Para concluir, a lo largo de éste proyecto se ha ejemplificado la programación de vectores, el uso de comunicación serial, lectura de señales analógicas, el remapeo de un intervalo de valores a otro y la manipulación de un servomotor.

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.