Contador de pulsos para Anemometro y Pluviometro

Hola, primero que nada dar la enhorabuena a la gente que hace posible y participa en este gran foro.

En el siguiente post el contenido, es que si no no me deja incluir imagenes o links.

Gracias!

Estoy desarrollando una estacion meteorologica que su finalidad es subir los datos obtenidos a un servidor web mediante PHP y los guardara en una tabla MySQL (esta parte ya esta solucionada).

Hace unas semanas compré el kit de Sparkfun: Weather Meters http://www.sparkfun.com/commerce/product_info.php?products_id=8942

El anemometro y el pluviometro lo he hecho funcionar mediante la lectura del numero de pulsos, el codigo que estoy usando es el siguiente para la lectura de uno de ellos (sacado de:http://note19.com/2008/12/28/circuit-gear-arduino-and-counting-pulses/):

int pulsePin = 3;
unsigned long counter = 0;
unsigned long duration = 0;
unsigned long timeout = 1000000; // in microseconds

void setup() {
  pinMode(pulsePin, INPUT);
  // enable the 20K pull-up resistor to steer
  // the input pin to a HIGH reading.
  digitalWrite(pulsePin, HIGH);
  Serial.begin(9600);
  Serial.println("Here we go again");
}

void loop() {
  duration = pulseIn(pulsePin, HIGH, timeout);
  if (duration == 0) {
    Serial.print("Pulse started before the timeout.");
    Serial.println("");
  } else {
    counter++;
    Serial.print(counter);
    Serial.print(", ");
    Serial.print(duration);
    Serial.println("");
  }
}

Este codigo me entrega el numero de pulsos y la duracion entre pulsos.

Mi problema viene cuando intento medir los pulsos del anemometro y el pluviometro a la vez, lo unico que hago es duplicar el codigo y cambiar las variables, que quedaria así:

int pinanemometro = 3;
int pinpluviometro = 5;
unsigned long countanem = 0;
unsigned long durationanem = 0;
unsigned long countplu = 0;
unsigned long durationplu = 0;
unsigned long timeout = 1000000; // in microseconds

void setup() {
  pinMode(pinanemometro, INPUT);
  pinMode(pinpluviometro, INPUT);
  // enable the 20K pull-up resistor to steer
  // the input pin to a HIGH reading.
  digitalWrite(pinanemometro, HIGH);
  digitalWrite(pinpluviometro, HIGH);
  Serial.begin(9600);
  Serial.println("Here we go again");
}

void loop() {

  durationanem = pulseIn(pinanemometro, HIGH, timeout);
  if (durationanem == 0) {
    Serial.print("Pulse started before the timeout.");
    Serial.println("");
  } else {
    countanem++;
    Serial.print(countanem);
    Serial.print(", ");
    Serial.print(durationanem);
    Serial.println("");
  }

  durationplu = pulseIn(pinpluviometro, HIGH, timeout);
  if (durationplu == 0) {
    Serial.print("Pulse started before the timeout.");
    Serial.println("");
  } else {
    countplu++;
    Serial.print(countplu);
    Serial.print(", ");
    Serial.print(durationplu);
    Serial.println("");
  }

}

En este caso mientras el pluviometro no se mueva el anemometro no da los resultados.

¿Se os ocurre alguna forma de medir el numero de pulsos a la vez desde dos entradas digitales?

No se si me he explicado correctamente, en caso de que no se entienda algo me lo preguntais.

Muchas gracias!!!

P.D: Por cierto, cuando lo tenga todo acabado subire todo el codigo de los scripts PHP para guardar los datos, scripts para generar las graficas en tiempo real...etc...etc...etc, que no sea por compartir jejeje.

Una muestra de lo que tengo de momento:

Yo creo que tendras que tirar por interrupciones. Echale una leida/pensada a esto Arduino Playground - Interrupts

Ya nos contaras.

Un saludo.

Ten en cuenta que pulseIn es una funcion bloqueante, es decir, hasta que no recibe un pulso no seguirá el código. De la manera que lo has puesto, solo contará pulsos que lleguen alternos, es decir, uno del pluviometro, uno del anemómetro, y así.

Una pregunta: Para qué te vale la duración del pulso? Te da alguna información relevante? Desde mi punto de vista no aporta nada que no aporte el número de pulsos.
Efectivamente deberías usar interrupciones. Si el código no va a hacer absolutamente nada más, si que podrías apañar un programilla sin interrupciones que cuente los pulsos y los mida sin interrupciones, pero no se si te merece la pena.

Saludos.
Eduardo

Hola! Muchas gracias a los dos por contestar, Eduardo_g la duración del pulso efectivamente no sirve para nada, venia en el ejemplo y no lo quité.

Buscando información de lo que me habéis aconsejado sobre el attachInterrupt() me he encontrado con esto (San Google, como siempre jejeje):

URL Fuente Original: http://home.comcast.net/~saustin98/misc/WeatherStationADC.txt

Aquí tenéis todo el código necesario para hacer funcionar el kit de medición de Sparkfun, lo he probado y funciona correctamente, os pego el código original, a ver si esta noche tengo un rato (estoy en el currele) y os cuelgo el modificado por mi, con la conversión a Km/h y el contador para el pluviómetro (que en esta versión no esta incluida).

/* Arduino sketch for Weather device from Sparkfun.
Uses only the wind direction vane and the anemometer (not the rain gauge).

Although the inclination for a weather logger is to run it for
a long time, due to the way Wiring.c implements the millis() function,
this should be restarted, oh, monthly. The millis() functions overflows
after about 49 days. We could allow for that here, and handle the
wraparound, but you've got bigger problems anyway with the delay()
function at an overflow, so it's best to "reboot".

=========================================================
ANEMOMETER
=========================================================
This is connected to Arduino ground on one side, and pin 2 (for the
attachInterrupt(0, ...) on the other.
Pin 2 is pulled up, and the reed switch on the anemometer will send
that to ground once per revolution, which will trigger the interrupt.
We count the number of revolutions in 5 seconds, and divide by 5.
One Hz (rev/sec) = 1.492 mph.

=========================================================
WIND DIRECTION VANE
=========================================================
We use a classic voltage divider to measure the resistance in
the weather vane, which varies by direction.
Using a 10K resistor, our ADC reading will be:
   1023 * (R/(10000+R))
where R is the unknown resistance from the vane. We'll scale
the 1023 down to a 255 range, to match the datasheet docs.

                  +5V
                   |
                   <
                   >     10K
                   <   Resistor
                   <
                   >
                   |
 Analog Pin 5------|
                   |
                   -----------| To weather vane
                              | (mystery resistance)
                   -----------|
                   |
                   |
                 -----
                  ---
                   -
The ADC values we get for each direction (based on a 255 max)
follow, assuming that pointing away from the assembly center
is sector zero. The sector number is just which 45-degree sector
it is, clockwise from the "away" direction. The direction
shown is assuming that "away" is West. Depending how
you orient the system, you'll have to adjust the directions.

Sector   Reading  Direction
  0        18        W
  1        33        NW
  2        57        N
  7        97        SW
  3       139        NE
  6       183        S
  5       208        SE
  4       232        E
The values in the ADC table below list the midpoints between
these, so our reading can vary a bit. We'll pick the first value
that's >= our reading.
=========================================================
RAIN GAUGE
=========================================================
Not implemented here. Hey. I live in Seattle. It's ALWAYS raining. Who
cares how much?
Okay, it would probably be done the same way as the anemometer, and use
attachInterrupt(1, ...) on pin 3. Each interrupt represents
.011 inches of rain, according to the docs.

*********************************************************************/

#define uint  unsigned int
#define ulong unsigned long

#define PIN_ANEMOMETER  2     // Digital 2
#define PIN_VANE        5     // Analog 5

// How often we want to calculate wind speed or direction
#define MSECS_CALC_WIND_SPEED 5000
#define MSECS_CALC_WIND_DIR   5000

volatile int numRevsAnemometer = 0; // Incremented in the interrupt
ulong nextCalcSpeed;                // When we next calc the wind speed
ulong nextCalcDir;                  // When we next calc the direction
ulong time;                         // Millis() at each start of loop().

// ADC readings:
#define NUMDIRS 8
ulong   adc[NUMDIRS] = {26, 45, 77, 118, 161, 196, 220, 256};

// These directions match 1-for-1 with the values in adc, but
// will have to be adjusted as noted above. Modify 'dirOffset'
// to which direction is 'away' (it's West here).
char *strVals[NUMDIRS] = {"W","NW","N","SW","NE","S","SE","E"};
byte dirOffset=0;

//=======================================================
// Initialize
//=======================================================
void setup() {
   Serial.begin(9600);
   pinMode(PIN_ANEMOMETER, INPUT);
   digitalWrite(PIN_ANEMOMETER, HIGH);
   attachInterrupt(0, countAnemometer, FALLING);
   nextCalcSpeed = millis() + MSECS_CALC_WIND_SPEED;
   nextCalcDir   = millis() + MSECS_CALC_WIND_DIR;
}

//=======================================================
// Main loop.
//=======================================================
void loop() {
   time = millis();

   if (time >= nextCalcSpeed) {
      calcWindSpeed();
      nextCalcSpeed = time + MSECS_CALC_WIND_SPEED;
   }
   if (time >= nextCalcDir) {
      calcWindDir();
      nextCalcDir = time + MSECS_CALC_WIND_DIR;
   }
}

//=======================================================
// Interrupt handler for anemometer. Called each time the reed
// switch triggers (one revolution).
//=======================================================
void countAnemometer() {
   numRevsAnemometer++;
}

//=======================================================
// Find vane direction.
//=======================================================
void calcWindDir() {
   int val;
   byte x, reading;

   val = analogRead(PIN_VANE);
   val >>=2;                        // Shift to 255 range
   reading = val;

   // Look the reading up in directions table. Find the first value
   // that's >= to what we got.
   for (x=0; x<NUMDIRS; x++) {
      if (adc[x] >= reading)
         break;
   }
   //Serial.println(reading, DEC);
   x = (x + dirOffset) % 8;   // Adjust for orientation
   Serial.print("  Dir: ");
   Serial.println(strVals[x]);
}


//=======================================================
// Calculate the wind speed, and display it (or log it, whatever).
// 1 rev/sec = 1.492 mph
//=======================================================
void calcWindSpeed() {
   int x, iSpeed;
   // This will produce mph * 10
   // (didn't calc right when done as one statement)
   long speed = 14920;
   speed *= numRevsAnemometer;
   speed /= MSECS_CALC_WIND_SPEED;
   iSpeed = speed;         // Need this for formatting below

   Serial.print("Wind speed: ");
   x = iSpeed / 10;
   Serial.print(x);
   Serial.print('.');
   x = iSpeed % 10;
   Serial.print(x);

   numRevsAnemometer = 0;        // Reset counter
}

Aquí el resultado:

Muchas gracias de nuevo!! Os mantengo informados...

Hi imariscal,
i'm new in the forum...and i don't speak spanish!
I've the same weather station from sparkfun and an Arduino Mega, and i see the same sketch you've posted months ago!
Could you help me in connecting the anemometer with the arduino? How did you do it?
Thanks a lot for the help!

I hope you'll answer soon!
Bye!

Muy buena informacion... unos cuantos de los proyectos que tengo en la cabeza para encarar con arduino necesitan contar pulsos, y todavia no habia encontrado como hacerlo.

Saludos!

For angeliam, this weekend will make him a photo to see how connected the anemometer. :wink:

Buenas, hace un tiempo (mas de un año) estuve probando arduino justamente para hacer una central meteorologica, todavia no vendian el kit de sparkfun... la idea era conectar el arduino a un Access Point, especificamente un Linksys de Cisco, estos aparatos que corren linux(ww.dd-wrt.com/site/index), se les puede agregar un puerto de entrada serial y otro de salida y tambien se le puede agregar una SD de hasta 2gb (ww.allaboutjake.com/network/linksys/wrt54g/hack/). Por lo que en un pequeño aparato tenemos casi todo, un linux con un servidor web, php, la Sd para almacenar los datos y puertos ethernet y conecciones wifi para tramitir y consultar los datos en tiempo real y almacenado en la base de datos. La programacion del puerto seria se puede hacer en el linux con shell scripting (physics.usask.ca/~hussey/ep413/asem51_html/bscript.htm) Bueno si a alguien le interesa la idea nos ponemos en contacto.- Esta muy bueno lo que publicaron y graciaas!

Hola!!

Me ha encantado el programa para representar los datos en gráficas. Claro y bonito.

Dice que lo ha hecho en PHP. ¿Alguien me puede pasar un ejmplo hecho info de como hacerlo?

Saludos!!

Buenas javiZgz! Las graficas las saqué de aqui:

http://pchart.sourceforge.net/

Me costó un poco hacerlas funcionar con la base de datos.

De momento el proyecto lo tengo paralizado por falta de tiempo, supongo que para el verano 2010 la acabe y la ponga en marcha.

Os mantendré informados, cuando esté todo OK, colgare TODOS los ficheros fuente.

Un saludo a todos! :wink:

Q bueno el pChart!!!!

Sube por favor los codes, aunque no los tengas acabados al 100%

Este como este ayudara!

Saludos

Una consulta, finalmente como resolviste el tema del pluviometro?

Wenas.

Yo también estoy construyendo una estación meteorológica, con el kit de Saprkfun. Para quien le interese, añado el código para el pluviómetro, hecho de mi cosecha. Está en inglés, al igual que todo el proyecto. Sorry :o

Básicamente usa interrupciones de manera similar al anemómetro, cuenta los "clicks" y presenta los resultados por el puerto serie cada segundo.

Espero que os sirva.

Saludos

PD: algún día os cuento algo más en detalle del proyecto.

/* Arduino sketch for Weather device from Sparkfun.
Uses only the rain gauge.
(copyleft) 2010 F. Javier Dominguez Murillo

This sketch simply counts the numbers of "clicks" occured at the
rain gauge by interrupts, and shows this number (and equivalent rain
quantity in litres per square meters) by serial port every second.

*********************************************************************/

#define PIN_RAIN_GAUGE  2     // Digital 2 (INT_0)

volatile int numClicksRainGauge = 0; // Incremented in the interrupt
float x; // for calculate the rain quantity

//=======================================================
// Initialize
//=======================================================
void setup() {
   Serial.begin(9600);
   pinMode(PIN_RAIN_GAUGE, INPUT);
   digitalWrite(PIN_RAIN_GAUGE, HIGH);
   attachInterrupt(0, countRainGauge, FALLING);

}

//=======================================================
// Main loop.
//=======================================================
void loop() {


 x = numClicksRainGauge*0.2794; // factor conversion as indicated in datasheet
   Serial.print(numClicksRainGauge); // number of contact closures
   Serial.print(" clicks, ");
   Serial.print(x); // quantity of rain in mm (litres per square meters)
   Serial.print(" mm (L/m2)\n");
   delay(1000);

   
}

//=======================================================
// Interrupt handler for rain gauge. Called on every 
// contact closure
//=======================================================
void countRainGauge() {
numClicksRainGauge++;
}

Yo he usado algo parecido para "contar" las revoluciones y velocidad de una CBR y saber en la marcha que va.

void r_rpm()
{
delayMicroseconds(100);
rpmcount++;
}
void r_speed()
{
delayMicroseconds(100);
speedcount++;
}

attachInterrupt(0, r_rpm, RISING); // 0 --> digital 2
attachInterrupt(1, r_speed, RISING); // 1 --> digital 3

He tenido que poner unos 2n2222a con sus resistencias y un condensador de 0.1uf en la velocidad para que se enterara de los pulsos.

Saludos y suerte.

Yo también estoy construyendo una estación meteorológica con el kit SparkFun: "Weather Meters" me pregunto a Imariscalsi e Javier se todos los sensores están funcionando bien este kit especialmente el indicador de lluvia? ¿Podrías enviarme el código completo de la Arduino?

Saludos , Armando (armando.camara@gmail.com)

Por favor, quisiera información sobre su estación y el clima de Imariscal.
¿Alguien sabe su e-mail

Por favor, quisiera información sobre su estación y el clima de Imariscal.
¿Alguien sabe su e-mail de Imariscal en Espanha??
Imariscal por favor me envie su email?

Tanks Armando.