help with timers- if value outside a range for set amount of time do > something

Hi all this is my first post on here sorry if this is the wrong place for this.

I'm writing my own code for an autolevel ecu that will turn on relays to adjust airbag suspension.

So far i have managed to get all the names down and set up an automatic calibration code that will record min and max sensor values on each corner of the vehicle through the full range of suspension travel. This then is written to the eeprom for future use so when car is turned off it will still remember these values etc.

Heres a few variables i have named.

a front right sensor named (frs) a target height for that front right sensor (frt) 3 conditions for the front right sensor - frhigh - frlow - frstable

I have been able to make it constantly adjust the height of the car to reach the target value and set frstable as true (not turning on any relays to bags)

Here is where my knowledge ends and need some help.

If frs is not within the boundary frt+frt*0.1 or frt-frt*0.1 then i want a timer to start from here i want it to check if the sensor frt remains outside that boundary for 20 seconds if at the end of 20 seconds it is still outside the boundary i want it to then adjust height until the frstable condition is true then im going to guess reset timer and continue checking

This is so if you go over a bump and the height changes the car doesn't instantly try change height for that 1 little bump it needs to remain outside the allowed range for 20 seconds before it makes changes.

I can attach my code if needed just after some help on where to start.

I'm not sure how i go about it but id also preferably like it to do the following assuming the car is lower than target range

check if a side is not within the range note if it is high or low (in this case too low) count 20 seconds if its still outside the range (still too low) raise the car until the sensor value is within the range then reset timer and continue checking

needs to be able to do this for all 4 corners and independently so if 1 corner is down then 10 seconds later the other corner is down i want it to act on the first corner after 10 seconds and the second corner after a further 10 seconds.

Thanks for any help or guidance. I can post the code i have now if required. Cheers

I think you just need a variable to hold the last time that the reading was seen to be in the correct range. Each time a reading is checked, if it is in the correct range, the variable is updated to the current time. If not in the correct range, check the variable against the current time to see how long ago the last correct reading was. If it is longer than 10? 20? seconds, switch the relay on, otherwise off.

The variable needs to be an unsigned long type. The current time is given by millis().

To avoid duplicating all your code 4 times, I would recommend using arrays of length 4. An array for the pin numbers of all the sensor inputs, an array for the output pins connected to the relays, an array for all the times captured and so on. Then you can simply put your code inside a for loop which will repeat everything 4 times over for the 4 corners. Naming your variables “frxxx”, “flxxx” and so on will inevitably result in lots of duplicated code.

Yes, absolutely, share your code. But please read the forum guidelines so you know how to post code correctly like

this.

I'd suggest that rather than frs, type out the whole thing: FrontRightSensor. It may save you from mistaking one variable for another - frs and frt are rather too close for comfort.

Thankyou for the replies. I may end up writing frontrightsensor only reason i did frs is to save me when typing it all out haha but yes that will help with debugging later and making things clearer.

Here is what i have so far

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////        NAMING
#include <EEPROM.h>

// Front right condiitions
boolean frlow = false;
boolean frhigh = false;
boolean frstable = false;

// Front Left condiitions
boolean fllow = false;
boolean flhigh = false;
boolean flstable = false;

// Rear right condiitions
boolean brlow = false;
boolean brhigh = false;
boolean brstable = false;

// Rear Left condiitions
boolean bllow = false;
boolean blhigh = false;
boolean blstable = false;

// Relay names
const int fru = 2;
const int frd = 3;
const int flu = 4;
const int fld = 5;
const int cal = 6;

//Calibration naming
int cals = digitalRead(cal);

//Sensor Names
int frs = analogRead(A0)/4;
int fls = analogRead(A1)/4;
int brs = analogRead(A2)/4;
int bls = analogRead(A3)/4;

//Eeprom Variables
int frsmin = EEPROM.read(0);
int flsmin = EEPROM.read(1);
int brsmin = EEPROM.read(2);
int blsmin = EEPROM.read(3);
int frsmax = EEPROM.read(4);
int flsmax = EEPROM.read(5);
int brsmax = EEPROM.read(6);
int blsmax = EEPROM.read(7);
int fr1 = EEPROM.read(11);
int fr2 = EEPROM.read(12);
int fr3 = EEPROM.read(13);
int fl1 = EEPROM.read(21);
int fl2 = EEPROM.read(22);
int fl3 = EEPROM.read(23);
int br1 = EEPROM.read(31);
int br2 = EEPROM.read(32);
int br3 = EEPROM.read(33);
int bl1 = EEPROM.read(41);
int bl2 = EEPROM.read(42);
int bl3 = EEPROM.read(43);

// Autolevel conditions
boolean handbrake = false;
boolean freeplay = false;
boolean user1 = false;
boolean user2 = false;
boolean user3 = false;
boolean ride = false;
boolean airout = false;
boolean lift = false;

// Target Heights
int frt = (frsmin + frsmax)/2;
int flt = (flsmin + flsmax)/2;
int brt = (brsmin + brsmax)/2;
int blt = (blsmin + blsmax)/2;

// Accuracy
int accuracy = 0.1;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////          Setup
void setup() {
Serial.begin(9600);
Serial.println ("Initializing"); // Starting Code
pinMode(LED_BUILTIN, OUTPUT);
pinMode(fru, OUTPUT);
pinMode(frd, OUTPUT);
pinMode(flu, OUTPUT);
pinMode(fld, OUTPUT); 
pinMode(cal, INPUT_PULLUP);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////          Calibration

  if(cals==0)
  {
    digitalWrite(LED_BUILTIN, 1);
    delay(100);
    digitalWrite(LED_BUILTIN, 0);
    delay(100);
    digitalWrite(LED_BUILTIN, 1);
    delay(100);
    digitalWrite(LED_BUILTIN, 0);
    delay(100);
    digitalWrite(LED_BUILTIN, 1);
    delay(100);
    digitalWrite(LED_BUILTIN, 0);
    delay(100);
    digitalWrite(LED_BUILTIN, 1);
    delay(2000);
    digitalWrite(LED_BUILTIN, 0);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////          Min Sensor Values
    Serial.println("Calibrating- Min Sensor Value");
    digitalWrite (fru, 0);
    digitalWrite (frd, 1);
    digitalWrite (flu, 0);
    digitalWrite (fld, 1);
    delay(10000);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////       Min Sensor Values Setting
    Serial.println("Getting Values");    
    frsmin = analogRead(A0)/4;
    flsmin = analogRead(A1)/4;
    brsmin = analogRead(A2)/4;
    blsmin = analogRead(A3)/4;
    delay(1000);
    Serial.println("Writing to eeprom");
    EEPROM.write(0,frsmin);
    EEPROM.write(1,flsmin);
    EEPROM.write(2,brsmin);
    EEPROM.write(3,blsmin);
    Serial.print("FRmin: "); Serial.print(frsmin); Serial.print(" FLmin: "); Serial.print(flsmin); Serial.print(" BRmin: "); Serial.print(brsmin); Serial.print(" BLmin: "); Serial.println(blsmin);

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////          Max Sensor Values
    Serial.println("Calibrating- Max Sensor Value");
    digitalWrite (fru, 1);
    digitalWrite (frd, 0);
    digitalWrite (flu, 1);
    digitalWrite (fld, 0);
    delay(10000);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////       Min Sensor Values Setting
    Serial.println("Getting Values");    
    frsmax = analogRead(A0)/4;
    flsmax = analogRead(A1)/4;
    brsmax = analogRead(A2)/4;
    blsmax = analogRead(A3)/4;
    delay(1000);
    Serial.println("Writing to eeprom");
    EEPROM.write(4,frsmax);
    EEPROM.write(5,flsmax);
    EEPROM.write(6,brsmax);
    EEPROM.write(7,blsmax);
    Serial.print("FRmax: "); Serial.print(frsmax); Serial.print(" FLmax: "); Serial.print(flsmax); Serial.print(" BRmax: "); Serial.print(brsmax); Serial.print(" BLmax: "); Serial.println(blsmax);
  } // if statement end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////      Getting values from eeprom
  if(cals==1){
    Serial.println("Values Received from eeprom");
    Serial.print("FRmin: "); Serial.print(frsmin); Serial.print(" FLmin: "); Serial.print(flsmin); Serial.print(" BRmin: "); Serial.print(brsmin); Serial.print(" BLmin: "); Serial.println(blsmin);
    Serial.print("FRmax: "); Serial.print(frsmax); Serial.print(" FLmax: "); Serial.print(flsmax); Serial.print(" BRmax: "); Serial.print(brsmax); Serial.print(" BLmax: "); Serial.println(blsmax);
    delay(5000);
  } // if calibration statement end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////          End calibration

} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////       Setup end

thats setup

this is the loop:

void loop() {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////      Handbrake naming target
     if (handbrake==true){
//////////////////////////////////////////////// User 1 target heights          
          if (user1==true){
            frt=fr1;
            flt=fl1;
            brt=br1;
            blt=bl1;
          }
          
//////////////////////////////////////////////// User 2 target heights
          if (user2==true){
            frt=fr2;
            flt=fl2;
            brt=br2;
            blt=bl2;
          }
          
//////////////////////////////////////////////// User 3 target heights
          if (user3==true){
            frt=fr3;
            flt=fl3;
            brt=br3;
            blt=bl3;
          }
          
//////////////////////////////////////////////// airout target heights
          if (airout==true){
            frt=frsmin;
            flt=flsmin;
            brt=brsmin;
            blt=blsmin;  
          }  
          
//////////////////////////////////////////////// lift target heights          
          if (lift==true){
            frt=frsmax;
            flt=flsmax;
            brt=brsmax;
            blt=blsmax;       
          }
//////////////////////////////////////////////// Ride target heights
          if (ride==true){
            frt = (frsmin + frsmax)/2;
            flt = (flsmin + flsmax)/2;
            brt = (brsmin + brsmax)/2;
            blt = (blsmin + blsmax)/2;             
          }

    }// end handbrake on
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////    Handbrake off naming target height
    if (handbrake==false){
            frt = (frsmin + frsmax)/2;
            flt = (flsmin + flsmax)/2;
            brt = (brsmin + brsmax)/2;
            blt = (blsmin + blsmax)/2;      
  }// end handbrake off
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Autolevel

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////      Sensor conditions

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Front right low
  if (frs<(frt-frt*accuracy)){
    frlow=true;
    frhigh=false;
    frstable=false;
  }// end front right low

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Front right High
  if (frs>(frt+frt*accuracy)){
    frlow=false;
    frhigh=true;
    frstable=false;
  }// end front right high

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Front right stable
  if (frs<(frt-frt*accuracy) && frs>(frt+frt*accuracy) ){
    frlow=false;
    frhigh=false;
    frstable=true;
  }// end front right stable
  
} // Loop Staatement end

As I feared, you already have heaps of duplicated code. I recommend you fix that before things get even more complex.

Ahh I'll have to look into arrays then I haven't ever dealt with them before sorry only learning and know basics with arduino.

So I'll investigate arrays to save coding repetition and for the timer I should start a timer on setup and then when a sensor goes outside the ranges record the time at which that happened?

Do you have any links or places with a similar example?

darcy_d:
for the timer I should start a timer on setup and then when a sensor goes outside the ranges record the time at which that happened?

No, please go back and read my first reply again.

You only need one timer, its called millis() and it automatically starts at zero when the Arduino starts/resets. You can’t and don’t need to reset it to zero at any other time.

When you see that a sensor is in the correct range, you record the time by reading millis() and saving that time value in a variable. If the sensor is not in the correct range, you look at the current time (the current value given by millis()) and compare this to the last known time when the sensor was in the correct range (the value stored in your variable). By subtracting one from the other, you can see how much time has passed.If that is more than 10 or 20 seconds, you activate a relay.

Is this making any more sense yet?

Ahh yes got you now sorry haven't dealt with this before haha thankyou for your help I'll see how I go!

Much appreciated

i’ve had a bit of a sus with arrays but im confused how that could help me. Yes it could help with the initial naming and reducing the pin outs / sensors etc to a few lines rather than a line for each name but in the later code it will be more difficult to write wouldnt it?

For example this code to see if the front right is too low:

  if (frs<(frt-frt*accuracy)){
    frlow=true;
    frhigh=false;
    frstable=false;
  }// end front right low

If i had all my sensor data and outputs in an array then rather than calling for a simple name frs etc id be calling sensorpins [3] which would end up being more complicated for me to write as id have to constantly try remember what each indexed number meant in the array?

Or did you mean mainly for the relay outputs?

As in make an array for all inflate relays so then you could simply write each element in the array high if wanting to inflate all instead of having to individually write each pin high?

Sorry just confused which part i should tidy up because to me its going to end up more complicated later without having individually named variables

darcy_d:
… but in the later code it will be more difficult to write wouldnt it?

No, I don’t think so. But I have a question which I’ll ask later.

darcy_d:
For example this code to see if the front right is too low:

  if (frs<(frt-frt*accuracy)){

frlow=true;
    frhigh=false;
    frstable=false;
  }// end front right low

This is a perfect case in point. Writing it like that, you will have to repeat that code, and many more sections, 4 times over, for: fr, fl, br & bl. But if you use arrays, you can write it once for all 4 wheels:

  for (byte wheel = 0; wheel < 4; wheel++) {
    if (sensorLevel[wheel] < (target[wheel] * (1-accuracy)){
      sensorLow[wheel] = true;
      sensorHigh[wheel] = false;
      sensorStable[wheel] = false;
    }
  }

darcy_d:
… id have to constantly try remember what each indexed number meant in the array?

No, because if all 4 wheels are identical and independent, you would not need to remember which was which, because all 4 are treated identically. If you need to write some debugging info to serial monitor, you could do something like this:

char* wheelName[4] = {"Front Right", "Front Left", "Rear Right", "Rear Left" };
....
....
for (byte wheel = 0; wheel < 4; wheel++) {
  Serial.print(wheelName[wheel]);
  Serial.print(" level is: ");
  Serial.println(sensorLevel[wheel]);
}

darcy_d:
an array for all inflate relays

This brings me to the question I wanted to ask:

// Relay names
const int fru = 2;
const int frd = 3;
const int flu = 4;
const int fld = 5;

Where are the pins for the back wheel relays?

PaulRB:

  for (byte wheel = 0, wheel < 4, wheel++) {

if (sensorLevel[wheel] < (target[wheel] * (1-accuracy)){
     sensorLow[wheel] = true;
     sensorHigh[wheel] = false;
     sensorStable[wheel] = false;
   }
 }
}

Sorry not familiar with this code 100% yet but that would essentially set a variable wheels with an initial value 0 which would be element 1 in the array correct?

So then it would go through check if element 1 is lower than the target range and if true set sensorlow[0] to true then continue to loop this for the indexed array 0,1,2 and 3 and then once it increases to 4 jumps out of the for loop so later you’d have a reset for wheels = 0 at the end of the void loop to start again?

So adapting this method i would have an array for

Sensorlevel which would be all 4 sensors values
Relay pins ( output pins)
sensor low
sensor high
sensor stable

Or would sensor low high and stable all be just named variables such as sensorlow[1] with a false or true condition?

Sorry for the questions just trying to understand what that code you wrote would be doing and what arrays i’d have to setup to achieve it in a simpler manor

PaulRB:
This brings me to the question I wanted to ask:

// Relay names

const int fru = 2;
const int frd = 3;
const int flu = 4;
const int fld = 5;



Where are the pins for the back wheel relays?

I had them in there but deleted it as i only had an arduino uno and couldnt have all my sensors out so that was just for me to be able to get the 2 sensors working and doing something then i was going to copy it for the rears.

i think i understand it now i wrote a quick example to see if what i was thinking is correct and this works well just to simply read each sensor value in only a few lines of code and then print them out.

void setup() {


Serial.begin(9600);
}

// All array values {FL,FR,BL,BR} 
int SensorPins[4] = {};


void loop() {
  SensorPins[0] = analogRead(A0);
  SensorPins[1] = analogRead(A1);
  SensorPins[2] = analogRead(A2);
  SensorPins[3] = analogRead(A3);

  for(int Wheels = 0; Wheels < 4; Wheels++) {
  
   Serial.println(SensorPins[Wheels]);
   delay(10);
  }
}

So i will go through and write my code with this should be neater ill see how i go and if i have any issues ill post here cheers

The first element of an array is always index 0 in C/C++ (unlike some other languages like Basic where the first index is 1).

You seem to have got the general idea.

Hopefully you will work out which variables need to be arrays and which don't as you go through the code "refactoring" it. If in doubt, post what you have at that point and ask for advice. (On this thread.)

void setup() {

  Serial.begin(9600);
}

// All array values {FL,FR,BL,BR} 
int sensorReading[4];
const int sensorPin[4] = { A0, A1, A2, A3 };


void loop() {

  for(int wheel = 0; wheel < 4; wheel++) {

   sensorReading[wheel] = analogRead(sensorPin[wheel]);
  
   Serial.println(sensorReading[wheel]);
   delay(10);
  }
}

PaulRB:

void setup() {

Serial.begin(9600);
}

// All array values {FL,FR,BL,BR}
int sensorReading[4];
const int sensorPin[4] = { A0, A1, A2, A3 };

void loop() {

for(int wheel = 0; wheel < 4; wheel++) {

sensorReading[wheel] = analogRead(sensorPin[wheel]);
 
  Serial.println(sensorReading[wheel]);
  delay(10);
  }
}

Ahh perfect I tried having a0 etc in the naming array but it gave me errors but I think I see where I went wrong perfect th a ks for your help!!

I’ve rewritten my code with various arrays and am now up to the timing stage.

I’m on phone so don’t have code with me but essentially I have 3 variables as follow

Unsigned long CurrentTime;
LastTimeStable[4];
Int TimeDelay =5000;

Later on in the loop the current time is set equal to millis ()

I also have the sensors writing the following as true if either low high or stable respectively

SensorLow [4]
SensorHigh [4]
SensorStable [4]

Tested all this and it works well thanks for that

This brings me to my original question that I need help with.

As an example for array index 0 which is front left corner I want it to do the following

I am wanting to set the array LastTimeStable value to current time when SensorStable is true

When sensorlow or sensor high is true it won’t update the last time value

Then have an if statement testing if the current time is greater than the last time value plus 5000ms then execute relay turn on

To do this part would I essentially do the following not looking at formatting as I’m on phone but am I on the right path?

for(int wheel = 0; wheel < 4; wheel++) 
  
   If (SensorStable [Wheels] == true){
    LastTime[Wheels]=CurrentTime 
      
         }

    If (SensorLow [Wheels] == true && CurrentTime>= (LastTime + TimeDelay)){ 
      digitalWrite( InflateRelays [Wheels], 1)
      digitalWrite( DeflateRelays [Wheels], 0)
         }

        If (SensorHigh[Wheels] == true && CurrentTime>= (LastTime + TimeDelay)){ 
      digitalWrite( InflateRelays [Wheels], 0)
      digitalWrite( DeflateRelays [Wheels], 1)
         }

      If (Sensorstable [Wheels] == true ){ 
      digitalWrite( InflateRelays [Wheels], 0)
      digitalWrite( DeflateRelays [Wheels], 0)
         }
  }
}

If I’m way off please give suggestions sorry been looking at too much code the other day not thinking properly haha cheers I can post my actual code tonight but jist want to see if this is one way to approach it

Sounds like you have got the idea.

Some more tips for you to think about:

You don't need to write

if (booleanVariable == true && x > y)

you can just say

if (booleanVariable && x > y)

This is because a boolean can have the values true or false, so you don't need to compare it to the value true.

In your code above, did you mean "LastTimeStable[wheel]" when you wrote "LastTime"?

Does your code now have many repetitions of the for loop? You can probably merge them all into a single for loop.

Yes sorry meant to write LastTimeStable [Wheels]

And it's just one simple for loop containing those 3 conditions Although soon will be larger containing a while for when handbrake is on and a few other things but yes very slim compared to how it was going to be!

So that way of comparing should work or is it best to say if current time - last time >= timedelay

Theoretically speaking, that second way you wrote is better because it deals with the situation where millis() rolls over back to zero. But that happens after around a month of continuous running, so I don't think your circuit is going to see that happen.