SOLVED Sensor target border

Please read post #7

Hi All

The code is a part of a fairly long sketch and i know you cannot compile it, however if someone could clarify if the way i done the hysteresis value is the way other do? i noticed that the target sometimes exceed the value it should stop at.

To briefly clarify:
LiftedFL is a bool of true or false.
LiftSensorValueFL is a actual real time sensor reading
readDriveMemFL is a EEPROM target value for the operation to stop to execute once reached
HysteresisLift is the threshold for the operation to fit in.

byte HysteresisLift = 8;

if (!liftedFL && (liftSensorValueFL <= (readDriveMemFL - HysteresisLift))) 
{
//code execution
}

Thanks in advance.

I find it impossible to determine what you have done from the code snippet posted.

I assume that you know that hysteresis is used to prevent rapid hunting around a target value read from a sensor by using a different target value when the value read from the sensor is increasing from that used when the sensor value is decreasing.

Does your program do that ?

UKHeliBob:
I find it impossible to determine what you have done from the code snippet posted.

I assume that you know that hysteresis is used to prevent rapid hunting around a target value read from a sensor by using a different target value when the value read from the sensor is increasing from that used when the sensor value is decreasing.

Does your program do that ?

I have no idea what you just said :smiley:

My thinking about hysteresis is that the target value have a border so assuming the target is 10 the execution can stop btw 2-18 to evaluate as true considering hysteresis is set to 8.

Better read up: Hysteresis - Wikipedia

gfvalvo:
Better read up: Hysteresis - Wikipedia

My bad. So how do we call it to be"right"? Target border?

The picture from the Wiki page provides a clear graphical explanation. At any given time, the threshold depends on the history of the system’s trajectory through the state diagram.

Hysteresis.JPG

Hysteresis.JPG

Ok, but this is not giving me the floating value for the target to settle down.
Hysteresis as per wiki, is rather "Pump on at 100psi/Pump off at 120psi" not pump until 120psi +/- 8 which what i`m looking for.

I will created new post as by my mistake we talking about 2 different thigs

Correction to the first few posts above.

I`m looking for a way on creating a border for a value. For example the target value is set to 50 and considering that the sensor value start to increase rapidly i want to have the option to evaluate as true anywhere 42 and 58 considering that the border is set to 8.

To briefly clarify:
LiftedFL is a bool of true or false.
LiftSensorValueFL is a actual real time sensor reading
readDriveMemFL is a EEPROM target value for the operation to stop to execute once reached
TargetBorderValue is the threshold for the operation to fit in.

int TargetBorderValue = 8;
bool liftedFL = false;


if (!liftedFL && (liftSensorValueFL <= (readDriveMemFL - TargetBorderValue))) {
liftedFL = true;

Thanks in advance.

It will be a lot easier to implement the system that you want if you start with an empty sketch, and hard code a few things, like the target value from EEPROM.

A minimal example will allow you to post ALL of your code AND your serial output.

It will be a lot easier, too, if you use nested if statements rather than compound if statements.

With nested if statements, it is easy to see what allows/prevents a block of code from executing. With compound if statements, that is much harder.

I see your point PaulS and agree to what you say. However, I don't have a issue with compiling or using this code, my only question is, is there any way to use +/- offset value for the target value as from the part I uploaded. I only target "minus" value with my code, rather then target "minus" value "or" target "plus" value. I cannot get my head around it.
Thanks

is there any way to use +/- offset value for the target value

If the target value is 50 and the sensor value will either start lower and increase towards it or start higher and reduce towards it, try this

if (abs(targetValue - currentValue) < 8)
{
  //we are within 8 of the target.  Do whatever is needed
}

The abs() function will return a positive number which is the difference between the target and current values

mOskit:
I`m looking for a way on creating a border for a value. For example the target value is set to 50 and considering that the sensor value start to increase rapidly i want to have the option to evaluate as true anywhere 42 and 58 considering that the border is set to 8.

Sounds like what I call a window. if( lowLimit <= argument <= hiLimit ). If the value is within a range then true else false.

Thanks guys.
Decided to use the abs()
If you think this could be further improved please let me know, but it does what i want.
The code below.

bool lifted = false;
unsigned long startMillis;
unsigned long currentMillis;
int targetValue = 100;
int LiftONtime = 200;
int LiftOFFtime = 200;
int LowerONtime = 100;
int LowerOFFtime = 1000;
int liftSensorValue = 0;
int UP = 10;
int DOWM = 9;
int TargetBorderValue = 8;
int HeightSensor = A2;
void setup() {
  Serial.begin(9600);
  pinMode(UP, OUTPUT);
  pinMode(DOWM, OUTPUT);
  pinMode(HeightSensor, INPUT);
}

void loop() {
  Serial.print("InputSensor = ");
  Serial.print(liftSensorValue);
  Serial.print(" Target = ");
  Serial.println(lifted);

  liftSensorValue = analogRead(HeightSensor);


  //If below target value
  
  if (!lifted) {

    if (liftSensorValue < targetValue && (abs(liftSensorValue - targetValue) > TargetBorderValue)) {

      currentMillis = millis();

      if (digitalRead(UP) == HIGH && currentMillis - startMillis >= LiftONtime)
      {
        digitalWrite(UP, LOW);
        startMillis = currentMillis;
      }
      else if (digitalRead(UP) == LOW && currentMillis - startMillis >= LiftOFFtime)
      {
        digitalWrite(UP, HIGH);
        startMillis = currentMillis;
      }

    }

    //If above target value
    
    else if (liftSensorValue > targetValue && (abs(liftSensorValue - targetValue) > TargetBorderValue)) {
      currentMillis = millis();

      if (digitalRead(DOWM) == HIGH && currentMillis - startMillis >= LowerONtime)
      {
        digitalWrite(DOWM, LOW);
        startMillis = currentMillis;
      }
      else if (digitalRead(DOWM) == LOW && currentMillis - startMillis >= LowerOFFtime)
      {
        digitalWrite(DOWM, HIGH);
        startMillis = currentMillis;
      }
    }

    //if in target
    else {
      digitalWrite(UP, LOW);
      digitalWrite(DOWM, LOW);
      lifted = true;
    }
  }
}

A couple of suggestions

Review the data types that you are using. For instance

int UP = 10;
int DOWM = 9;

Why are these pin numbers declared as ints when the largest number they could ever be is less than 255, for which a byte would suffice ? There are other examples of the same thing in the program. Save memory when you can by using the smallest size of data type appropriate for its purpose

Are these values going to change within the program ? If not then declare them as const to prevent any possible changes of value perhaps caused by a typo when editing the program

Could you improve the names to make them more descriptive when reading the code ?

loop() starts by printing liftSensorValue before reading its value which does not seem to make sense
When you print lifted, which is a boolean variable with a value of 0 or 1, why is its label printed as " Target = " ?

  //If below target value
  if (!lifted)

Does the comment match the code ? I suspect that the comment is in the wrong place

abs(liftSensorValue - targetValue)

This is calculated a couple of times in the code. I would calculate it once before it is needed and put the value in a variable with a sensible name such as distanceToTarget

loop() starts by printing liftSensorValue before reading its value which does not seem to make sense
When you print lifted, which is a boolean variable with a value of 0 or 1, why is its label printed as " Target = " ?

its just my sense of naming things. Im unable to declare it so it satisfy everybody.

Code: [Select]
abs(liftSensorValue - targetValue)

This is calculated a couple of times in the code. I would calculate it once before it is needed and put the value in a variable with a sensible name such as distanceToTarget

Will do.

Correct as advised.

bool targetReached = false;
unsigned long startMillis;
unsigned long currentMillis;
int targetValue = 100;
int LiftONtime = 200;
int LiftOFFtime = 200;
int LowerONtime = 100;
int LowerOFFtime = 1000;
int liftSensorValue = 0;
const byte UP = 10;
const byte DOWM = 9;
const byte TargetBorderValue = 8;
int HeightSensor = A2;
int distanceToTarget = 0;
void setup() {
  Serial.begin(9600);
  pinMode(UP, OUTPUT);
  pinMode(DOWM, OUTPUT);
  pinMode(HeightSensor, INPUT);
}

void loop() {


  liftSensorValue = analogRead(HeightSensor);
  distanceToTarget = abs(liftSensorValue - targetValue);
  Serial.print("InputSensor = ");
  Serial.print(liftSensorValue);
  Serial.print(" Target = ");
  Serial.println(targetReached);
  //If below target value

  if (!targetReached) {

    if (liftSensorValue < targetValue && (distanceToTarget > TargetBorderValue)) {
      digitalWrite(DOWM, LOW);
      currentMillis = millis();

      if (digitalRead(UP) == HIGH && currentMillis - startMillis >= LiftONtime)
      {
        digitalWrite(UP, LOW);
        startMillis = currentMillis;
      }
      else if (digitalRead(UP) == LOW && currentMillis - startMillis >= LiftOFFtime)
      {
        digitalWrite(UP, HIGH);
        startMillis = currentMillis;
      }

    }

    //If above target value

    else if (liftSensorValue > targetValue && (distanceToTarget > TargetBorderValue)) {
      digitalWrite(UP, LOW);
      currentMillis = millis();

      if (digitalRead(DOWM) == HIGH && currentMillis - startMillis >= LowerONtime)
      {
        digitalWrite(DOWM, LOW);
        startMillis = currentMillis;
      }
      else if (digitalRead(DOWM) == LOW && currentMillis - startMillis >= LowerOFFtime)
      {
        digitalWrite(DOWM, HIGH);
        startMillis = currentMillis;
      }
    }

    //if in target
    else {
      digitalWrite(UP, LOW);
      digitalWrite(DOWM, LOW);
      targetReached = true;
    }
  }
}