Pages: [1]   Go Down
Author Topic: Watermeter counter on browser  (Read 1285 times)
0 Members and 1 Guest are viewing this topic.
Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi I have a water meter that closes a reed switch every 10 litres
I want to be able to read the meter from my browser
I have tried to join the button sketch and webserver sketch from http://arduino.cc/en/Tutorial/WebServer
Both sketches work fine before I join them
What I want to do is have a pulsed input on pin5 that counts up after 10 litres and shows the count on my browser
I am using a duemilanove and an Arduino genuine ethernet shield

Using attached sketch I can see counter and it counts up only when I refresh browser whilst grounding pin 5

If I ground pin5 a couple of times and then refresh browser it doesn't count

Any advise gratefully appreciated

Code:
/*
  Web  Server
 
 A simple web server that shows the value of the digital input pins.
 using an Arduino Wiznet Ethernet shield.
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 * digital inputs attached to pins A0 through A5 (optional)
 
 created 18 Dec 2009
 by David A. Mellis
 modified 4 Sep 2010
 by Tom Igoe
 
 */
int LED = 11;
int Button = 5;
int value = 0;
int counter = 3;
int lastbuttonstate = 7;

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {
  192,168,1, 25 };

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
Server server(80);

void setup()
{
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();

  Serial.begin(9600);                  // Sets the baud rate to 9600
  pinMode(LED, OUTPUT);              // initializes digital pin 13 as output
  pinMode(Button, INPUT);                // initializes digital pin 10 as input

}

void loop()
{
  // listen for incoming clients
  Client client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();

          value = digitalRead(Button);   // reads the value at a digital input
          digitalWrite(LED, value);   

          if(value != lastbuttonstate){
            if(value == 1){
              counter++;
             
             
              Serial.println(counter, DEC);
              Serial.write(11);
              Serial.write(5);


            }
          }       


          lastbuttonstate = value; 

          // output the value of each digital input pin
          for (int digitalChannel = 0; digitalChannel < 6; digitalChannel++) {
            client.print("digital input ");
            client.print(digitalChannel);
            client.print(" is ");
            client.print(digitalRead(digitalChannel));
            client.println("<br />");

            client.print(counter, DEC);
            client.println("<br />");
            client.print(digitalRead(Button));
            client.println("<br />");

         
          }
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }
}



Any advise / links to a similar project  gratefully appreciated
Maurice

Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You better read the sensor with an interrupt routine. - http://www.arduino.cc/en/Reference/AttachInterrupt - and increase the counter after every pulse. Then the main loop can just be your webserver. I tinkered a bit with your code with this result,

connect the pulse from the watersensor to pin 2 (interrupt 0).

(Code compiles but not tested)

Code:
/*
  Web  Server
 
 A simple web server that shows the value of the digital input pins.
 using an Arduino Wiznet Ethernet shield.
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 * digital inputs attached to pins A0 through A5 (optional)
 
 created 18 Dec 2009
 by David A. Mellis
 modified 4 Sep 2010
 by Tom Igoe
 
 */
int LED = 11;

int value = 0;

int lastbuttonstate = 7;

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {
  192,168,1, 25 };

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
Server server(80);

volatile unsigned long counter = 0;

void IRQ()
{
  counter++;
  digitalWrite(LED, !digitalRead(LED));   // inverse the LED
}


void setup()
{
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();

  Serial.begin(9600);
  pinMode(LED, OUTPUT);

  attachInterrupt(0, IRQ, FALLING);  // IRQ pin 2
}

void loop()
{
  // listen for incoming clients
  Client client = server.available();
  if (client)
  {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected())
    {
      if (client.available())
      {
        char c = client.read();
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank)
        {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();

          // output the value of each digital input pin
          for (int digitalChannel = 0; digitalChannel < 6; digitalChannel++)
          {
            client.print("digital input ");
            client.print(digitalChannel);
            client.print(" is ");
            client.print(digitalRead(digitalChannel));
            client.println("<br />");

            client.print(counter, DEC);
            client.println("<br />");
            client.print(digitalRead(2));  // the IRQ line
            client.println("<br />");
          }
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(10);
    // close the connection:
    client.stop();
  }
}
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Dank je wel

I tried your code and it works very well, except  I note that
  • the LED attached to pin 11 doesn't change state (Should it?)
  • the switch is extremely sensitive and often gives a count >1
I see that I cant add a delay to attachinterrupt to make pin D2 less sensitive
But I am going to keep with it and try and improve it
I will also need to multiply the counter x 10 to make it read litres
Thanks again
Maurice


Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
the LED attached to pin 11 doesn't change state (Should it?)

it should change every pulse, the ! before the digitalRead(LED) should inverse the output. Have you connected the LED correctly?

Quote
the switch is extremely sensitive and often gives a count >1
interrupts are famous for their sensotivity, but you can tune it a bit.

Code:
volatile unsigned long lastTime = 0;  // remember last IRQ
#define THRESHOLD 8               // I expect max 100 IRQ's per second so if they are shorter than 8 millis after another its a false alert :)
void IRQ()
{
  if (millis() - lastTime < THRESHOLD)
  {
    lastTime = millis();
    return;
  }
  counter++;
  digitalWrite(LED, !digitalRead(LED));   // inverse the LED
}

Quote
I will also need to multiply the counter x 10 to make it read litres
You only need that during display:

client.print(counter * 10, DEC);
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Rob,
Thanks for your help
I tried your suggestions and I still can't get it to work.

I moved the LED to pin 13 and it still doesn't change state when switch is closed or opens
I tried the threshold at 8 , 80 , 800,  8000 but my readings still go up >1
Because the meter reads 1 pulse for every 10litres I would expect a max of 1 pulse / 5 seconds
http://www.bes.co.uk/product/102~PL~1812~1812~-Pulsed-Water-Meters-For-Remote-Reading.html
The client.print(counter *10, DEC); works fine
I have a 1kohm resistor between pin 2 and GND
I have the magnetic switch between 5v and pin 2

I am presuming that "IRQ pin 2" is actually Digital I/O pin 2 on the Duemilanove


Code:
/*
  Web  Server
 
 A simple web server that shows the value of the digital input pins.
 using an Arduino Wiznet Ethernet shield.
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 * digital inputs attached to pins A0 through A5 (optional)
 
 created 18 Dec 2009
 by David A. Mellis
 modified 4 Sep 2010
 by Tom Igoe
 
 */
int LED = 13;

int value = 0;

int lastbuttonstate = 0;

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {
  192,168,1, 25 };

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
Server server(80);

volatile unsigned long counter = 0;
volatile unsigned long lastTime = 0;  // remember last IRQ
#define THRESHOLD 8     
// I expect max 100 IRQ's per second so if they are shorter than 8 millis after another its a false alert :)


void IRQ()
{
  if (millis() - lastTime < THRESHOLD)
  {
    lastTime = millis();
    return;
  }
  counter++;
  digitalWrite(LED, !digitalRead(LED));   // inverse the LED
}


void setup()
{
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();

  Serial.begin(9600);
  pinMode(LED, OUTPUT);

  attachInterrupt(0, IRQ, FALLING);  // IRQ pin 2
}

void loop()
{
  // listen for incoming clients
  Client client = server.available();
  if (client)
  {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected())
    {
      if (client.available())
      {
        char c = client.read();
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank)
        {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();

          // output the value of each digital input pin
          for (int digitalChannel = 0; digitalChannel < 6; digitalChannel++)
          {
            client.print("digital input ");
            client.print(digitalChannel);
            client.print(" is ");
            client.print(digitalRead(digitalChannel));
            client.println("<br />");

            client.print(counter *10, DEC);
            client.println("<br />");
            client.print(digitalRead(2));  // the IRQ line
            client.println("<br />");
          }
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(10);
    // close the connection:
    client.stop();
  }
}

Regards
Maurice
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Pin 10-13 are used by the ethernetshield / SPI, did not think of it earlier

you should another free pin for the LED 
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Rob, for your quick reply
Changed LED to pin 8 and it when pulsed:
First time switches on LED
Second time switches off LED

However the readings using Tresholds between 8 to 800 still give wrong counts

Regards
Maurice
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Because the meter reads 1 pulse for every 10litres I would expect a max of 1 pulse / 5 seconds

one pulse per 5 seconds == 1 pulse / 5000 millisec.

Change THRESHOLD to 2500 ==> meaning if a pulse comes in the next 2.5 seconds after one it is ignored

Max flow that will be detected is about 10L in 2.5 sec = 4 Liter/sec

3000, 3500, 4000, are other values  to test

===========

If you got it working you can try the following (not earlier!!)

Change the line:

attachInterrupt(0, IRQ, CHANGE);  // IRQ pin 2

That will give you two pulses per 10 Liter - not necessary one per 5 liter, but it might give you some extra accuracy. You should check the timing of the pulse edges
The THRESHOLD should become something like 1500 then BTW

sofar my 2 cents,
Rob







Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Rob, for all your suggestions and pointing me in the right direction

I got it working
This sketch counts pulses and shows the water meter reading on the web
It is based on a Duemilanove and a wiznet ethernet shield
The only connections are a 1K resistor from +5v to pin2 and the reed switch on the meter is connected between pin2 and ground

Code:
/*
  Water Meter Counter
 Web  Server
 
 A simple web server that shows the value of the digital input pins.
 using an Arduino Wiznet Ethernet shield.
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 * digital inputs attached to pins A0 through A5 (optional)
 
 created 18 Dec 2009
 by David A. Mellis
 modified 4 Sep 2010
 by Tom Igoe
 
 */
int LED = 7; // Led 13 doesnt work with ether shield
int Button = 2;
int value = 0;
int counter = 120; //initial water meter reading
int lastbuttonstate = 0;

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {
  192,168,1, 25 };

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
Server server(80);

void setup()
{
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();

  Serial.begin(9600);                  // Sets the baud rate to 9600
  pinMode(LED, OUTPUT);              // initializes digital pin 13 as output
  pinMode(Button, INPUT);                // initializes digital pin 10 as input


}

void loop()
{

  {
    value = digitalRead(Button);   // reads the value at a digital input
    digitalWrite(LED, value);   

    if(value != lastbuttonstate){
      if(value == 1){
        counter++;
        Serial.println(counter *10, DEC); // Litres for every pulse
        Serial.write(7);
        Serial.write(2);

      }
    } 
    lastbuttonstate = value;                         
  }
  // listen for incoming clients
  Client client = server.available();
  if (client)
  {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected())
    {
      if (client.available())
      {
        char c = client.read();
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank)
        {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();

          // output the value of each digital input pin
          for (int digitalChannel = 0; digitalChannel < 1; digitalChannel++)
          {


            client.print("Watermeter Input ");
            client.print(digitalChannel);
            client.print(" is ");
            client.print(digitalRead(digitalChannel));
            client.println("<br />");

            client.print(counter *10, DEC);
            client.print("  Litres ");
            client.println("<br />");
            client.print(" Installation Date = 20/6/2011 ");

          }
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(10);
    // close the connection:
    client.stop();
  }
}

On my phone it looks like:

Watermeter Input 0 is 1
1210 Litres
Installation Date = 20/6/2011





Hope it helps someone else
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well done Maurice,

for readability you could add an extra level in loop()

void loop()
{
  doMeasurement();
  doEthernet();
}

Furthermore in your code you add the following change: (earlier discussed in IRQ version)

Code:
{
  value = digitalRead(Button);   // reads the value at a digital input
  digitalWrite(LED, value);   

  if(value != lastbuttonstate)
  {
    counter++;
    Serial.println(counter *5, DEC); // Litres for every pulse
    Serial.write(7);
    Serial.write(2);
  } 
  lastbuttonstate = value;                         
}

Then it will count (approx) per 5 liters..

Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Pages: [1]   Go Up
Jump to: