Is delay() best for my project?

I have an UNO reading a pressure sensor and displaying said pressure and a force calculation on an LCD. I will electrically raise/lower the pressure with solenoids, but when I do, the pressure drop/rise makes the pressure reading jump dramatically sometimes I think, or it is some electrical interference. I’m not sure there is a good way to correct the goofy readings, besides just not displaying them. I do not need very frequent updates, as I will not be changing the pressure much. I have delay() a few times in my setup section, but only at the end of the loop section. Is too long of “delay()” (maybe 8 seconds or more instead of 2) detrimental to anything besides blocking/not updating the readout? This board is ONLY performing the described function currently. My theory is that if I change the pressure right before it updates the display it is displaying goofy readings(during the pressure change), then takes 2 seconds(delay time) to correct. So if I lengthen the delay() time and I get the timing wrong, it will display goofy numbers for longer, but the chances of hitting that exact time are lower, correct?

#include <LiquidCrystal_PCF8574.h>
#include <Wire.h>
// V 1.00 updates include "setup info" and the filter at 2 to 3 (99/100) decimal break over point changed from 30/30 to 28/29. 
LiquidCrystal_PCF8574 lcd(0x27);

int rawValue= 50; // A/D readings
int offset = 51; // zero pressure adjust
int fullScale = 1085; // max pressure (span) adjust
float pressure; // final pressure
float weight; // Added downforce



void setup() {
  Serial.begin(9600);
  lcd.begin(16,2);
  lcd.setBacklight(255);//lcd._backlight();
  lcd.setCursor(0,0);
  lcd.print("JD 7200 12R30");
  lcd.setCursor(0,1);
  lcd.print("PDF Monitor");
  delay(3000);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Software Version");
  lcd.setCursor(0,1);
  lcd.print("1.00");
  delay(3000);
 
}

void loop() {
  rawValue = analogRead(A0);
  pressure = (rawValue - offset) * 1.2 / (fullScale - offset)*139; // pressure conversion
  weight = (pressure * 3.81)-7.15;
  lcd.setCursor(0,0);
  lcd.print("Press: ");
  lcd.setCursor(9,0);
  lcd.print(pressure, 0); 
  lcd.setCursor(0,1);
  lcd.print("Force: "); 
  lcd.setCursor(12,0);
  lcd.print("PSI");
  lcd.setCursor(8,1);
  if (pressure>29){lcd.print(weight, 0);}
  if (pressure<28){(lcd.setCursor(8,1)),(lcd.print(" ")),(lcd.setCursor(11,1)),(lcd.print(" ")),(lcd.setCursor(9,1)),lcd.print(weight,(0));} //lcd.print(Thermister(analogRead(0)), 0);
  lcd.setCursor(12,1);
  lcd.print("LBS");  
  delay(2000);
}

No, your sensor is working properly. Study up on what happens to fluids when there is a RAPID change in pressure. A pressure wave is created that propagates throughout all the fluid(gas). Your sensor is detecting the pressure wave.

You can likely change the software to ignore any sudden change in pressure. Perhaps a pressure change that lasts only a fraction of a second.

Paul

using delay delays all processing within loop. you can compare a current timestamp using millis() to a previously captured timestamp to do various operations with various periods.

you may want to verify that your measurement of a static pressure is consistent and correct any problem if it isn't.

without using delay, you can measure more frequently and average if necessary. based on a reliable measurement, you can track changes and decide what action to take, when or how often.

i would create sub-functions for different operations rather than put everything under loop(), especially you code to update the lcd display. looks like it could probably be updated every second with the latest measurements

Did you consider using a PID control algorithm? Though it is perhaps mostly used for motor control in our Arduino world, controlling pressure and temperature are classic fields of application.

Paul_KD7HB:
No, your sensor is working properly. Study up on what happens to fluids when there is a RAPID change in pressure. A pressure wave is created that propagates throughout all the fluid(gas). Your sensor is detecting the pressure wave.

You can likely change the software to ignore any sudden change in pressure. Perhaps a pressure change that lasts only a fraction of a second.

Paul

I am aware, and to make it even worse, how it is plumbed(from original mfg) the pressure sensor takes the brunt of the pressure spikes/dips. I thought about a mechanical damper of sorts but I think some sort of programming would be a better bet. From extensive to just a delay - balancing performance and simplicity will be the way I go. I'm not very experienced with the other options y'all have suggested. So I am not even sure where a good starting point would be besides pure trial and error.

brunt of the pressure spikes/dips.

you might consider median filter to limit spikes followed by a little bit of averaging. seems like you have enough time

The pressure peaks are really there, so in my eyes it would make sense to display them.

You can indeed use a median filter to smooth it out. There are other options besides delay to limit the number of measurements you take. For example, here’s a piece of code that measures A0 every 10 ms, applies a median filter and then prints it. It doesn’t block, so the loop can do other things, even when waiting for the next sample instant.

MedianFilter.ino (Arduino-Filters library)

[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]Filters[/color][/b][color=#434f54].[/color][color=#000000]h[/color][color=#434f54]>[/color]

[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]AH[/color][/b][color=#434f54]/[/color][color=#000000]STL[/color][color=#434f54]/[/color][color=#000000]cmath[/color][color=#434f54]>[/color]
[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]AH[/color][/b][color=#434f54]/[/color][color=#000000]Timing[/color][color=#434f54]/[/color][color=#000000]MillisMicrosTimer[/color][color=#434f54].[/color][color=#000000]hpp[/color][color=#434f54]>[/color]
[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]Filters[/color][/b][color=#434f54]/[/color][b][color=#d35400]MedianFilter[/color][/b][color=#434f54].[/color][color=#000000]hpp[/color][color=#434f54]>[/color]

[color=#00979c]void[/color] [color=#5e6d03]setup[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000]115200[/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]

[color=#434f54]// Sampling frequency[/color]
[color=#00979c]const[/color] [color=#00979c]double[/color] [color=#000000]f_s[/color] [color=#434f54]=[/color] [color=#000000]100[/color][color=#000000];[/color] [color=#434f54]// Hz[/color]

[color=#434f54]// Sample timer[/color]
[b][color=#d35400]Timer[/color][/b][color=#434f54]<[/color][color=#d35400]micros[/color][color=#434f54]>[/color] [color=#000000]timer[/color] [color=#434f54]=[/color] [color=#000000]std[/color][color=#434f54]:[/color][color=#434f54]:[/color][color=#d35400]round[/color][color=#000000]([/color][color=#000000]1e6[/color] [color=#434f54]/[/color] [color=#000000]f_s[/color][color=#000000])[/color][color=#000000];[/color]
[color=#434f54]// Median filter of length 10, initialized with a value of 512.  [/color]
[b][color=#d35400]MedianFilter[/color][/b][color=#434f54]<[/color][color=#000000]10[/color][color=#434f54],[/color] [color=#00979c]uint16_t[/color][color=#434f54]>[/color] [color=#000000]medfilt[/color] [color=#434f54]=[/color] [color=#000000]{[/color][color=#000000]512[/color][color=#000000]}[/color][color=#000000];[/color]

[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [color=#5e6d03]if[/color] [color=#000000]([/color][color=#000000]timer[/color][color=#000000])[/color]
    [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]medfilt[/color][color=#000000]([/color][color=#d35400]analogRead[/color][color=#000000]([/color][color=#000000]A0[/color][color=#000000])[/color][color=#000000])[/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]

You can tweak the length of the median filter to match your needs. Right now, it gives out the median of 10 samples of 10 ms each, so it would work for peaks smaller than 50 ms. Don’t make the number of samples too high, storing and sorting 1000 numbers is not possible on an UNO, for example, mainly due to RAM constraints.

Pieter

After more thought, I have a small, very old air compressor. The pressure gauge is tapped off the pipe going to the tank. It goes crazy while the motor is running. But I have had 90 gallon tank compressors and 60 gallon tank compressors that have the gauge right on the tank. Neither of those showed the rapid fluctuation.

Tell us where you pressure sensor is located! Bet it's NOT on the tank.

Paul

a schematic is attached. There is a 12 volt compressor maintaining 105-150 PSI in the air storage tank due to a pressure switch. The fill and exhaust solenoids along with the pressure sensor reside in a valve block on the tank. The “S” boxes are the fill and exhaust solenoids, and the “P” is the pressure sensor, then from there they are plumbed in parallel to the air springs(bags) providing additional down force to the planting units(transfers frame weight to the planting unit). The air line is only 1/4" so flow is the biggest issue. When the ~125 psi from the tank is allowed into the bags there is a tremendous pressure differential(~100 psi). Likewise, when you exhaust the air from the bags, there is yet again another tremendous pressure differential (~50 psi or what ever is in the bags essentially). There isn’t much I can do to change how the that part operates. The pressure spikes displayed aren’t that big of an issue. But it seems kind of basic to me. IF I can fix it, great, if I can’t balance simplicity and performance, it’s not going to hurt anything.

Diag.jpg

Then lets take another approach to the problem. Who controls the solenoid valves? Can your Arduino determine when the valves are active? If so, only take pressure reading while the valves are not active.

Your air tank must have a drain at the bottom to remove water. Plumb that to a pipe and mount the pressure sensor at that point. Still have a valve to allow water to drain out.

Paul

At this point I am using a momentary rocker switch to control the solenoids. I thought about that sort of a logic, but at this point its too much programming, and I am not interested in Arduino controlled solenoids yet. Also, a side note, the air tank is a storage tank with a mechanical gauge and a pressure switch controls the tank pressure(on/off of the compressor). The pressure sensor I am reading is measuring the pressure after the valve block and what is in the air bags, so tank pressure is irrelevant.

The solenoids are 12v, so unless I got really creative I don’t know exactly how to put a signal into the board to tell it when not to read. The toggle switch is switching 12v so unless I brought it down to 5v and coded pin(whatever) LOW is switch centered and pin(whatever) HIGH is switch pressed one way or another. Just spit balling right now. If this (minor) issue is resolved and there are no issues my first planting season, I will be a very happy camper, well farmer!!!