Go Down

Topic: Arduino (Counter as a Dead man Switch) (Read 983 times) previous topic - next topic

hddforensic

Oct 08, 2017, 07:00 pm Last Edit: Oct 08, 2017, 07:06 pm by hddforensic
I built a Scuba compressor and it is controlled by an Arduino (UNO)

On that UNO I have:

4 buttons - Start and stop (Compressor, Oxygen solenoid, purging timer circuit, Oxygen calibration)
4 Relays  - Output for 3 buttons and the last one for an alarm
4 sensors - High Pressure (PSI while filling the scuba tanks)
             - Oxygen (O2) (amount of oxygen NITROX)
             - Temperature (Temperature of the compressor)
             - Light sensor (Detect alarm of an independent Carbon monoxide detector)
             - Flow sensor (Detect when air is blowing out during the purging)


I have different conditions (if)

Stop compressor when reach 3,150 PSI
Stop Oxygen and Compressor if higher than 40% Oxygen
etc..

I can see the sensors value on two LCD's

I also installed an Arduino NANO that takes the value of the sensors from the UNO (TX pin)
and this NANO is driving a RF transmitter (HRF24L01) and sends the signal to a small box
with an OLED display so I can monitor my compressor while I'm away (few hundreds feet) is enough.

All this is working well

I'm new with coding and Arduino.  I began playing with that 3 months ago and I'm learning
with examples.  I find a code near of what I need, I integrated in my existing code and I modify it to fit my needs.

But now I need more and I need help.


The compressor need to be purge of the humidity every 6 minutes.  I installed a small circuit timer
that open a close the purge valve every 6 minutes.  The valve is open and close by a DC motor that I
modify with a sproket created with my 3D printer.

Every six minute the circuit timer is opening and closing the valve to purge and during a 2 or 3 seconds, a high pressure air is blowing in a small hose.  at the end of that hose I install a water flow sensor working with a hall effect.  So every six minutes the air blow and the flow sensor reach a value.

I add a small code that say "if flowRate" is higher that 20 open a LED and it's working.  that code was only to test the flow sensor and it is ok.  But now I need to go further,


DMS

I need to add a "dead man switch"  this DMS will monitor the purging that append every 6 minutes.


I want a counter that I can see on my LCD, that count from 0 to 360 and if it reach the value of 360, I want "stateRELAY1" to go LOW (relay that control the compressor).  Every time the air blow in my flow sensor, it should reset the counter to 0 and start counting again.  Results, that flow sensor will act as a DMS.  If the system is not purge between 0 and 360 seconds, I want the compressor to stop.


I also need to:

Monitoring the increase of the PSI

The high pressure sensor is monitoring the PSI.  I already put a condition that when PSI reach 3,150 PSI, the compressor stop. But I also want to monitor the increasing PSI and if the PSI in not increasing for X PSI per second or minutes it will mean that I have an air leak and I want the compressor to stop.


Below in clear text, see the part of the code about the FlowSensor and the counter.


See attache files for the full code.



Code: [Select]


//*********************************************************FlowSensor  
                                                           //this section is taking care of the FlowSensor
                                                           //I put an LED to see if the sensor was working
                                                          
void FlowSensor(){
  
  pulseCount++;
  
  if((millis() - oldTime) > 1000)    // Only process counters once per second
  {
  detachInterrupt(sensorInterrupt);    
  flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount);
  oldTime = millis();
  Serial.print("Flow rate: ");
  Serial.println(int(flowRate));
  attachInterrupt(sensorInterrupt, FlowSensor, FALLING);
  }
  
  if (flowRate > 20){
  digitalWrite(LED1, HIGH);
  }
  
  else
  {  
  digitalWrite(LED1, LOW);
  }
}


//**************************************************LcdCounter for DMS   (testing phase)

void LcdCounter(){

 // this section is my first few attenps to create the counter for the DMS
 // My first problem is that when it start counting, it stop as soon as the flowrate value is below 20.
 // It's normal for the flowRate to reach higher than 20 only for a few seconds since the air blow from the
 // purge is very short.
 
    if (flowRate > 20)
    {
    a ++;
    lcd_2.setCursor(11, 1);
    lcd_2.print(a);
    }  


//  Below I put 30 as a value just to see is it's working.
//  But I didn't find a way to reset the counter so when the counter reach 30,
//  the two relays stop and "Purge" is printed on the LCD but I don't
//  have any way to make it reset unless reseting the Arduino.

//    if (a > 30){  
//    stateRELAY1 = LOW;
//    stateRELAY2 = LOW;
//    lcd_2.setCursor(11, 1);
//    lcd_2.print(F("Purge"));
//    }

}



//*********************************************************LOOP

void loop(){

  Button();
  analysing_O2(0,calibrationv,"O2 ");
  Pression();
  Temperature();
  LightSensor();

  FlowSensor();
  LcdCounter();
  
  pulseCount = 0;  // this line should probably removed one day but for now I need it otherwise
                   // the counter go crazy. like starting for no reason and doesn't stop counting.
                   // probably a bug in the FlowRate section


PaulS

Quote
I add a small code that say "if flowRate" is higher that 20 open a LED and it's working.
How do you open an LED? Are you able to close it again?

Quote
I need to add a "dead man switch"  this DMS will monitor the purging that append every 6 minutes.
Switches don't monitor anything. They get pressed. They get released. What, EXACTLY, is the relationship between the switch and the purging function?

Quote
But I also want to monitor the increasing PSI and if the PSI in not increasing for X PSI per second
You mean "by X PSI per second"?

The art of getting good answers lies in asking good questions.

hddforensic

Hi PaulS,

I got some help last night and the DMS is working now.


Code: [Select]

void LcdCounter(){


    CounterMillis = millis();
    if (CounterMillis - CounterMillis1 >= interval2) {

    if (a < 40 && purge == 0 && stateRELAY1 == HIGH) // value of 40 for testing purpose.             
                                                                                 // The final goal will be 400 counts
   {                                                                         
    a ++;
    lcd_2.setCursor(11, 1);
    lcd_2.print(a);

    Serial.println(CounterMillis);  // for debug millis
    Serial.println(CounterMillis1); // for debug millis
    }
   
    else
    {
    if (purge == 1){
    a = 0;
    purge = 0;
    lcd_2.setCursor(11, 1);
    lcd_2.print(F("     "));
    }

    if (a >= 40) // value of 40 for testing purpose.
                      // The final goal will be 400 counts
   
   { 
    stateRELAY1 = LOW;  //shutdown compressor
    stateRELAY2 = LOW;  //shutdown oxygen solenoid
    stateRELAY3 = LOW;  //shutdown relay 3
    lcd_2.setCursor(11, 1);
    lcd_2.print(F("Purge"));
    }
    }
    CounterMillis1 = CounterMillis;
    }
}
 



With this code, every time the purge occur, the air blow in a flowSensor and it reset the counter
to zero and it restart.  If there is no blow during a count of 400, it shutdown 3 relays.

The only problem is that I found that millis is not equal to 1 second probably because my code
takes more than 1000ms to execute.

I add two lines for debug (serial print CounterMillis and CounterMills1) and if I substract
the two values I obtains 1383 instead of 1000. 

If I deactivate all loops in my code and just keep the counter, it work  and then millis do equal to 1000.

So for now I put an interval and the best I can do is 1000 millis = 9.25 seconds more or less since my finger is pressing the stopwatch on my phone to compare.

I will read a little on RTC to find a way to get a real counter in my code but a count of 400 is ok for now.



Monitoring the increase of PSI


PSI is the variable that stored the value of the air pressure.
I need to make sure that this value is increasing.  If I can
get a good example on how to do it, I will then adjust the
TIME vs the PSI for 10 PSI each 20 seconds more or less.




PaulS

Quote
PSI is the variable that stored the value of the air pressure.
I need to make sure that this value is increasing.  If I can
get a good example on how to do it, I will then adjust the
TIME vs the PSI for 10 PSI each 20 seconds more or less.
You need two variables - one for the current PSI and one for the previous PSI.

Each time you read from the sensor, you get the current PSI value. It isn't rocket science to compare the current value to the previous value. It isn't rocket science to determine whether the change is significant enough to continue, or is small enough to warrant shutting off stuff.

At the end of loop(), the current value becomes the previous value.
The art of getting good answers lies in asking good questions.

hddforensic


Hi,

It may not be rocket science for an astronaut but for a newbie like me it is.

I see the logic in that and it's the easy part but like I said, I'm searching for a good example
on how to do it.  "Full" example would the correct word.

That's why I post my question


   

PaulS

Code: [Select]
bool pressureIsStillIncreasing()
{
   bool goingUp = true;
   static int currPress;
   static int prevPress = 0;

   currPress = readCurrentPressure();
   if(currPress <= prevPress)
      goingUp = false;

   prevPress = currPress;

   return goingUp;
}


Write the readCurrentPressure() function to get the pressure from the sensor. Call this function once every second, half-second, week, whatever. If it returns true, leave the compressor running. Otherwise, turn it off, run in circles, scream and shout.
The art of getting good answers lies in asking good questions.

hddforensic

Hi PaulS

Thanks for your answer,

Sorry for the delay but I was out on the road for a job so I didn't had the
chance to spent time in front of my computer.


I did some tests this morning and I'm not sure how to fully implement your suggestion.

I wante to show you what I did and please, try not to laugh to much because like I said, I'm a newbie.



This is at the beginning of my code for the initialization.

Code: [Select]

  bool goingUp = true;
  static int currPress;
  static int prevPress = 0;




This is the fonction section


Code: [Select]


bool pressureIncreasing()
 
   {
   currPress = PSI;
   if(currPress <= prevPress)
   goingUp = false;
   

   Serial.println (currPress); // I add the 3 next lines to see if the value were ok
   Serial.println("    ");
   Serial.println (prevPress);


   prevPress = currPress; 
   return goingUp;

   if (goingUp = false)
   {
   stateRELAY1 = LOW;
   }
}
 



And in my Loop at the end I added the section's name with all the other I have.

I try to put only the name of each fonction in the loop so I can take them out
for troubleshooting when I need.

Code: [Select]



void loop(){

pressureIncreasing();

}



For now it's not working, I can see the values in the Serial.print with the 3 lines I added
but that's it.

I have no error message so far but no results also :-)

What can you tell me from here  ?


Thanks


My goal will be to tell the code:

If the Pressure (PSI) did not increase by 25PSI in the last 3 minutes, close the compressor (stateRELAY1).

hddforensic

Hi,

I finally found a way to do it

With help and reading.  Thanks to this Forum.

Code: [Select]

void PsiWatchDog(){   

   if(prevPress == 0)
   {
   prevPress = PSI;
   }

   DateTime now = rtc.now(); 
   OneSecond1 = now.second();
   IntervalRTC1 = OneSecond1 - PreviousSec1;

   if (IntervalRTC1 < 0){
   IntervalRTC1 += 60;
   }
   if (IntervalRTC1 >180){ //Wait 3 minutes befoere check PSI increase
   
   currPress = PSI;
   
   if (currPress - prevPress > 30)
   {
   prevPress = 0;
   lcd_2.setCursor (9,0);
   lcd_2.print ("       ");
   }
   
   else if (stateRELAY1 == HIGH)
   {
   stateRELAY1 = LOW;
   stateRELAY2 = LOW;
   stateRELAY3 = LOW;

   lcd_2.setCursor (12,1);
   lcd_2.print ("Leaks");
   prevPress = PSI;
   }

   PreviousSec1 = OneSecond1;
   }
}

Go Up