Events display zero with hall sensor

Hey,
I have pretty much no clue what im actually doing so please be patient with me, and thanks for reading through this even if you dont reply.
So i got the following code to read data off the YF-S201 sensor and publish it to events in the cloud.

However i keep getting "0"as output.
no idea where im going wrong .
( i got this code off another project built by someone else AKA not Mine)

byte statusLed    = D7; 
byte sensorInterrupt = D2;  // 0 = digital pin 2 
byte sensorPin       = D2; 
// The hall-effect flow sensor outputs approximately 4.5 pulses per second per litre/minute of flow. 
float calibrationFactor = 4.5;
volatile byte pulseCount;  
float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;
unsigned long oldTime;
void setup()
{
  // Initialize a serial connection for reporting values to the host
  Serial.begin(38400);
  // Set up the status LED line as an output
  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);
  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitres  = 0;
  oldTime           = 0;
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}
void loop()
{
  if((millis() - oldTime) > 1000)    // Only process counters once per second
  { 
    detachInterrupt(sensorInterrupt);
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    oldTime = millis();
    flowMilliLitres = (flowRate / 60) * 1000;
    totalMilliLitres += flowMilliLitres;
    unsigned int frac;
    char str[10];
    char str2[10];
    Serial.print('Flow rate: ');
    Serial.print(int(flowRate));  // Print the integer part of the variable
    Serial.print('.');             // Print the decimal point
    frac = (flowRate - int(flowRate)) * 10;
    Serial.print(frac, DEC) ;      // Print the fractional part of the variable
    Serial.print('L/min');
    Serial.print('  Current Liquid Flowing: ');             // Output separator
    Serial.print(flowMilliLitres); 
    Serial.print('mL/Sec');
    sprintf(str, "%d", flowMilliLitres);
    Particle.publish("FlowRatesmlPerSec", str);
    Serial.print("  Output Liquid Quantity: ");             // Output separator
    Serial.print(totalMilliLitres);
    Serial.println("mL"); 
    sprintf(str2, "%d", totalMilliLitres);
    Particle.publish("totalFlowInML", str2);
  }
}
void pulseCounter()
{
  pulseCount++;
} 

There may be other issues, but the thing that stood out to me is this:

if((millis() - oldTime) > 1000)    // Only process counters once per second
{ 
    detachInterrupt(sensorInterrupt);

After 1 second of running, the interrupt handler is detached, so it will not measure pulses anymore. I’d comment out the detachInterrupt line.

Also, probably after this:

totalMilliLitres += flowMilliLitres;

add this:

pulseCount = 0;
1 Like

This used to be the "old" way to set pull-up resistors for Arudino but this never worked with Particle devices.
If you want an internal pull-up applied you'd write

  pinMode(sensorPin, INPUT_PULLUP);

However, with a signal source that provides a discrete level at all times, you wouldn't need a pull-up at all.

You may also want to consider using Serial.printlnf() or snprintf() to construct your serial output text to make the code a bit less convoluted.

    Serial.printlnf("Flow rate             : %6.1f l/min \r\n"
                    "Current Liquid Flowing: %6d ml/s \r\n"
                    "Output Liquid Quantity: %6d ml"
                   , flowRate
                   , flowMilliLitres
                   , totalMilliLitres
                   );
    char txt[32];
    snprintf(txt, sizeof(txt), "%d ml/s (%d ml total)", flowMilliLitres, totalMilliLitres);
    Particle.publish("FlowRate", txt);

You also use single quotes where you definitely need double quotes. Single quotes are for single characters only, strings require double quotes.

BTW, I also indented your code as this makes following the code flow a lot easier, not only for us but for yourself too. It's a habit you should adopt as early as possible if you want to wirte clean code.

2 Likes

Hey guys,
Thanks alot for the help, so i did change the code and now i can see the input in the events tab, however for some odd reason, my "FlowRatesmlPerSec " remains a constant even when their is no input from the sensor.
Yet "totalFlowInML" keeps increasing even with no input.
A little bit more help would be much apreciated,
thanks in advance.

Here is the code i now use

byte statusLed    = D7; 
byte sensorInterrupt = D2;  // 0 = digital pin 2 
byte sensorPin       = D2; 
// The hall-effect flow sensor outputs approximately 4.5 pulses per second per litre/minute of flow. 
float calibrationFactor = 4.5;
volatile byte pulseCount;  
float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;
unsigned long oldTime;
void setup()
{
// Initialize a serial connection for reporting values to the host
Serial.begin(38400);
// Set up the status LED line as an output
pinMode(statusLed, OUTPUT);
digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
pinMode(sensorPin, INPUT_PULLUP);
digitalWrite(sensorPin, HIGH);
pulseCount        = 0;
flowRate          = 0.0;
flowMilliLitres   = 0;
totalMilliLitres  = 0;
oldTime           = 0;
attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}
void loop()
{
if((millis() - oldTime) > 1000)    // Only process counters once per second
{ 
//detachInterrupt(sensorInterrupt);
flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
oldTime = millis();
flowMilliLitres = (flowRate / 60) * 1000;
totalMilliLitres += flowMilliLitres;
unsigned int frac;
char str[10];
char str2[10];
Serial.print('Flow rate: ');
Serial.print(int(flowRate));  // Print the integer part of the variable
Serial.print('.');             // Print the decimal point
frac = (flowRate - int(flowRate)) * 10;
Serial.print(frac, DEC) ;      // Print the fractional part of the variable
Serial.print('L/min');
Serial.print('  Current Liquid Flowing: ');             // Output separator
Serial.print(flowMilliLitres);
Serial.print('mL/Sec');
sprintf(str, "%d", flowMilliLitres);
Particle.publish("FlowRatesmlPerSec", str);
Serial.print("  Output Liquid Quantity: ");             // Output separator
Serial.print(totalMilliLitres);
Serial.println("mL"); 
sprintf(str2, "%d", totalMilliLitres);
Particle.publish("totalFlowInML", str2);
  }
}
 void pulseCounter()
{
  pulseCount++;
} 

Can you help us read your code by decluttering it and formatting it to make it a bit easier on our eyes :wink:

BTW, with two publishes and only one second waiting time you will run into the publish rate limit - that's also why I adapted your code to only publish once.

The solution to your current problem was already provided by @rickkas7 in his original response.
You even quote it in your post but the code you provided doesn't show it applied as it was meant.

Not in setup() but after you used it in your calculation :wink:

Hi, you didn't follow any of suggestion provided by @rickkas7 and @ScruffR except one:

Also you publish rate is 2 per sec you have to wait at least 2 sec for recover here is a nice explanation but with this:

you don't need to care about Publish rate ( all is done at once )

try this code (not tested):

#include "Particle.h"

#define statusLed D7 
#define sensorInterrupt D2  // 0 = digital pin 2 

/*byte sensorPin       = D2;  why why why ??? */

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per litre/minute of flow. 

volatile byte pulseCount = 0;
float calibrationFactor = 4.5;
float flowRate = 0.0;

unsigned int flowMilliLitres = 0;
unsigned long totalMilliLitres = 0;
unsigned long oldTime = 0;

void setup()
{
//Initialize a serial connection for reporting values to the host

    Serial.begin(38400);

//Set up the status LED line as an output

    pinMode(statusLed, OUTPUT);
    digitalWrite(statusLed, HIGH);  // We have an active-low LED attached

//Set up internal pullup on D2 
 
    pinMode(sensorInterrupt, INPUT_PULLUP);

/*digitalWrite(sensorPin, HIGH); why why why ??? old Arduino style*/

    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}

void loop()
{

    if((millis() - oldTime) > 1000)   // Only process counters once per second
     { 
        flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
        oldTime = millis();
        flowMilliLitres = (flowRate / 60) * 1000;
        totalMilliLitres += flowMilliLitres;
        pulseCount = 0;

        Serial.printlnf("Flow rate: %6.1f l/min \r\n"
                        "Current Liquid Flowing: %6d ml/s \r\n"
                        "Output Liquid Quantity: %6d ml"
                       , flowRate
                       , flowMilliLitres
                       , totalMilliLitres
                       );

        char msg[32];
        snprintf(msg, sizeof(msg), "%d ml/s (%d ml total)", flowMilliLitres, totalMilliLitres);
        Particle.publish("FlowRate", msg, PRIVATE);
     }
}

 void pulseCounter()
{
  pulseCount++;
} 
1 Like

Hey guys,
Thanks alot for the help, @dreamER 's code worked like a charm.

Thank you so much, @ScruffR, thanks for the help , Im new to the whole programming thing, so im sorry that my code was hard on your eyes but i truly appreciate your help and advise.

you guys rock

@unknown5666, there is nothing wrong in being a beginner and kudos for jumping into it :+1:

One thing I want to implore you to do is to have a close look at @dreamER’s code.
He has taken the advice given by Rick and myself and incorporated it as it was meant, so don’t just take his code as is but compare it to your own and see where it it differs and give it a good thought why it’s done that way (including the look and feel of well written code in other threads).

For instance try to understand which of these changes made the difference between your non-working code and this. Why does it work now?

In programming it’s not the solution for one problem that counts but the skill to deconstruct any set problem and how to approach it systematically.

That’s why I rather provide hints and verbal pointers to find the solution yourself than “ready-meal” code.
Code you got working yourself will benefit you more than taking a solution as is without paying attention to the question why and how it works.

Some notes tho’

I’d advise against is using #define when it isn’t strictly necessary and rather go with this

const int statusLed       = D7; 
const int sensorInterrupt = D2; 

Also don’t “over comment”. Adding comments for the obvious makes it harder to focus on the important comments.

Remove “zombi code” and don’t break the visual code flow with superfluous blank lines and full-line comments unless you have very distinct code blocks you explicitly want to separate.

Don’t use block comments (/* ... */) whenever you can use line comments (// ...).
This allows you to temporarily comment code sections for debugging by surrounding them with block comments. That’s not possible as soon only one block comment in your regular code would appear inside that block.

1 Like

As always a constructive criticism, especially from the Master like @ScruffR is warmly appreciated :blush:
But you guys have to forgive me as I’m still in learning mode :grin: ( I have a fealing that I stuck in this mode forever :see_no_evil: ) So… if there’s any opportunity for exercising I’m not gonna loose them :+1:
Consider the advise to go over your code and mine, line by line and you gonna see just a little diffrences which I applay after @ScruffR and @rickkas7 advised to you in previus posts, try to modyfy something, just play arround for exercising :wink:

1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.