Pulse/Frequency Counting from Flow Meter

Hello, i'm rather new to the PLC/controller world and very much like to learn about it more. I was tasked with a project - find a pressure drop of a product. I have 2 K-type thermocouples, 2 pressure transducers (4-20ma), and a solenoid (analog output).

Keeping all that in mind i need to read pulses or frequency from a flow meter. Currently I have it adjusted to 0.1 Lb/min per pulse with a pulse width of 150ms. I've written the following code to test sensors and it does not get anywhere near what the actual value is (20 Lb/min) and it doesn't seem to be stable either. I've tried using the interrupt method found on this forum with no luck either.


#include <Arduino_MachineControl.h>
#include <USBHost.h>
#include "Wire.h"
#include "USBconn.h"


using namespace machinecontrol;
uint16_t readings = 0; //for digital input
volatile unsigned long pulseCount = 0; // pulse count
unsigned long lastPulseTime = 0; //time of the last pulse
unsigned long currentPulseTime = 0;

//4-20mA Input Setup
#define SENSE_RES 120
float reference = 3.3;

//Flow Rates and Factor
float flowrate = 0.00;

//Temperature Variables
float Tin = 0.00; //Ch0
float Tout = 0.00; //Ch1


void setup() 
{
  Serial.begin(115200);
  Wire.begin();
  Wire.setClock(1000000);

  //Enabling Thermocouples
  temp_probes.tc.begin();
  Serial.println("Temperature probes initialization done");
  temp_probes.enableTC();
  Serial.println("Thermocouples enabled");

  //Enabling Pressure Sensors
  analogReadResolution(16);
  analog_in.set4_20mA();

  //Valve Signal Output - 0-10V ANALOG OUTPUT open
  analog_out.period_ms(0, 10.4);

  //Check Flow Meter Digital Input and Setup
  if (!digital_inputs.init())
  {
    Serial.println("Digital input GPIO expander initialization fail!!");
  }
}


void loop()
{
  //Printing Values from all sensors Continuously

  //Temp in F
  temp_probes.selectChannel(0);
  Tin = temp_probes.tc.readTemperature()*1.8+32;
  Serial.print("Tin:");
  Serial.print(Tin);
  Serial.println();
  temp_probes.selectChannel(1);
  Tout = temp_probes.tc.readTemperature()*1.8+32;
  Serial.print("Tout:");
  Serial.print(Tout);
  Serial.println();
  delay(50);

  //Pressure
  float raw_voltage_ch0 = analog_in.read(0);
  float voltage_ch0 = (raw_voltage_ch0 * reference) / 65535;
  float current0 = (voltage_ch0 / SENSE_RES) * 1000;
  float Pin = (current0-4)*100/16;
  Serial.print("Pin:");
  Serial.print(Pin);
  Serial.println();
  float raw_voltage_ch1 = analog_in.read(1);
  float voltage_ch1 = (raw_voltage_ch1 * reference) / 65535;
  float current1 = (voltage_ch1 / SENSE_RES) * 1000;
  float Pout = (current1-4)*100/16;
  float dP = Pout-Pin;
  Serial.print("Pout:");
  Serial.print(Pout);
  Serial.println();
  Serial.print("dP:");
  Serial.println(dP);
  delay(50);

  //Flow Meter
  readings = digital_inputs.read(DIN_READ_CH_PIN_00);
  if (readings = 1)
  {
    pulseCount++;
    currentPulseTime = millis(); 
  }

  if (pulseCount > 0 && currentPulseTime - lastPulseTime >= 1000)
  {
    flowrate = (pulseCount * 0.1) / ((currentPulseTime - lastPulseTime) / 60000.0);
    Serial.print("flowrate:");
    Serial.print(flowrate);
    Serial.println();
    pulseCount = 0;
    lastPulseTime = currentPulseTime;
  }
  delay(20);

With this confusion of '=' for '==' and the 120ms(?) of delays, I'd bet you get odd readings.

How long does a loop() run?

Hey Dave, thank you for commenting, it takes ~1000 ms to get through the loop. I tried removing delays and it changed the pulse count but still was not accurate.

Did you change:

to

  if (readings == 1)

Per

I don't have the Arduino with me at the moment but i will try that. It seems i was setting the value = 1 instead of comparing it. I feel like there may be something else, but ill check that first and get back to you tomorrow.

The main problem with the pulse width of 150ms and the 1000ms loop time is that you'll miss most of the pulses. You'll need to shorten the loop time.

I can adjust the flow meter output pulse width, and value per pulse. I've tried to do 500ms pulse width pulses but didnt seem to have luck with the accuracy. Now that i know about my == confusion i may have solved the problem. I'd really like not to sacrifice accuracy in any way if possible. I also thought that the volatile tacked on to the variable i did not matter where im at within the loop.

With 20lb/min / (0.1 lb/pulse) * (1min/60 sec) that's 3.33 pulse/sec or 0.3sec/pulse. There isn't time for >300ms/pulse or 300ms/loop. If 20lb/min is max flow, setting it to 150ms/pulse is reasonable. But you need to check the value faster than the pulse width. 75ms between checks at most.

'volatile' doesn't magically change the data-- pulsecount is only changed whenever this bit is executed:

Maybe try modifying the state change detection example to work with your:

to see if it counts more reasonably.

state change was the way to go. however i'm limited to readings to about 120 HZ which i can deal with