Using PWM to control a solenoid valve based on sensor readings

I am using Honeywell ASDXACX100PAAA5 sensors and Parker 912-000007-003 solenoid valves to control pressure from a CO2 cartridge (850-900 PSI) and am having trouble preventing the pressure from the CO2 cartridge from overwhelming my system b/c I want to waste as little CO2 as possible. I've heard that PWM could be a method to help with this and wanted to know what functions/logic would be needed to replace the functions of my current system. Here is the current system's code:

#include <Wire.h>
#include <Adafruit_GFX.h> //Include libraries for different components
#include <Adafruit_SSD1306.h>

//Setup for OLED:
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define SysValve 37
#define ExitValve 36
#define DistValve 35
#define MidValve 34
#define ProxValve 33

#define SysMin 27
#define SysMax 40

#define DistMin 27 
#define DistMax 27

#define MidMin 27
#define MidMax 27

#define ProxMin 27 
#define ProxMax 27

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();

  pinMode(SysValve, OUTPUT);  //Setting the output pins to the valves:
  pinMode(ExitValve, OUTPUT);
  pinMode(DistValve, OUTPUT);
  pinMode(MidValve, OUTPUT);
  pinMode(ProxValve, OUTPUT);

  pinMode(A0, INPUT); //Setting input pins from sensors
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);

  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
   display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
}

void loop() {


      digitalWrite(ExitValve, LOW);   //Reset all valves to closed:
  digitalWrite(SysValve, LOW);
  digitalWrite(DistValve, LOW);
  digitalWrite(MidValve, LOW);
  digitalWrite(ProxValve, LOW);
  
  int ProxRead=analogRead(A0);
  int DistRead=analogRead(A2); //Sensor readings
  int MidRead=analogRead(A1);
  int SysRead=analogRead(A3);

  int SysPSI= SysRead/(222/14.7);
  int DistPSI= DistRead/(222/14.7);
  int MidPSI= MidRead/(222/14.7);
  int ProxPSI= ProxRead/(222/14.7);

  display.clearDisplay(); //Display setup
  display.setCursor(0,0);

  display.print(F("System Pressure: ")); //Displaying sensor readings:
  display.println(SysPSI);
  display.print(F("Distal Pressure: "));
  display.println(DistPSI);
  display.print(F("Middle Pressure: "));
  display.println(MidPSI);
  display.print(F("Proximal Pressure: "));
  display.println(ProxPSI);
  display.display();  

       if (SysPSI<SysMin) { // If the pressure is lower than desired pressure let air in:
        digitalWrite(ExitValve, LOW);
        digitalWrite(SysValve, LOW);
      }
      if (DistPSI<DistMin) {
        digitalWrite(ExitValve, LOW);
        digitalWrite(SysValve, HIGH);
        digitalWrite(DistValve, HIGH);
        delay(15);
      }
      if (MidPSI<MidMin) {
        digitalWrite(ExitValve, LOW);
        digitalWrite(SysValve, HIGH);
        digitalWrite(MidValve, HIGH);
      }
      if (ProxPSI<ProxMin) {
        digitalWrite(ExitValve, LOW);
        digitalWrite(SysValve, HIGH);
        digitalWrite(ProxValve, HIGH);
        delay(15);
      }
      
      if (SysPSI>SysMax) {
        digitalWrite(ExitValve, HIGH);
        digitalWrite(SysValve, HIGH);
        delay(15);
        digitalWrite(SysValve, LOW);
      }
      if (DistPSI>DistMax) {  // If the pressure is higher than desired pressure let air out:
        digitalWrite(SysValve, LOW);
        digitalWrite(ExitValve, HIGH);
        digitalWrite(DistValve, HIGH);
      }
      if (MidPSI>MidMax) {
        digitalWrite(SysValve, LOW);
        digitalWrite(ExitValve, HIGH);
        digitalWrite(MidValve, HIGH);
      }
      if (ProxPSI>ProxMax) {
        digitalWrite(SysValve, LOW);
        digitalWrite(ExitValve, HIGH);
        digitalWrite(ProxValve, HIGH);
      }

     digitalWrite(DistValve, LOW);
     digitalWrite(MidValve, LOW);
     digitalWrite(ProxValve, LOW);

      if (DistPSI<DistMin) {
        digitalWrite(ExitValve, LOW);
        digitalWrite(SysValve, HIGH);
        digitalWrite(DistValve, HIGH);
        
      }
      if (ProxPSI<ProxMin) {
        digitalWrite(ExitValve, LOW);
        digitalWrite(SysValve, HIGH);
        digitalWrite(ProxValve, HIGH);
        delay(5);
      }
      if (SysPSI>SysMax) {
        digitalWrite(ExitValve, HIGH);
        digitalWrite(SysValve, HIGH);
      }
      if (SysPSI>SysMax) {
        digitalWrite(ExitValve, HIGH);
        digitalWrite(SysValve, HIGH);
      }

    delay(5);
  
}

I was thinking that I could change the system to use digitalWrite functions that control the valves and change their duty cycles using if functions to increase and decrease the number in the digitalWrite functions, adjusting the duty cycles of each valve until each is letting through as much air as needed.

Where?
Your theory about how to make/use PWM is home made and useless.
Look up arduino/reference and analogWrite.

As soon as you use the word "control" that means you have feedback from some sensor. Do you really want control or are you just releasing gas pressure randomly?
Unless you are releasing the CO2 into a vacuum, you are already wasting it by mixing with air.
What are you really trying to do with your project?
Paul

See analogWrite() how to produce PWM signals.

For the duty cycles of the various valves you should have some idea how these depend on the measured pressures.

It is not guaranteed that a specific PWM duty cycle will result in an equivalent opening or throughput. The data sheet only mentions PWM as a means of valve power reduction.

I'm controlling the pressure within 3 chambers in a soft prosthetic and 1 chamber coming out of the CO2 cartridge. The idea of using PWM was from someone I know.

I see you are using Honeywell pressure sensors. Are these working for you?
What is the problem you are having with just releasing some CO2 and watching the pressure and then releasing some more in your regular program? Are you overshooting the required pressure?
Do you have a needle valve to control the gas release?
Paul

The Honeywell sensors are working quite well, my problem is that this program is going to be used in the future with more chambers and needs to be scalable as well as usable for long periods. The current program seems to dump CO2 like no tomorrow and can only get the Middle Chamber up to pressure. (I suspect that is due to egregious leaking and have applied sealant to the necessary areas, just waiting for it to cure.) I have a valve that is controlling the amount of CO2 coming out of the cartridge and it tends to have almost no leeway between releasing nothing and too much CO2.

As I already suspected :frowning:

The last couple times I tested the system it wasn't usually overloading the system but always changes how much pressure is going through the system when I set the CO2 cartridge and valve down. Here's the CO2 valve I'm using.

Then your valve does not contain a needle valve that limits the volume of gas flowing. Add a needle valve between your current valve and the device you are inflating.
Paul

I ordered a ball valve and it's on its way, would that work instead of a needle valve?

If a valve is going to provide continuously variable flow by modulating the operating voltage (or current) it must be specially designed to do so. It's very hard to achieve that level of control using a solenoid, as (depending upon the design) the gas pressure can generate a fair bit of static friction ("stiction") which must be overcome before the valve starts opening. As soon as it opens it tends to"snap" the rest of the way as the friction reduces. Also, some solenoids have a built-in tendency to "snap" because the mechanical force from the magnetic field increases as the solenoid moves towards the operated position. This allows the solenoid to be held open with a much lower current.

I would approach this by researching motorised valves, which I think would meet your needs much better.

Meanwhile, how about making a restriction to seriously limit the gas flow rate? Then you could pulse the solenoid until sufficient gas has been delivered.

By the way, those valves you linked to can only handle 100psi, but your CO2 is at 850psi. Is this a mistake?

I was thinking of PWM as a way to turn the valves on/off faster than my current system, is it possible to mess with the frequency to do this instead of altering the voltage? The CO2's flow is being somewhat limited by this valve. I ordered a ball valve yesterday which should limit the flow more, would that work?

That's why analog valves prefer operation by PWM and a low frequency of e.g. 100 Hz. Then the signal ripple will prevent the valve from sticking. See the data sheets of analog valves.

1 Like

Are there any analog/proportional valve of similar size to the Parker valves I'm using? Size is a major constraint for my project

Yep. However, PWM control is not mentioned in the data sheet for the valves the OP cited.

Anyway, @kidt, what about my question? 100psi valves controlling 850psi gas?

The gas is not at 850psi when it enters the system b/c the valve lowers its flow enough to keep the psi where the sensors can read it.

1 Like

Not at all. If you are not familiar with a needle valve, it is controlled by a moveable pin, shaped like a needle with a fine point that fits into a similar shaped receptical. A screw controls the position of the needle. Fully seated, the gas flow is zero. As the needle is moved, more gas is allowed to escape past the needle. Very fine threads on the needle mean very fine control of the volume of gas escaping.
This will give you fine control of the CO2 flow and pressure.
Several years ago I bought needle valve on Ebay to use in a nitrogen gas generation system we were installing. You will need to do the plumbing, but are likely already doing that.
Paul