El objetivo es estudiar el comportamiento de la medida de
sensores con el fin de mejorar la toma de valores de dichos sensores realizando
un calibrado y reducción del ruido.
Se dispone de un sensor de luz LDR para obtener la
luminosidad. Como referencia se utiliza el sensor de luz presente en un
Smartphone a través de la aplicación Lux Meter.
A continuación, se expone el esquema de conexiones que se
utilizará durante la ejecución de las pruebas necesarias
Cálculo del rando real de valores, puntos de la curva de transferencia y descripción de la linealidad
Para realizar los calculos pertinentes se desarrolla el siguiente código .ino:
#define ldr
A0
void
setup() {
pinMode(ldr,INPUT);
Serial.begin(9600);
}
void loop()
{
int lx=analogRead(ldr);
Serial.println(lx);
delay(1000);
}Mientras se obtienen las medidas del sensor es necesario obtener la luminosidad a traves de la aplicacion LuxMeter. Es necesario obtener un conjunto de valores representativos de todo el rango. Para cada medida obtenida se obtiene la medida real en la aplicacion:
Si se representan los datos obtenidos en un grafico se obtiene lo siguiente:
Calibración del offset y sensibilidad asumiendo que la curva es lineal
Realizando una regresion lineal de los datos obtenidos anteriormente es posible obtener lo siguiente:A partir de la regresion lineal se obtiene que la sensibilidad es 193,5 y el offset es 95,9
Calcular media, mediana y moda
Para calcular estas variables es necesario mantener la luminosidad constante y obtener varios valores:A través de los resultados se concluye que las medidas que obtiene el sensor son estables, es decir, sin variaciones bruscas. Con dichos resultados es posible determinar los parametros para los siguientes apartados
Calcular la media movil y mostrarla por pantalla. Inferir un valor adecuado para la tolerancia
De los resultados anteriores se deduce que la tolerancia
debería ser 1 (aproximación de la desviación típica). Debido a que este valor
de tolerancia es demasiado estricto se opta por seleccionar el valor 2.
El algoritmo para el cálculo de la media móvil es el
siguiente
El codigo .ino generado a partir del algoritmo anterior es el siguiente
#define ldr
A0
int in;
int arr_med[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int leng_med = 10;
int med_min = 8;
int med_max = 913;
int old_index = 0;
int out = 0;
int in;
int arr_med[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int leng_med = 10;
int med_min = 8;
int med_max = 913;
int old_index = 0;
int out = 0;
int
out_temp = 0;
int tol = 0;
void setup() {
// put your setup code here, to run once:
pinMode(ldr, INPUT);
for(int i=0; i<leng_med;i++){
arr_med[i]=0;
}
leng_med = 10;
med_min = 10;
med_max = 950;
old_index = 0;
out = 0;
out_temp = 0;
tol = 2;
Serial.begin(9600);
}
int mean_med() {
float sum = 0;
for (int i = 0; i < leng_med; i++) {
sum = sum + arr_med[i];
}
return round(sum / leng_med);
}
void loop() {
in = analogRead(ldr);
while (in < med_min && in > med_max) {
in = analogRead(ldr);
}
arr_med[old_index] = in;
old_index = (old_index + 1) % leng_med;
int mean = mean_med();
if (in > (mean - tol) && in < (mean + tol)) {
out = mean;
}
Serial.println(out);
delay(500);
}
int tol = 0;
void setup() {
// put your setup code here, to run once:
pinMode(ldr, INPUT);
for(int i=0; i<leng_med;i++){
arr_med[i]=0;
}
leng_med = 10;
med_min = 10;
med_max = 950;
old_index = 0;
out = 0;
out_temp = 0;
tol = 2;
Serial.begin(9600);
}
int mean_med() {
float sum = 0;
for (int i = 0; i < leng_med; i++) {
sum = sum + arr_med[i];
}
return round(sum / leng_med);
}
void loop() {
in = analogRead(ldr);
while (in < med_min && in > med_max) {
in = analogRead(ldr);
}
arr_med[old_index] = in;
old_index = (old_index + 1) % leng_med;
int mean = mean_med();
if (in > (mean - tol) && in < (mean + tol)) {
out = mean;
}
Serial.println(out);
delay(500);
}
Usar una tabla lookup para generar un valor linealizado
En este apartado se construye una tabla lockup con el fin de
realizar una regresión lineal utilizando la interpolación.
La tabla lockup utilizada está construida por los mismos
valores que el primer apartado:
El valor linealizado se obtiene a partir de la siguiente formula:
El codigo final en el lenguaje .ino es el siguiente:
#define ldr
A0
int real[5]
= {0, 74, 323, 626, 934};
int
medida[5] = {8, 742, 852, 867, 913};
int n = 5;
void
setup() {
pinMode(ldr, INPUT);
Serial.begin(9600);
Serial.println("Tabla
Lockup");
Serial.println("Medida, Real");
for (int i = 0; i < 5; i++) {
Serial.print(medida[i]);
Serial.print(",");
Serial.println(real[i]);
}
Serial.println("");
Serial.println("-------------");
Serial.println("");
Serial.println("Ejecucion de pruebas");
Serial.println("Medida, Real");
}
void loop()
{
int data_out = 0;
int data_in = analogRead(ldr);
if (data_in < medida[10]) {
data_out = real[0];
} else if (data_in > medida[n - 1]) {
data_out = real[n - 1];
} else {
int i = 1;
while (i < (n - 1) && medida[i]
< data_in) {
i++;
}
data_out = map(data_in, medida[i - 1],
medida[i], real[i - 1], real[i]);
}
Serial.print(data_in);
Serial.print(",");
Serial.println(data_out);
delay(1000);
}Realizar un programa que realice la calibracion lineal, lockuup y muestre valores en base a la media móvil
El programa comenzará pidiendo los valores reales de luminosidad
para rellenar la tabla lockup (calibración inicial) y a continuación comienza
el bucle principal del programa en el que se linealiza la entrada proveniente
del sensor LDR utilizando la tabla lockup, se calcula la media móvil y se
muestra por pantalla el valor de la medida
#define ldr
A0
int real[5]
= {0, 74, 323, 626, 934};
int
medida[5] = {8, 742, 852, 867, 913};
int n = 5;
int
arr_med[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int
leng_med = 10;
int med_min
= 8;
int med_max
= 913;
int
old_index = 0;
int out =
0;
int
out_temp = 0;
int tol =
0;
int
mean_med() {
float sum = 0;
for (int i = 0; i < leng_med; i++) {
sum = sum + arr_med[i];
}
return round(sum / leng_med);
}
void
setup() {
for (int i = 0; i < leng_med; i++) {
arr_med[i] = 0;
}
leng_med = 10;
med_min = 10;
med_max = 950;
old_index = 0;
out = 0;
out_temp = 0;
tol = 2;
pinMode(ldr, INPUT);
Serial.begin(9600);
Serial.println("CALIBRACION DEL SENSOR");
char continuar =
'n';
while (continuar ==
'n') {
Serial.println("A continuacion se deberan introducir 5 valores de
menor a mayor del sensor de iluminacion");
int i = 0;
while (i < n) {
Serial.print("Introduzca el
valor ");
Serial.println((i + 1));
while (!Serial.available()) {}
real[i] = Serial.parseInt();
medida[i] = analogRead(ldr);
i++;
}
Serial.println("Tabla Lockup");
Serial.println("Medida, Real");
for (int i = 0; i < 5; i++) {
Serial.print(medida[i]);
Serial.print(",");
Serial.println(real[i]);
}
do {
Serial.println("¿Los valores son correctos? (y/n)");
while (!Serial.available()) {
}
continuar =
(char)Serial.read();
} while (continuar
!= 'y' && continuar != 'n');
}
med_min = medida[0];
med_max = medida[n -
1];
//sustituir med_min
med_max
Serial.println("");
Serial.println("-------------");
Serial.println("");
Serial.println("Ejecucion de pruebas");
}
void loop()
{
int out = 0;
int in = 0;
int data_out = 0;
int data_in = analogRead(ldr);
Serial.print("ldr");
Serial.println(data_in);
if (data_in < medida[0]) {
data_out = real[0];
} else if (data_in > medida[n - 1]) {
data_out = real[n - 1];
} else {
int i = 1;
while (i < (n - 1) && medida[i]
< data_in) {
i++;
}
data_out = map(data_in, medida[i - 1],
medida[i], real[i - 1], real[i]);
}
in = data_out;
while (in < med_min && in >
med_max) {
in = analogRead(ldr);
}
arr_med[old_index] = in;
old_index = (old_index + 1) % leng_med;
int mean = mean_med();
if (in > (mean - tol) && in <
(mean + tol)) {
out = mean;
}
Serial.println(out);
delay(500);
}
No hay comentarios:
Publicar un comentario