Variation in the voltage value for no input using Arduino

Hello Everyone!

So I am basically trying to have the Arduino to run a flow controller HFC-302 specially calibrated for Nitrogen/Air. They specially requires a bipolar +15V, -15V and COM to run [don’t worry about the gas for now]. Now based on the connection document available online for the reference, pin 05 and pin 12 which are also internally connected in the flow controller are signal common , and hence the pins 05 in my case has been connected to the COM of the power supply. To ensure proper grounding, pin 07 on the controller was earthed on the GND case of the power supply and the Arduino GND was connected to the board of the breadboard on row 15. Similarly, the Resistor and capacitor was also connected, as the input from the Arduino was considered using the PWM 5 and hence has to be converted to the analog signal, the resistor and capacitor used are respectively 10kohms and 10uF for the conversion. Now when I will use the code , the signal will move from PWM to then via RC circuit to the controller and output will be obtained at pin A1 of the Arduino taking output from the flow controller from pin 06. The issue is that I am observing -0.4V between PWM and pin 05 on the flow controller with no flow condition. Maybe the grounding is not proper, but I am not sure if this is normal, anyone has any recommendations. for connecting the wires I am using WAGO221 connectors .

They often say that a picture is worth a thousand words. Please make a drawing. Clearly show the connections between all components; don't forget GND and power lines.

Please post a (link to) the datasheet / user manual of the HFC-302.

Please show your code; as you have been away for a while, remember to use code tags as described in https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum/679966#posting-code.

Thank you so much for reply, given below I have uploaded the manual and the connection drawing , apologizes for I am not good in drawing, if you have questions let me know, I will be adding the code as well.

/ ---------------- USER CONFIG ----------------

const int pwmPin = 5; // PWM output to flow controller

const int analogPin = A1; // Analog input from flow controller const float fullScaleVoltage = 5.0; // Maximum voltage representing full flow const float fullScaleFlow_H2 = 1000.0; // Hydrogen full scale flow in sccm const float H2_correctionFactor = 1.41; // Gas correction factor if MFC is calibrated for another gas float zeroOffset = 0.0; // Voltage reading when flow is zero float calibrationOffset = 0.0; // Optional voltage calibration if measured voltage is slightly off
// ---------------- CONTROL PARAMETERS ----------------

151-HFM-300_HFC-302_Manual.pdf (3.1 MB)

float Kp = 2.0; // Proportional gain for PWM adjustment int pwmValue = 0; // Stores current PWM value float desiredFlowPercent = 0; // User input desired flow % unsigned long startTime; // Timer for logging time bool simulationRunning = true; // Flag to control STOP/START void setup() { // Initialize serial communication at 9600 baud Serial.begin(9600); // Set PWM pin as output pinMode(pwmPin, OUTPUT); // Print CSV header for easy plotting Serial.println("Time_ms,PWM_Voltage,Measured_Voltage,Error_Voltage"); // Initialize timer startTime = millis(); // Instructions for user Serial.println("Enter desired flow % (0-100) via Serial Monitor:"); Serial.println("Type STOP to pause simulation and START to resume."); } void loop() { // ---------------- HANDLE USER INPUT ---------------- if (Serial.available() > 0) { String inputString = Serial.readStringUntil('\n'); // Read input until Enter inputString.trim(); // Remove any whitespace/newline if (inputString.equalsIgnoreCase("STOP")) { // Pause the simulation simulationRunning = false; Serial.println("Simulation stopped. Type START to resume."); } else if (inputString.equalsIgnoreCase("START")) { // Resume simulation simulationRunning = true; startTime = millis(); // Reset timer for logging if needed Serial.println("Simulation resumed."); } else { // Treat input as desired flow % desiredFlowPercent = inputString.toFloat(); desiredFlowPercent = constrain(desiredFlowPercent, 0, 100); // Limit between 0-100% } } // ---------------- CLOSED-LOOP CONTROL ---------------- if (simulationRunning) { // Convert desired flow % to desired voltage float desiredVoltage = (desiredFlowPercent / 100.0) * fullScaleVoltage; // Read measured voltage from MFC (0-1023) and convert to 0-5V float measuredVoltage = analogRead(analogPin) * (5.0 / 1023.0); measuredVoltage = constrain(measuredVoltage, 0.0, fullScaleVoltage); // Apply zero offset and calibration offset float correctedVoltage = measuredVoltage - zeroOffset + calibrationOffset; correctedVoltage = constrain(correctedVoltage, 0.0, fullScaleVoltage); // Calculate error voltage float errorVoltage = desiredVoltage - correctedVoltage; // Update PWM proportionally to reduce error pwmValue += Kp * (errorVoltage / fullScaleVoltage) * 255; // Scale error to PWM units pwmValue = constrain(pwmValue, 0, 255); // Ensure PWM stays in valid range analogWrite(pwmPin, pwmValue); // Send PWM to MFC // Calculate PWM voltage for logging float pwmVoltage = (pwmValue / 255.0) * fullScaleVoltage; // ---------------- LOG DATA ---------------- unsigned long currentTime = millis() - startTime; Serial.print(currentTime); Serial.print(","); // Time in ms Serial.print(pwmVoltage, 3); Serial.print(","); // PWM voltage Serial.print(correctedVoltage, 3); Serial.print(","); // Measured voltage Serial.println(errorVoltage, 3); // Error voltage // Sampling delay (adjust as needed, 200 ms = 5 Hz) delay(200); } }

Thanks

Next time please rotate your image before posting; it makes it easier.

They way your code was posted is a mess; that is probably not your fault but due to a bug in the forum software.

Please retry.

  1. Click the circled button in the below image till you get the layout of the below image.
  2. In the IDE
    • use tools → auto format
    • use edit → copy for forum to copy the code to the clipboard.
  3. Paste the content of the clipboard.
  4. Either fix your post or create a new reply and paste the
/ ---------------- USER CONFIG ----------------
const int pwmPin = 5;        // PWM output to flow controller
const int analogPin = A1;    // Analog input from flow controller

const float fullScaleVoltage = 5.0;       // Maximum voltage representing full flow
const float fullScaleFlow_H2 = 1000.0;    // Hydrogen full scale flow in sccm
const float H2_correctionFactor = 1.41;   // Gas correction factor if MFC is calibrated for another gas

float zeroOffset = 0.0;       // Voltage reading when flow is zero
float calibrationOffset = 0.0; // Optional voltage calibration if measured voltage is slightly off

// ---------------- CONTROL PARAMETERS ----------------
float Kp = 2.0;               // Proportional gain for PWM adjustment
int pwmValue = 0;             // Stores current PWM value
float desiredFlowPercent = 0; // User input desired flow %

unsigned long startTime;      // Timer for logging time
bool simulationRunning = true;  // Flag to control STOP/START

void setup() {
  // Initialize serial communication at 9600 baud
  Serial.begin(9600);

  // Set PWM pin as output
  pinMode(pwmPin, OUTPUT);

  // Print CSV header for easy plotting
  Serial.println("Time_ms,PWM_Voltage,Measured_Voltage,Error_Voltage");

  // Initialize timer
  startTime = millis();

  // Instructions for user
  Serial.println("Enter desired flow % (0-100) via Serial Monitor:");
  Serial.println("Type STOP to pause simulation and START to resume.");
}

void loop() {
  // ---------------- HANDLE USER INPUT ----------------
  if (Serial.available() > 0) {
    String inputString = Serial.readStringUntil('\n'); // Read input until Enter
    inputString.trim(); // Remove any whitespace/newline

    if (inputString.equalsIgnoreCase("STOP")) {
      // Pause the simulation
      simulationRunning = false;
      Serial.println("Simulation stopped. Type START to resume.");
    }
    else if (inputString.equalsIgnoreCase("START")) {
      // Resume simulation
      simulationRunning = true;
      startTime = millis(); // Reset timer for logging if needed
      Serial.println("Simulation resumed.");
    }
    else {
      // Treat input as desired flow %
      desiredFlowPercent = inputString.toFloat();
      desiredFlowPercent = constrain(desiredFlowPercent, 0, 100); // Limit between 0-100%
    }
  }

  // ---------------- CLOSED-LOOP CONTROL ----------------
  if (simulationRunning) {
    // Convert desired flow % to desired voltage
    float desiredVoltage = (desiredFlowPercent / 100.0) * fullScaleVoltage;

    // Read measured voltage from MFC (0-1023) and convert to 0-5V
    float measuredVoltage = analogRead(analogPin) * (5.0 / 1023.0);
    measuredVoltage = constrain(measuredVoltage, 0.0, fullScaleVoltage);

    // Apply zero offset and calibration offset
    float correctedVoltage = measuredVoltage - zeroOffset + calibrationOffset;
    correctedVoltage = constrain(correctedVoltage, 0.0, fullScaleVoltage);

    // Calculate error voltage
    float errorVoltage = desiredVoltage - correctedVoltage;

    // Update PWM proportionally to reduce error
    pwmValue += Kp * (errorVoltage / fullScaleVoltage) * 255; // Scale error to PWM units
    pwmValue = constrain(pwmValue, 0, 255); // Ensure PWM stays in valid range
    analogWrite(pwmPin, pwmValue); // Send PWM to MFC

    // Calculate PWM voltage for logging
    float pwmVoltage = (pwmValue / 255.0) * fullScaleVoltage;

    // ---------------- LOG DATA ----------------
    unsigned long currentTime = millis() - startTime;
    Serial.print(currentTime); Serial.print(",");       // Time in ms
    Serial.print(pwmVoltage, 3); Serial.print(",");     // PWM voltage
    Serial.print(correctedVoltage, 3); Serial.print(","); // Measured voltage
    Serial.println(errorVoltage, 3);                     // Error voltage

    // Sampling delay (adjust as needed, 200 ms = 5 Hz)
    delay(200);
  }
}

Let me also upload an image which explains the connections to the best way I could 
![image|504x500](upload://cpGydieiAGgj3Hz7m7qOG7Gh00V.jpeg)

Apologies here is the image I wanted to share.

As I understand the figures 2.1 in the manual the signal ground should be connected to the controller, not to any other GND. The differential ADC input may provide much better results.

Pin 05 is unspecified in "U" (voltage) pin-out.

Your code says you use A1, your picture says A0...
Keep the signal wires and gnd wire to analog input together..
Maybe add small cap near analog input. A resistor of 10k to gnd may also help... the manual seems to imply 2k or even less...
It is difficult to follow, but you may have created gnd loops...

It appears that the controller is not responding properly to the code The voltages across the pins are ok, but the valve is not opening properly
regards
Ketan

You're using low pass filtered, 980Hz PWM for a set point signal? How much ripple on that signal (in millivolts)?
Think I would use a 12 bit DAC with a tight reference voltage supply.

Well, the voltage on the Arduino at max is just 5.1V, with the flow controller I am using using a +15 and -15V, and COM being connected to pin 05 and grounded well. The minimum voltage with no flow condition is around 0.01 V. I am using an RC filter of 10Kohm and 10uF for the signal for PWM, with the voltage variation between 0-5V. What is DAC for ? Why would the valve not respond?
regards
Ketan

Hello Everyone, so the interesting thing that I am observing is that the voltage across the inputs and outputs at the pin of the flow controller and also at the Arduino are matching based on requirements giving 100%=5V, 50%=2.5V and 0%=0V, but the valve is not opening properly somehow the valve maybe stuck or I would assume the signal is not going to the valve properly? This is an H-pin out. Any suggestions? I can also share my code if someone would like to have a look and go through the logic. The flow controller is N2-based calibrated, but using H2, and hence the gas correction factor was used in the code, given below is the code:

// -------------------------------
// Arduino Flow Controller with H2 Correction
// -------------------------------

const int pwmPin = 5;        // PWM output to flow controller
const int measurePin = 16;   // Analog input (A2)

const float gasCorrectionFactor = 1.004;  // N2 → H2 correction

void setup() {
  pinMode(pwmPin, OUTPUT);
  pinMode(measurePin, INPUT);

  Serial.begin(9600);
  while (!Serial) { ; } // Wait for Serial Monitor
  Serial.println("Enter desired flow % (0-100) for H2:");
}

void loop() {
  if (Serial.available() > 0) {
    int flowPercent = Serial.parseInt();
    Serial.read(); // clear newline

    // Constrain flow % between 0 and 100
    flowPercent = constrain(flowPercent, 0, 100);

    // Apply gas correction factor
    float correctedFlow = flowPercent * gasCorrectionFactor;
    correctedFlow = constrain(correctedFlow, 0, 100); // clamp to 100%

    // Map corrected flow % to PWM value (0-255)
    int pwmValue = map(correctedFlow, 0, 100, 0, 255);

    // Output PWM
    analogWrite(pwmPin, pwmValue);

    delay(50); // small delay for stabilization

    // Read ADC value
    int adcValue = analogRead(measurePin); // 0-1023

    // Convert ADC to voltage (0-5V)
    float measuredVoltage = (adcValue / 1023.0) * 5.0;

    // Clamp measured voltage to max 5 V
    if (measuredVoltage > 5.0) measuredVoltage = 5.0;

    // Calculate expected voltage for H2
    float expectedVoltage = (correctedFlow / 100.0) * 5.0;

    // Print results
    Serial.print("Flow % (H2): "); Serial.print(flowPercent);
    Serial.print("  PWM Value: "); Serial.print(pwmValue);
    Serial.print("  Expected Voltage: "); Serial.print(expectedVoltage, 2);
    Serial.print(" V  Measured Voltage: "); Serial.println(measuredVoltage, 2);

    Serial.println("\nEnter next desired flow % (0-100) for H2:");
  }
}

That's why typically PWM is used for the set point, at a recommended frequency. Then the ripple will prevent the valve from sticking.

Oh , then how can I reduce the ripple effect?

I would assume it to be solenoid issue

Consult the data sheet.

A wiring diagram would be really useful.
You say you measure the correct voltages. But what is the reference of the measured voltage?

Thank you for your reply, with no flow condition , I am observing a voltage of 0.01V on the PWM pin, for flow conditions, 50% is giving me 2.5/2.6V and then 100% flow is 5/5.1V output. I have uploaded the wiring diagram below, the wire from the pin12 is removed since, pin 05 and pin 12 is interconnected. For a 100% flow, I am also observing a 5V on the Arduino pin A2(output pin connected to pin 06), but my code is giving different values(probably a code issue I suppose). though the valves are opening.

Given below is an image, please have a look.

The document using which these connections were made is also shared below,

151-HFM-300_HFC-302_Manual.pdf (3.1 MB)

If you have any questions, let me know. I believe the flow controller works on the principle of creating a pressure difference between input(upstream) and output(downstream). The flow controller is rated at an upstream pressure of 90 psig for the downstream pressure variation between 0-30 psi.

That is not a wiring diagram. It is a picture of a somewhat messy setup...

It looks messy yes, I have uploaded the document which should have the pin diagram