Flow sensor library

canada7764, my water sensor is tied up in my basement on the hot water output of my gas heater so I will test will a square wave generator, which is how I developed the original code. Will get back to you when I get results.

Oh, and I LOVE white so much, especially in Ottawa (NOT!) :wink:

canada7764, it seems I left out the code for the ISR for the water sensor!! Here is the full code that compiles correctly. The Serial.print code can be removed. I added it for simpler debugging.

/*
    Water flow sensor test sketch

*/


unsigned long oldTime = 0;
volatile unsigned int WaterPulseCount = 0;

// conversion from pps to litres, plastic sensor (485 for metal)
const float pulsesPerLiter = 450;

// Spark Digial Pin D2
#define WATER_SENSOR_PIN	D2		// Water sensor using pin D2

// Define Spark variable - not sure "float" type works so define as INT
// so decimal is shifted left with * 100 (so xx.yy becomes xxyy)
int liters = 0;


//-----------------------------------------------------------------------------
// Water Sensor interrupts
//-----------------------------------------------------------------------------
void WaterPulseCounter(void)
{
	// Increment the water pulse counter
	detachInterrupt (WATER_SENSOR_PIN) ;
	++WaterPulseCount;
	attachInterrupt(WATER_SENSOR_PIN, WaterPulseCounter, FALLING) ;
}


void setup()
{
  Serial.begin(115200);
  
  Spark.variable("liters",&liters, INT);

  // Set Digital pin WATER_SENSOR_PINT to INPUT mode and set
  // interrupt vector (water flow sensor) for FALLING edge interrupt
  pinMode(WATER_SENSOR_PIN, INPUT_PULLUP);
  attachInterrupt(WATER_SENSOR_PIN, WaterPulseCounter, FALLING) ;
}


void loop()
{
  unsigned long t;

  t = (millis() - oldTime);
  if(t >= 1000)    			// Only process counters once per second
  {
    //Read water sensor pulse count and process
    if (WaterPulseCount != 0)		// Do nothing if water is not flowing!
    {
    detachInterrupt (WATER_SENSOR_PIN);	// Disable water flow interrupt to read value
    //Calculate litres and adjust for 1 sec offset, if any
    liters = (WaterPulseCount / pulsesPerLiter) * (t / 1000) *100;
    oldTime = millis();				// Reset base delay time
    WaterPulseCount = 0;			// Reset the water pulse counter
    attachInterrupt(WATER_SENSOR_PIN, WaterPulseCounter, FALLING);
    Serial.print("WaterPulseCount= ");
    Serial.print(WaterPulseCount);
    Serial.print(", liters= ");
    Serial.println(liters);
    }
  }
}

Cheers!

1 Like

peekay,

I forget things all the time (added the routine) but thanks for posting. Just finished installing on greenhouse irrigation and gonna test accuracy now.

If only you could see the 13’ banks iv made here in Alberta.

Thanks

Dude, those are walls now, not banks!

:wink:

Going way off topic now!

3 Likes

canada7764,

I got the code working and running solidly with a few caveats. First, some of my code must have been written WAY too late at night so I fixed my own bugs. Seconds, the Spark Cloud API is not quite ready for prime time. That is, the FLOAT and DOUBLE types are not parsed correctly by the Cloud API so a GET request will get garbage. I ended up using a FLOAT for liters and then converted it to a STRING for the Spark.variable. Another oddity I experienced is that I could not use digital pin D2 as it would not work! I changed over to D3 and all was fine so I have to do some digging on that issue. So, here is the code for your enjoyment:

/*
    Water flow sensor test sketch

*/


unsigned long oldTime;
volatile unsigned int WaterPulseCount = 0;

// conversion from pps to litres, plastic sensor (485 for metal)
const float pulsesPerLiter = 450;

// Spark Digial Pin D3 (D2 did not work)
#define WATER_SENSOR_PIN	D3	// Water sensor digital pin

// Define Spark variable - not sure "float" type works so define as INT
// so decimal is shifted left with * 100 (so xx.yy becomes xxyy)
float liters = 0;
char liters_S[6];

//-----------------------------------------------------------------------------
// Water Sensor interrupts
//-----------------------------------------------------------------------------
void WaterPulseCounter(void)
{
	// Increment the water pulse counter
	//detachInterrupt (WATER_SENSOR_PIN) ;
	WaterPulseCount++;
	//attachInterrupt(WATER_SENSOR_PIN, WaterPulseCounter, FALLING) ;
}


void setup()
{
  Serial.begin(9600);
  
  Spark.variable("litersS", &liters_S, STRING);

  // Set Digital pin WATER_SENSOR_PINT to INPUT mode and set
  // interrupt vector (water flow sensor) for FALLING edge interrupt
  pinMode(WATER_SENSOR_PIN, INPUT);
  attachInterrupt(WATER_SENSOR_PIN, WaterPulseCounter, FALLING) ;
  oldTime = millis();
}


void loop()
{
  unsigned long t;
  static unsigned int pc;

  t = (millis() - oldTime);
  if(t >= 1000)    			// Only process counters once per second
  {
    //Read water sensor pulse count and process
    if (WaterPulseCount != 0)		// Do nothing if water is not flowing!
    {
    detachInterrupt (WATER_SENSOR_PIN);	// Disable water flow interrupt to read value
    //Calculate litres and adjust for 1 sec offset, if any
    liters = (WaterPulseCount / pulsesPerLiter) * (t / 1000);
    oldTime = millis();				// Reset base delay time
    pc = WaterPulseCount;
    WaterPulseCount = 0;			// Reset the water pulse counter
    attachInterrupt(WATER_SENSOR_PIN, WaterPulseCounter, FALLING);

    sprintf(liters_S, "%4.3f", liters);
    
    Serial.print("WaterPulseCount= ");
    Serial.print(pc);
    Serial.print(", liters= ");
    Serial.print(liters,3);
    Serial.print(", liters_S= ");
    Serial.println(liters_S);
    }
  }
}

:smile:

Glad you guys got this working! Sorry about the floats not being parsed correctly thing, the API and cloud services are definitely still evolving, especially with community support and bug reports like this :slight_smile:

– I poked the firmware guys again about this one, we’ll post back here when it’s fixed.

edit: okay, I have a fix for this for doubles with Spark.variable, it’s on staging now, and it’ll be included in our next production rollout.

@Dave got a fix in for floating point endianness today. Should be deployed to the Cloud by early next week.

Thanks guys! I always look forward to each new release :smile:

1 Like

Greetings Spark Community! I’am a computer programming student here in Canada. I’am using a Flow Rate Sensor the same product @canada7764 posted at the beginning. I have tried using the code provided by @peekay123 it compiles great and seems to be working! The issue is viewing the results… I have tried to use the Cloud APi to view it via the web, it is connecting but not showing the results. Can someone Please help!! am i doing this correctly? I just want to view the amount of water flowing through the sensor… :frowning:

Thank you for your time

@Clarke, I’m from Ottawa, where are you? I removed the link from your post because it contained your Core’s token and ID! If you post your code, I can give you some advice (hopefully) :stuck_out_tongue:

@peekay123 Thanks for taking the time out of your day to reply! :smiley: I’am from Barrie, just north of Toronto a second semester programming student. Also i appreciate you taking the link out, wasn’t sure if i should post it or not lol. For my code i was actually using what you posted Feb of 2014 with Variable " litersS " ( most resent code ) as a test and then was going to write some code to change it from litres to millilitres and just play around with the code making changes and learning from trial and error etc. But as of right now just trying to get something to work. I have used an Arduino with bluetooth for the same purpose and it worked. Just now switching to the Spark Core because its so awesome I’am having some trouble and not much mentoring at school being such a new platform.

@Clarke, if just viewing the results is what you need, the code I posted prints to the Serial port (USB). All you need is to open a terminal on your PC and monitor the COM port created by the connected Core. :smiley:

@peekay123 Well that was simple enough, worked great! As you can probably guess by now, i’am a total rookie when it comes to this. When trying to view the results via Cloud API using Spark.variable(“litersS”, &liters_S, STRING); https://api.spark.io/v1/devices/ID/litersS/?access_token= It does get connected, but does not display the results. Would you be able to help me, as to how to go about getting it to work. :smiley:

Have a Great weekend! Its gonna be a cold one!

@Clarke, I need to see your code to be able to help you :stuck_out_tongue:

@peekay123 This is the code ( your code ) lol :smile: I have been trying

I have been using Variable " liters_S "

Example Request ( It does gets connected but does not display results )

@Clarke, you are not allocating enough space in you liters_S array. With %4.3f, that uses a minimum of 8 chars plus the null terminator. Make your array 20bytes in size to avoid problems and try again :smiley:

2 Likes

Anyone have advice for code to add to @peekay123 's code that will publish an event when certain conditions are met? Ideally, I’d like to publish an event when the water flow stays above a certain level for a certain amount of time. I know next to nothing about C++ and am trying to fumble through the basics. By the end of the project, I’d love to be able to log water usage too, but figured I’d try to get the events thing figured out first. Baby steps.

Any advice is appreciated!

@stringpark, what have you tried?

@peekay123 Well, I’m a little embarrassed to say, because I really have no idea what I’m doing. I tried adding the “if” statement below, but that doesn’t verify, so I must have formatted something wrong.

void loop()
{
  unsigned long t;
  static unsigned int pc;

  t = (millis() - oldTime);
  if(t >= 1000)    			// Only process counters once per second
  {
    //Read water sensor pulse count and process
    if (WaterPulseCount != 0)		// Do nothing if water is not flowing!
    {
      detachInterrupt (WATER_SENSOR_PIN);	// Disable water flow interrupt to read value
      //Calculate litres and adjust for 1 sec offset, if any
      liters = (WaterPulseCount / pulsesPerLiter) * (t / 1000);
      oldTime = millis();				// Reset base delay time
      pc = WaterPulseCount;
      WaterPulseCount = 0;			// Reset the water pulse counter
      attachInterrupt(WATER_SENSOR_PIN, WaterPulseCounter, FALLING);

      sprintf(liters_S, "%4.3f", liters);

      if(liters_S > .04)
      {
        Particle.publish("litersS",liters_S,60,PRIVATE);
      }

    }
  }
}

I’ve also tried adding the Particle.publish line below, just to see what would happen. It compiled, but I didn’t see anything in the cloud. Again, I’m pretty much clueless, sorry.

void setup()
{
  Serial.begin(9600); 

  Particle.variable("litersS", liters_S, STRING);
  Particle.publish("litersS",liters_S,60,PRIVATE);
  // Set Digital pin WATER_SENSOR_PINT to INPUT mode and set
  // interrupt vector (water flow sensor) for FALLING edge interrupt
  pinMode(WATER_SENSOR_PIN, INPUT);
  attachInterrupt(WATER_SENSOR_PIN, WaterPulseCounter, FALLING) ;
  oldTime = millis();
}