Publishing messages too rapidly


#1

Hello,

I do I make sure that particle only published once. I have rpm being measured on a pump and will run the pump for 1 minute once a button is pressed.

Can someone tell me how to only send the rpm once after the pump runs for a certain time.

here is code
Thanks

// This #include statement was automatically added by the Particle IDE.
#include <Ubidots.h>

//define the input/output pins
//pump/relay pins
#define PUMP_IN_PIN 3
#define PUMP_OUT_PIN 2

//pushbutton pins
#define BUTTON_1_PIN 5
#define BUTTON_2_PIN 6

//Time for pumping stations to turn on in milliseconds
#define PUMP_IN_TIME 60000
#define PUMP_OUT_TIME 60000


const byte interruptPin = 4; //digital pin for hall effect
volatile unsigned long halltime, halllast, hallinterval; // timing variables
int rpm;
int pulsecount;

//Ubidots info
//   //Ubdiots
#ifndef TOKEN
#define TOKEN "BBFF-"  // Put here your Ubidots TOKEN
#endif

Ubidots ubidots(TOKEN, UBI_TCP); //Non Education 

char data[200];

//setup() runs once
void setup(){
    
    Serial.begin(115200);
  pinMode(interruptPin, INPUT_PULLUP); //set pin mode with pullup
  attachInterrupt(interruptPin, HallPulse, FALLING); //attach interrupt
  Serial.println("Hall Effect RPM Test");
    
  //setup output pins for pumping stations
  pinMode(PUMP_IN_PIN, OUTPUT);
  pinMode(PUMP_OUT_PIN, OUTPUT);
  
  //setup input pins for buttons
  pinMode(BUTTON_1_PIN, INPUT);
  pinMode(BUTTON_2_PIN, INPUT);  

}

//loop() runs indefinitely
void loop(){

  //check pushbutton on pin BUTTON_1_PIN to see if it is HIGH (it has been pressed)
  if(digitalRead(BUTTON_1_PIN) == HIGH)
  {
     digitalWrite(PUMP_IN_PIN, HIGH); //turn pump 1 on
     delay(PUMP_IN_TIME);             //wait PUMP_1_TIME milliseconds
     digitalWrite(PUMP_IN_PIN, LOW);  //turn pump 1 off
  }
  
  //check pushbutton on pin BUTTON_2_PIN to see if it is HIGH (it has been pressed)
  if(digitalRead(BUTTON_2_PIN) == HIGH)
  {
     digitalWrite(PUMP_OUT_PIN, HIGH); //turn pump 2 on
     delay(PUMP_OUT_TIME);             //wait PUMP_2_TIME milliseconds
     digitalWrite(PUMP_OUT_PIN, LOW);  //turn pump 2 off
  }
  
  rpm = pulsecount*2;
    
    snprintf(data, sizeof(data)-1, "%0.d%",rpm);
Particle.publish("rpm", data, PRIVATE);

    
    
    ubidots.add("rpm", rpm);
    //ubidots.send();
  pulsecount = 0;

}

void HallPulse(){
 noInterrupts();
  halltime = millis();                // get current time
  hallinterval = halltime - halllast; // calc time since last pulse
  if (hallinterval > 50)             // ignore switch-bounce glitches less than 50 ms 
   {
     pulsecount++;                        // increment counter, sum # of tips
     halllast = halltime;              // set up for next event
   }    
 interrupts(); 
  
 }

#2

Are you actually using a Hall sensor?
If so, you shouldn’t need INPUT_PULLUP nor switch debouncing.
On the other hand, for your buttons you should use pull-down resistors (internal or external).

You also don’t want to use delay().
There are multiple ways to do the timing, but I’d go with two one-shot software timers.

Inside the timer callback I’d switch off the respective OUTPUT pin and set a flag which then “allows” loop() to publish.

BTW, pulsecount also needs to be declared volatile.
I’m also not sure why you only have one set of pulsecount and rpm but seem to have two pumps.


#3

Thanks ScruffR

im a little lost when you say

Inside the timer callback I’d switch off the respective OUTPUT pin and set a flag which then “allows” loop() to publish.

An example would be great.

I have never used timer so maybe ill research that first and the rest will come.
Also I have one pump but can forward and reverse pump.

This is just a code to test the pump. Is the delay the main issue why its publishing lot. I understand that using delay is bad but I also and new to coding and find it very difficult to implement the other timing code like blink without delay. Can I leave the delay and still just fix the publishing frequency. I


#4

OK, just off the top of my head without testing, but you should get the idea

bool  needPublish = false;
Timer offTimer(60000, switchOff, true); // create a one-shot timer which
                                        // calls switchOff after 60 seconds
...
void switchOff() {
  digitalWrite(pinPumpIn , LOW);       // all off
  digitalWrite(pinPumpOut, LOW);
  needPublish = true;
}
...
void loop() {
  if (digitalRead(pinButton1)) {
    rpm = pulsecount = 0;             // reset all counters
    digitalWrite(pinPumpIn, HIGH);    // switch on 
    offTimer.start();                 // prepare switch off after one minute
    delay(100);                       // poor man's button debounce
  }
  ...

  if (needPublish) {
    rpm = pulsecount*2;
    snprintf(data, sizeof(data), "%d", rpm);
    Particle.publish("rpm", data, PRIVATE);
    needPublish = false;
  }
}

Since I doubt you’ll have tens of kHz interrupts and using a non-bouncing hall sensor I think you can get away with this simple ISR.

volatile uint32_t pulsecount;

void HallPulse() {
  pulsecount++; 
}