Como crear un array calculado

Hola,

Estoy leyendo un sensor que me devuelve unos resultados no continuos, que significa? que leo un sensor que me devuelve datos con rango:

190 a 199
270 a 280
360 a 375
515 a 540
670 a 685
810 a 830
960 a 985
905 a 920

Lo que le pido son 50 lecturas y hacer la media...al no ser continuo este es el problema.

Que idea tenia en la cabeza? establecer un valor por cada lectura

190 a 199 == 3
270 a 280 == 5
360 a 375 == 6
515 a 540 == 1
670 a 685 == 7
810 a 830 == 12
960 a 985 == 9
905 a 920 == 11

y al sacar la media se acercara a los valores mapeados

 int wdirection = 0;
 int windVanereadings = 50;
 for ( int i = 0 ; i < windVanereadings ; i++ ) {
   direction = analogRead(A1); 
   if (direction >= 190 && direction < 199) 
     wdirection = 3 ;
   else if (direction >= 270 && direction < 280)
     wdirection = 5;
   else if (direction >= 360 && direction < 375)
     wdirection = 6;
   else if (direction >= 515 && direction < 540)
     wdirection = 1;
   else if (direction >= 670 && direction < 685)
     wdirection = 7;
   else if (direction >= 810 && direction < 830)
     wdirection = 12;
   else if (direction >= 960 && direction < 975)
     wdirection = 9;
   else if (direction >= 905 && direction < 920)
     wdirection = 11;
   else
     wdirection = 0;
   wdirection += wdirection;
   Serial.print(wdirection);
   
   delay(50);
 }
 wdirection /= windVanereadings;

Mil gracias por vuestra ayuda

¿y cual es la pregunta?

que no me funciona jajajajaja

si lo harias así o mejor de otra forma :wink:

Hola a todos,

Este es mi codigo:

Pero la media me devuelve cero....el problema es como hacer un map de estas lecturas tan "raras" ya que son "saltos" y hay vacios de datos al no ser unos valores continuos y consecutivos

/*
   Direction PIN A1 with a resistor 9k between A1 and power at 3.5v
*/

int direction = 0;
int Wdeg = 0;
String rosa = "-";

void setup() {

  delay(3000);
  Serial.begin(9600);
  Serial.println("VaneValue-tDirection-Heading-rosa");
  digitalWrite(7, HIGH);       // powering on lines

}

void loop() {
digitalWrite(7, HIGH);       // powering on lines

  int wdirection = 0;
  int windVanereadings = 50;
  for ( int i = 0 ; i < windVanereadings ; i++ ) {
    direction = analogRead(A1); 
    if (direction >= 190 && direction < 199) 
      wdirection = 3 ;
    else if (direction >= 270 && direction < 280)
      wdirection = 5;
    else if (direction >= 360 && direction < 375)
      wdirection = 6;
    else if (direction >= 515 && direction < 540)
      wdirection = 1;
    else if (direction >= 670 && direction < 685)
      wdirection = 7;
    else if (direction >= 810 && direction < 830)
      wdirection = 12;
    else if (direction >= 960 && direction < 975)
      wdirection = 9;
    else if (direction >= 905 && direction < 920)
      wdirection = 11;
    else
      wdirection = 0;
    wdirection += wdirection;
    Serial.print(wdirection);
    
    delay(50);
  }
  wdirection /= windVanereadings;
Serial.print("Media: ");
Serial.print(wdirection);

Mil gracias por vuestra ayuda!!!

Ese es la misma situación que se presenta con el teclado presente en el LCD Shield de Arduino.
El mismo tiene un arreglo de resistencias conectadas al pin A0 y las 6 teclas tienen intervalos determinados.

Yo creo que tu enfoque no esta mal pero lo únido que debes hacer es ser algo mas generoso y no tan estricto con los rangos.
Total, te queda mucho camino entre medio si lo que ocurre son solamente esos estados y solo te importa el valor que orienta la veleta de viento porque supongo que es un sensor indicador de la dirección del viento.

Cuento 8 posiciones o sea los 4 puntos cardinales mas las posiciones intermedias.
Si es asi, entonces amplia el rango y te aseguraras algo mas efectivo.

Esta es la rutina para el teclado, que hay que adaptar a tu caso cuando ajustes los rangos pero mira el error que describo.

int read_LCD_buttons()  
  { adc_key_in = analogRead(0);      // Leemos A0
    // Mis botones dan:  0, 145, 329,507,743
    // Y ahora los comparamos con un margen comodo
    if (adc_key_in > 900) return btnNONE;     // Ningun boton pulsado 
    if (adc_key_in < 50)   return btnRIGHT; 
    if (adc_key_in < 250)  return btnUP;
    if (adc_key_in < 450)  return btnDOWN;
    if (adc_key_in < 650)  return btnLEFT;
    if (adc_key_in < 850)  return btnSELECT; 

    return btnNONE;  // Por si todo falla
  }

y estos tus rangos

190 a 199 Rango 0: 235
270 a 280 Rango 1: 320
360 a 375 Rango 2: 445
515 a 540 Rango 3: 605
670 a 685 Rango 4: 747
810 a 830 Rango 5: 895
960 a 985 Rango 6: Estos ultimos dos tienen un solapamiento Verifica
905 a 920 Rango 7: no es posible que empiece por debajo de 985

Para probar

const int numReadings = 50;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = A1;

void setup() {
  // initialize serial communication with computer:
  Serial.begin(9600);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {
  
  total = total - readings[readIndex];
  readings[readIndex] = analogRead(inputPin);
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
    // poner los rangos correctos a cada punto cardinal.
   if (average >= 220 && average < 300) { Serial.println("Viento Norte")};
   if (average >= 321 && average < 380) { Serial.println("Viento Noreste")};
   if (average >= 400 && average < 460) { Serial.println("Viento Este")};
   if (average >= 480 && average < 520) { Serial.println("Viento Sudeste")};
   // Y continuar para todos los puntos cardinales
   
    readIndex = 0;
  }

  average = total / numReadings;
 
  delay(20);
 
}

No hace falta ningún promedio, solo saber que cae dentro del rango.

surbyte:
No hace falta ningún promedio, solo saber que cae dentro del rango.

¿Porque pide hacer 50 lecturas y tomar la media?

Lo que este usuario tiene que no dijo aquí pero si en el foro en ingles es un veleta que su sensor tiene 8 resistencias unidas en un punto central común y los extremos tocan con el otro conductor. De esta forma lee los 8 puntos cardinales puesto que las ocho resistencias tienen un valór determinado y único, pero tiene un contacto mecánico con lo cual esa es la razón por lo que arduino le lee un valor con diferencias por ejemplo, de 25 entre 960 y 985. Ademas la veleta puede estar moviéndose entre dos puntos cardinales por efecto del viento.

Hola a todos,

el motivo de las 50 lecturas es simple. El viento no es una linea constante, cuando miras una veleta esta se mueve a izquierda y derecha.

Por ejemplo, imaginaros que la veleta mira (o apunta) al norte puro, y la veleta nos da da un valor de 820, este caso es facil, Pero en el entorno real no es asi, el viento no es constante ni con direccion unica por esto la veleta puede moverse desde el NNW (norte noroeste) hasta el NNE (norte Noreste).

Tomo 50 lecturas y promedio, pero el problema viene ya que los valores no son consecutivos y por eso lo traduzco a un sistema correativo (o como dice @Surbyte) simulando un reloj o compas...así puedo promediar y entonces representar la media de lecturas sobre un compas.

Si tomo 50 lecturas a intervalos de 50 milisegundos puedo hacer una estimacion rapida de la direccion del viento.

Por desgracia no puedo jugar con las resistencias, ya que éstas estan dentro del hardware y no me planto modificarlo

Mil gracias por vuestra ayuda

Estoy leyendo un sensor que me devuelve unos resultados no continuos, que significa?

Yo intuí por mi cuenta (hasta el post#6) que se trataba de un sensor de viento simplemente por la semejanza con el LCD Keyboard Shield, de modo que mas alla de como sople el viento variable o no.. me parecía lógico lo propuesto.

Ahora bien si eso no es suficiente pues avanti con el promedio.

Es mas simple cualquier cosa, el tema que ya tiene ESE sensor y le entrega ESA información.
En esas condiciones tal vez el tema del promedio es lo mas conveniente pero.. como dije como adivinarlo?
La consulta empieza con un problema aparentemente de otro tipo hasta que surge el VIENTO como elemento importante y entonces cambia de direccion como la VELETA.

Estria facilisimo si solo tuviesemos una sola lectura, pero el periodo de exposicion es de 2 segundos dividiendo ese tiempo por 50 millis.

Estoy usando este codigo:

/*
   Direction PIN A1 with a resistor 9k between A1 and power at 3.5v
*/

int direction = 0;
int Wdeg = 0;

void setup() {

  delay(3000);
  Serial.begin(9600);
  Serial.println("VaneValue-tDirection-Heading-rosa");
  digitalWrite(7, HIGH);       // powering on lines

}

void loop() {
  digitalWrite(7, HIGH);       // powering on lines

    int wdirection = 0;
    int windVanereadings = 5;
    for ( int i = 0 ; i < windVanereadings ; i++ ) {
  direction = analogRead(A1);
      if (direction >= 190 && direction < 199)
        wdirection = 3 ;
      else if (direction >= 270 && direction < 280)
        wdirection = 5;
      else if (direction >= 360 && direction < 375)
        wdirection = 6;
      else if (direction >= 515 && direction < 540)
        wdirection = 1;
      else if (direction >= 670 && direction < 685)
        wdirection = 7;
      else if (direction >= 810 && direction < 830)
        wdirection = 12;
      else if (direction >= 960 && direction < 975)
        wdirection = 9;
      else if (direction >= 905 && direction < 920)
        wdirection = 11;
      else
        wdirection = 0;
      wdirection += wdirection;
  Serial.println(direction);Serial.print("-");
  Serial.print(wdirection);
direction = 0;
wdirection = 0;
  delay(50);
}
wdirection /= windVanereadings;
Serial.print("Media: ");
Serial.println(wdirection);



delay(5000);
}

Pero estoy teniendo valores "doblados"

961-18
961-18
961-18
960-18
960-18
Media: 0

La veleta esta en posicion 961, pero me devuelve 18, pero deberia ser 9...

Estoy hecho un lio amigos mios

Muchisimas gracias por vuestra ayuda

Hola.

Te devuelve al doble por esto:

wdirection += wdirection;

ecabanas:
Estoy usando este codigo:

¿Y que has hecho con el código que te dejé antes?

Te lo vuelvo a dejar comentado para que primero tomes lectura de cada punto cardinal sin exponer la veleta al viento y vayas anotando el promedio de cada punto cardinal para luego decirle al programa
que valor tiene cada posición de la veleta y así te informe si el viento es sur, oeste etc.

const int numReadings = 50;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = A1;

void setup() {
  // initialize serial communication with computer:
  Serial.begin(9600);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {
 
  total = total - readings[readIndex];
  readings[readIndex] = analogRead(inputPin);
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
   // Para saber que resultado promedio da de leer la veleta en cada punto cardinal haces lo siguiente
   // Serial.println(average);  
   // Si por ejemplo luego de varios segundo de lectura de la veleta en posición 
   // de viento norte arroja un valor de 500 entonces construyes la condición 
   // if (average >= 520 && average < 480) { Serial.println("Viento Norte");}
   // Y continuar para todos los puntos cardinales
   
    readIndex = 0;
  }
  average = total / numReadings;
  delay(20);
}

Hola @Daniel_Arg

He intentado cargarlo y hacer pruebas pero no me funciona, a parte tengo otro problema, imaginate que la primera lectura mide

norte = 12
norte = 12
norte = 12
Noreste = 1
Noreste = 1

La media que me devuelve es 7, como si apuntara a sur oeste

No se como solucionar este issue

/*
   Direction PIN A1 with a resistor 9k between A1 and power at 3.5v
*/

int direction = 0;
int Wdeg = 0;

void setup() {

  delay(3000);
  Serial.begin(9600);
  Serial.println("VaneValue-tDirection-Heading-rosa");
  digitalWrite(7, HIGH);       // powering on lines

}

void loop() {
  digitalWrite(7, HIGH);       // powering on lines

    int wdirection = 0;
    int t_readings=0;
    int windVanereadings = 5;
    for ( int i = 1 ; i <= windVanereadings ; i++ ) {
  direction = analogRead(A1);
      if (direction >= 1 && direction <= 220)wdirection = 15 ;
      else if (direction >= 221 && direction <= 320)wdirection = 5;
      else if (direction >= 321 && direction <=420)wdirection = 6;
      else if (direction >= 421 && direction <= 620)wdirection = 1;
      else if (direction >= 621 && direction <= 720)wdirection = 7;
      else if (direction >= 721 && direction <= 900)wdirection = 12;
      else if (direction >= 901 && direction <= 940)wdirection = 11;
      else if (direction >= 941 && direction <= 1030)wdirection = 9;
      else if (direction == 0)wdirection = 0;
      t_readings =t_readings+ wdirection;
  Serial.print(direction);Serial.print("-");  Serial.print(wdirection);Serial.print("..");

  delay(50);
}
wdirection = t_readings/ windVanereadings;
Serial.print("Media: ");
Serial.println(wdirection);

direction = 0;
wdirection = 0;

delay(5000);
}

Con tu código no estas leyendo varias veces y sacando promedio..

Yo pruebo el siguiente código con un sensor de luz resistivo (LDR) y tengo distintas lecturas promediadas y cambia el valor cuando paso la mano por delante del sensor.

Le he bajado a 20 lecturas porque 50 son demasiadas.

const int numReadings = 20;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = A1;

void setup() {
  // initialize serial communication with computer:
  Serial.begin(9600);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {
 
  total = total - readings[readIndex];
  readings[readIndex] = analogRead(inputPin);
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
   // Para saber que resultado promedio da de leer la veleta en cada punto cardinal haces lo siguiente
   // Si por ejemplo luego de varios segundo de lectura de la veleta en posición 
   // de viento norte arroja un valor de 500 entonces construyes la condición 
   // if (average >= 520 && average < 480) { Serial.println("Viento Norte");}
   // Y continuar para todos los puntos cardinales
   Serial.println(average);
   readIndex = 0;
  }
  average = total / numReadings;


  delay(50);
}

Primero que nada Si esto no te arroja resultados en el monitor serie así:
970
880
770
540 etc es porque algo tienes mal en tu entrada analógica.

Tu sensor no es mas que una resistencia que varía con la posición como si fuera un potenciómetro, por lo tanto uno de los cables de la veleta debe estar conectado a GND y otro a la entrada A1 analógica de tu arduino, pero eso no es suficiente, debes tener una resistencia entre A1 y +5v para formar un divisor de tensión.

¿Has puesto la resistencia de 10k como indica tu sensor?

Insisto con que acabo de probar el código y da bueno resultados. Solo debes agregar tantos if( como están en el código comentados con los valores para que según cual sea por monitor serie te diga hacia donde va el viento.