newbie: I'm not sure what i need or how to approach my problem

Hi

Sorry i'm somewhat of a noob at coding so i'm not even sure how to name my issue but here's what i'm after:

i have a pressure sensor taking readings and if the pressure > 10 then a LED turns on else LED off.
However i don't want the LED to turn on straight away as soon as the pressure drops below the threshold. I only want the LED to turn on if the pressure has been below the threshold for more than 5 seconds.

so basically:

If pressure > threshold for more than 5 seconds LED on else LED off.

i've tried all sorts with delays, i've tried For loops (although i'm not sure how they work) hours of searching but if i don't know exactly what to look for the task is somewhat difficult.

can someone give me an answer and an idea of how to integrate it into my code.

here's my code:

int sensorPin = A0;
int sensorBase = 0;
int sensorBaseAverage = 0;
int ledPinGreen = 12; // pin that the LED is attached to
int ledPinWhite = 9;
int ledPinRed = 7;
int count = 0;

void setup(){
Serial.begin(9600);
sensorBaseAverage = 0;
for(int j=0; j<20; j++){ // Startup sequence to create a bassline result
sensorBase = analogRead(sensorPin);// * (5.0 / 1023.0);
sensorBaseAverage = sensorBaseAverage+sensorBase;
delay(100);
}
sensorBaseAverage = (sensorBaseAverage / 20) * (5.0 / 1024.0);
}

void loop(){
float pressure = readPressure(A0);
float millibars = pressure/100;

if(pressure < 0){
Serial.println(pressure);
//Serial.print(" Pascals ");
//Serial.println(pressure);
delay(100);
}

if( -10 < pressure ) {
digitalWrite(ledPinGreen, HIGH);
}
else {digitalWrite(ledPinGreen,LOW);
}

if((-10.1 > pressure) && (pressure > -25)){
digitalWrite(ledPinWhite, HIGH);
}
else {digitalWrite(ledPinWhite, LOW);
}

for (if count <= 2000){
digitalWrite(ledPinWhite,LOW);
int count = int count + 1;
delay(1);
}
else {
digitalWrite(ledPinWhite,HIGH);
delay(1);
}

if( pressure > -25.1) {
digitalWrite(ledPinRed, LOW);
}
else {digitalWrite(ledPinRed,HIGH);
}

}

float readPressure(int pin){
int pressureValue = analogRead(sensorPin);
float pressure= (((pressureValue / 1023.0)-0.92)/0.007652);
return pressure;

}

Many thanks!

(and please try to be nice people are brutal to newcomers on these forums)

Please use [ code ] tags next time.

This line:sensorBaseAverage = (sensorBaseAverage / 20) * (5.0 / 1024.0);
will store the values 0, 1, 2, 3, or 4. No other values are possible because sensorBaseAverage is an integer. Is this what you want?

Hi thanks for the reply.

yeah that part of the code is just converting what is read by the sensor to a different pressure reading ( pascals). This for me is easier to work with and make reference to.

The part of the code the problem is with is:

[
if((-10.1 > pressure) && (pressure > -25)){
digitalWrite(ledPinWhite, HIGH);
}
else {digitalWrite(ledPinWhite, LOW);
}
]

My attempted but failed solution for 'If pressure > threshold for more than 5 seconds LED on else LED off.' is:

[
for (if count <= 2000){
digitalWrite(ledPinWhite,LOW);
int count = int count + 1;
delay(1);
}
else {
digitalWrite(ledPinWhite,HIGH);
delay(1);
}
]

Where have you ever seen a for loop written like that?

You need to record the time when the pressure goes below the threshold for the first time and use that time to compare to the current time to see if it has been 5 seconds. The millis function will give you a timestamp of the number of milliseconds since the last time the board was reset.

That was an attempt by by friend. I'm not particularly sure how they work so..

ok thanks. I'll do some exploration/ research around the millis function.

Hi conorl09,

See my answer in this post and modify the code to your needs:
http://forum.arduino.cc/index.php?topic=320389.0

If you want to check if something remains in a state for X millisecs the trick is to reset the timer every time it is NOT in that state. Something like this (if you want to check that it is >= 10 for a period)

if (pressure < 10) {
   startMillis = millis();
}
if (millis() - startMillis >= waitPeriod) {
   // do your stuff
}

...R

Thanks guys. i think im getting somewhere with this! cheers for the help! will post if i need anymore.

Hi,

I'm having trouble with one of my LED's not turning off.

so this part of the code:

if( pressure < 7 ) {
  StartMillis = millis ();
 digitalWrite(ledPin9, HIGH);
  } 
else
  if (millis() - StartMillis >= 5000) {
{digitalWrite(ledPin9,LOW); 
}


 


if((pressure > 7) && (pressure < 15)){
  StartMillis = millis ();
}
if (millis() - StartMillis >= 5000) {
  digitalWrite(ledPin12, HIGH); 
}
else  
if (millis() - StartMillis >= 5000) {
{digitalWrite(ledPin12, LOW); 
  }

produces the results:

  • if the pressure is below below 7 then ledPin9 is ON.
  • if the pressure goes between 7 and 15 for more than 5 seconds ledPin9 goes OFF and ledPin12 goes ON.
  • if the pressure drops back below 7 then ledPin9 Goes back ON instantly.
    HOWEVER
    ledPin12 does not go back to OFF.

Any ideas why ledPin12 will not turn back off when the pressure goes outside of its threshold? i'm stumped and have spend hours and hours trying to figure it out.

full code:

int sensorPin = A0;
int sensorBase = 0;
int sensorBaseAverage = 0;
int ledPin9 = 9;       // pin that the LED is attached to
int ledPin12 = 12; 
int ledPin4 = 4; 
unsigned long  StartMillis;

void setup(){
    pinMode(ledPin9, OUTPUT);
    Serial.begin(9600);
    sensorBaseAverage = 0;
    for(int j=0; j<20; j++){ // Startup sequence to create a bassline result
      sensorBase = analogRead(sensorPin);// * (5.0 / 1023.0);
      sensorBaseAverage = sensorBaseAverage+sensorBase;
      delay(100);    
    }
    sensorBaseAverage = (sensorBaseAverage / 20) * (5.0 / 1024.0);
}


 


void loop(){
  float pressure = ((readPressure(A0))*-1);
  float millibars = pressure/100; 
    
  
     Serial.println(pressure);
     //Serial.print(" Pascals ");
     //Serial.println(pressure);
     delay(100);
  
  

 
 
  
if( pressure < 7 ) {
  StartMillis = millis ();
 digitalWrite(ledPin9, HIGH);
  } 
else
  if (millis() - StartMillis >= 5000) {
{digitalWrite(ledPin9,LOW); 
}


 


if((pressure > 7) && (pressure < 15)){
  StartMillis = millis ();
}
if (millis() - StartMillis >= 5000) {
  digitalWrite(ledPin12, HIGH); 
}
else  
if (millis() - StartMillis >= 5000) {
{digitalWrite(ledPin12, LOW); 
  }


}}}



float readPressure(int pin){
  int pressureValue = analogRead(sensorPin);
  float pressure= (((pressureValue / 1023.0)-0.92)/0.007652);
  return pressure;

}

You don't have any code in the part that gets run if pressure is below 7 that says to turn that pin off.

is it not this part:

else  
if (millis() - StartMillis >= 5000) {
{digitalWrite(ledPin12, LOW); 
  }

what would you suggest?

maybe adding:

if((pressure < 7) && (pressure > 40)){
  StartMillis = millis ();
}
if (millis() - StartMillis >= 5000) {
  digitalWrite(ledPin12, LOW);

thanks

if (millis() - StartMillis >= 5000) {
  digitalWrite(ledPin12, HIGH); 
}
else  
if (millis() - StartMillis >= 5000) {
{digitalWrite(ledPin12, LOW); 
  }

Sorry, I missed this. This is a big problem. The else only happens when the thing in the if isn't true. But here the first thing you do in the else block is check the same thing that the if was checking. So if it's been less than 5000 milliseconds, it goes to the else, where if it has been less than 5000 milliseconds you do nothing.

If you haven't done it already, drawing a simple state diagram can often help. It often makes a whole lot easier to make the code from that, especially when things get complex.

Another thing that can often help is creating so-called helper methods, breaking up a big chunk of code in to smaller more managable parts.

To me it seems like you might have some unwanted { and } in your main loop and basically pin9 will always go low if millis() - startmillis is greateror equal to 5000. With tabs and alignment your main loop looks like this:

void loop(){
	float pressure = ((readPressure(A0))*-1);
	float millibars = pressure/100; 
    
  
    Serial.println(pressure);
    //Serial.print(" Pascals ");
    //Serial.println(pressure);
    delay(100);

	if( pressure < 7 ) {
		StartMillis = millis ();
		digitalWrite(ledPin9, HIGH);
	} 

	else if (millis() - StartMillis >= 5000) {
		{digitalWrite(ledPin9,LOW);}

		if((pressure > 7) && (pressure < 15)){
			StartMillis = millis ();
		}

		if (millis() - StartMillis >= 5000) {
			digitalWrite(ledPin12, HIGH); 
		}
		
		else if (millis() - StartMillis >= 5000) {
			{digitalWrite(ledPin12, LOW);}
		}
	}

}

Also, as Delta_G says, that "else if" is only fired if and only if the "if" statement is not true, so having for an example:

if (millis() - StartMillis >= 5000) {
    digitalWrite(ledPin12, HIGH); 
}
		
else if (millis() - StartMillis >= 5000) {
    digitalWrite(ledPin12, LOW);
}

Will never fire the "else if", as the condition is the same. I think you have to review your conditions :slight_smile:

Did you set the pin mode for pin 12? I don't see a

pinMode(ledPin12, OUTPUT);

any where.
According to the reference for digitalWrite()
NOTE: If you do not set the pinMode() to OUTPUT, and connect an LED to a pin, when calling digitalWrite(HIGH), the LED may appear dim. Without explicitly setting pinMode(), digitalWrite() will have enabled the internal pull-up resistor, which acts like a large current-limiting resistor.

Though the ways suggested above are more "proper" and probably better practices, I suppose you could just make a function called void readPressure() or something and in it have:

delay(5000);
int  pressure = analogRead(pressureSensorPin);

or whatever you want to call the variables. If you then call the function in the void loop, it would effectively be saying "wait 5 seconds, if someone is still pressing, variable pressure is the value of analogRead of pressureSensorPin".

Not sure how ell this would work in actuality, but is worth a try.

ma7730:
it would effectively be saying "wait 5 seconds, if someone is still pressing,

Sorry, but it would NOT do that. All it would do is start the delay() when something is pressed. It would not check whether anything is still happening during, or at the end of the delay() period. The Arduino just wastes time during a delay() which is why millis() is used to manage timing so that other things can be tested during the interval.

...R

@Robin2 -
No need to apologize.

It maybe wrong, but I'm not sure. My post says that you could put the code I posted below in a function, and then call the function, in the main loop. If you put it at the beginning, shouldn't it wait 5 seconds before checking the pressure?

ma7730:
If you put it at the beginning, shouldn't it wait 5 seconds before checking the pressure?

Yes, that is true. But it is not the same thing as ensuring the pressure is at a particular value throughout the 5 seconds.

For the most part the delay() function has no role in a "serious" program. It can be useful in a "quick and dirty" test program.

...R