user7167: This code compares the analog input value against two thresholds, having three voltage regions. Then it will turn on an LED according to what region the read voltage is in.
The problem is that when the voltage read is very close to the threshold, the noise will disturb the output, resulting in an uncontrolled switching between LEDs.
I would need to add some sort of HYSTERESIS around my thresholds to avoid the uncontrolled switching, but I have no idea how to write this into the code language. Would anyone be able to help me writing the threshold bit?
This is the full code:
// these constant won't change:
const int BatteryVoltagePin = 14;   // the pin that battery voltage is attached to
const int GreenLedPin = 3;           // the pin that the green LED (On charge) is attached to
const int OrangeLedPin = 4;          // the pin that the orange LED (no risk) is attached to
const int RedLedPin = 5;             // the pin that the red LED (low battery) is attached to

// Variables will change:
int currentVoltage ;         // current voltage value
int previousVoltage ;     // previous voltage value    

void setup() {
  // initialize the battery voltage pin as a input:
  pinMode(BatteryVoltagePin, INPUT);
  // initialize the green LED as an output:
  pinMode(GreenLedPin, OUTPUT);
  // initialize the orange LED as an output:
  pinMode(OrangeLedPin, OUTPUT);
  // initialize the red LED as an output:
  pinMode(RedLedPin, OUTPUT);
}


void loop() {
  // read the voltage across the battery voltage pin:
  currentVoltage = digitalRead(BatteryVoltagePin);

  // compare the current voltage value to its previous value
 if (currentVoltage != previousVoltage) 

 delay(10);

    // value above maximum threshold
    {
     if ((( ( analogRead(BatteryVoltagePin) ) > ( 699 ) ))   
        {
        digitalWrite(GreenLedPin, HIGH);
        }
        else
        {
          digitalWrite(GreenLedPin, LOW );
        }
    }

    //value between two thresholds (middle region)
    {
     if (( ( ( analogRead(BatteryVoltagePin) ) <= ( 699 ) ) && ( ( analogRead(BatteryVoltagePin) ) >= ( 628 ) ) ))          
        {       
        digitalWrite(OrangeLedPin, HIGH );
        }
        else
        {
          digitalWrite(OrangeLedPin, LOW );
        }
    }

    // value below minimum threshold
    {
     if (( ( analogRead(BatteryVoltagePin) ) < ( 628 ) ))   
        {
        digitalWrite(RedLedPin, HIGH);
        }
        else
        {
          digitalWrite(RedLedPin, LOW );
        }
     }


  // save the current state as the last state, 
  //for next time through the loop
  previousVoltage = currentVoltage;
 }


user11258: This includes hysteresis and uses some loops and arrays to simplify and compact the code, since the logic for each range is essentially the same.  More ranges are easy to include by extending the Cutoffs and LedPins arrays (one more led than cutoff).
const int VoltagePin = 14;
const int Cutoffs[] = { 628 , 699 };
const int NumCutoffs = sizeof(Cutoffs)/sizeof(int);
const int Hysteresis = 5;

const int LedPins[NumCutoffs+1] = {5,4,3};

int Level = 0; 
int Voltage = 0;

void setup()
{
  for (int i=0; i<=NumCutoffs; ++i) {
    pinMode(LedPins[i],OUTPUT);
  }
}

void loop()
{
  Voltage = analogRead(VoltagePin);

  while (Level < NumCutoffs && Voltage >= Cutoffs[Level]) {
    ++Level;
  }

  while (Level > 0 && Voltage < Cutoffs[Level-1] - Hysteresis) {
    --Level;
  }

  for (int i=0; i<=NumCutoffs; ++i) {
    digitalWrite(LedPins[i], i == Level);
  }

  delay(20);
}


user15704: Here is what I do. I detect whether the voltage is rising or falling and adjust the threshold based on that.
int ledPin = 13;   //pin 13 will be connected to the MOSFET SS relay

void setup() {
    Serial.begin(9600);
    pinMode(ledPin, OUTPUT);
}

void loop() {
    int sensorValue = analogRead(A0); // This is the main battery voltage sensor
    int RLA1;   //this will be connected to the MOSFET SS relay
    float threshold; //  To enable some hysteresis and prevent the relay from chattering, we move the threshhold, depending on whether we are going up or down

    float Vmainold;  //  Used to detect whether we are going up or down
    float  Vmain;   // Main battery voltage.
    float Vaux;     // Auxillary battery voltage

    Vmain = sensorValue / 204.6 + 9.8;   // Add back the ~10V that the zener shifts for higher resolution

   if (Vmain > Vmainold) threshold = 13.2;  // If the voltage is rising, set threshhold to 13.2
   else
    if (Vmain < Vmainold) && (Vmainold > 12.8) threshold = 12.8 // If the voltage is falling and previous voltage is above TH, set theshhold to 12.8
    else
        if (Vmain = Vmainold) threshold = 13.2;  // If the voltage is stable, set threshhold to 13.2

   if (Vmain >= threshold) RLA1 = 1; //  Charging

   else
    if (Vmain < threshold) { RLA1 = 0;  Vmainold = Vmain; }  // Not connected

   delay(1000);
   Serial.print(Vmain);
   Serial.print("  Main  ");
   Serial.print(Vmainold);
   Serial.print("  old  ");
   Serial.println();
   Vmainold = Vmain;
   digitalWrite(ledPin, RLA1);
}

`

user3742: The state machine is a solid approach.
For this simple case, you can also solve this by implementing small dead bands around the change levels.  When the value is in a range near the transition threshold, do nothing.  Only when the value is certainly above or below the transition, make the change.  Your code would be:
// Variables will change:
int currentVoltage = 0;         // current voltage value
int previousVoltage = 0;     // previous voltage value    

void loop() {
  int deadband = 5;
  // on very first loop, start with no dead band
  // this is necessary in case starting voltage is in 
  // middle of a transition range
  if (0 == previousVoltage) {
    deadband = 0;
  }

  // read the voltage across the battery voltage pin:
  currentVoltage = analogRead(BatteryVoltagePin);

  // test the voltage against the three ranges
  // value above maximum threshold
  if ((699+deadband) < currentVoltage) {   
    digitalWrite(GreenLedPin, HIGH);
    digitalWrite(OrangeLedPin, LOW );
    digitalWrite(RedLedPin, LOW );
  }

  //value between two thresholds (middle region)
  if (((628+deadband) < currentVoltage) && (currentVoltage <= (699-deadband))) {          
    digitalWrite(GreenLedPin, LOW);
    digitalWrite(OrangeLedPin, HIGH);
    digitalWrite(RedLedPin, LOW);
  }

  // value below minimum threshold
  if (currentVoltage < (628-deadband)) {
    digitalWrite(GreenLedPin, LOW);
    digitalWrite(OrangeLedPin, LOW );
    digitalWrite(RedLedPin, HIGH);
  }

  // Note that at this point, none of the if cases above
  // might have been true.  When the voltage is right near the
  // thresholds, do nothing.  Only when the voltage is definitively
  // in the range does the LED state change.

  // save the current state as the last state, 
  //for next time through the loop
  previousVoltage = currentVoltage;
  delay(10);

  return;
}

In function, this will achieve the same result as hysteresis.

user1677: Adding hysteresis behavior to your code is not difficult. You just need to store the state you're in and make the thresholds for transitioning into another state dependent on that.
You can use an enum to store the state:
enum BatteryStates {
  Red, Orange, Green
};

Then, instead of defining and checking against one threshold value, define two thresholds for each transition, separated by so much that you don't observe the undesired flip-flopping behavior.
For example, when transitioning from Green to Orange you could do something like this:
if ((state == Green) && (battery < 690))
  state = Orange;

And the other direction would use a slightly higher threshold
if ((state == Orange) && (battery > 700))
  state = Green;

so that small fluctuations of the voltage do not cause flip-flopping.
(Note that my code assumes
int battery = analogRead(BatteryVoltagePin);

The variable state should be declared and initialized like so:
enum BatteryStates state = Green;

Instead of an enum you could use a simple int and map each state to a number (e.g. red = 1, orange = 2, green = 3), but using enum makes the code easier to read and write. (In fact enum does use integer numbers.)
I might also use a switch statement instead of an if chain to implement the transitions, but that's a matter of taste.)

7167: <p>This code compares the analog input value against two thresholds, having three voltage regions. Then it will turn on an LED according to what region the read voltage is in.</p>

<p>The problem is that when the voltage read is very close to the threshold, the noise will disturb the output, resulting in an uncontrolled switching between LEDs.</p>

<p>I would need to add some sort of HYSTERESIS around my thresholds to avoid the uncontrolled switching, but I have no idea how to write this into the code language. Would anyone be able to help me writing the threshold bit?</p>

<p>This is the full code:</p>

<pre><code>// these constant won't change:
const int BatteryVoltagePin = 14;   // the pin that battery voltage is attached to
const int GreenLedPin = 3;           // the pin that the green LED (On charge) is attached to
const int OrangeLedPin = 4;          // the pin that the orange LED (no risk) is attached to
const int RedLedPin = 5;             // the pin that the red LED (low battery) is attached to

// Variables will change:
int currentVoltage ;         // current voltage value
int previousVoltage ;     // previous voltage value    

void setup() {
  // initialize the battery voltage pin as a input:
  pinMode(BatteryVoltagePin, INPUT);
  // initialize the green LED as an output:
  pinMode(GreenLedPin, OUTPUT);
  // initialize the orange LED as an output:
  pinMode(OrangeLedPin, OUTPUT);
  // initialize the red LED as an output:
  pinMode(RedLedPin, OUTPUT);
}


void loop() {
  // read the voltage across the battery voltage pin:
  currentVoltage = digitalRead(BatteryVoltagePin);

  // compare the current voltage value to its previous value
 if (currentVoltage != previousVoltage) 

 delay(10);

    // value above maximum threshold
    {
     if ((( ( analogRead(BatteryVoltagePin) ) &gt; ( 699 ) ))   
        {
        digitalWrite(GreenLedPin, HIGH);
        }
        else
        {
          digitalWrite(GreenLedPin, LOW );
        }
    }

    //value between two thresholds (middle region)
    {
     if (( ( ( analogRead(BatteryVoltagePin) ) &lt;= ( 699 ) ) &amp;&amp; ( ( analogRead(BatteryVoltagePin) ) &gt;= ( 628 ) ) ))          
        {       
        digitalWrite(OrangeLedPin, HIGH );
        }
        else
        {
          digitalWrite(OrangeLedPin, LOW );
        }
    }

    // value below minimum threshold
    {
     if (( ( analogRead(BatteryVoltagePin) ) &lt; ( 628 ) ))   
        {
        digitalWrite(RedLedPin, HIGH);
        }
        else
        {
          digitalWrite(RedLedPin, LOW );
        }
     }


  // save the current state as the last state, 
  //for next time through the loop
  previousVoltage = currentVoltage;
 }
</code></pre>
 11258: <p>This includes hysteresis and uses some loops and arrays to simplify and compact the code, since the logic for each range is essentially the same.  More ranges are easy to include by extending the Cutoffs and LedPins arrays (one more led than cutoff).</p>

<pre><code>const int VoltagePin = 14;
const int Cutoffs[] = { 628 , 699 };
const int NumCutoffs = sizeof(Cutoffs)/sizeof(int);
const int Hysteresis = 5;

const int LedPins[NumCutoffs+1] = {5,4,3};

int Level = 0; 
int Voltage = 0;

void setup()
{
  for (int i=0; i&lt;=NumCutoffs; ++i) {
    pinMode(LedPins[i],OUTPUT);
  }
}

void loop()
{
  Voltage = analogRead(VoltagePin);

  while (Level &lt; NumCutoffs &amp;&amp; Voltage &gt;= Cutoffs[Level]) {
    ++Level;
  }

  while (Level &gt; 0 &amp;&amp; Voltage &lt; Cutoffs[Level-1] - Hysteresis) {
    --Level;
  }

  for (int i=0; i&lt;=NumCutoffs; ++i) {
    digitalWrite(LedPins[i], i == Level);
  }

  delay(20);
}
</code></pre>
 15704: <p>Here is what I do. I detect whether the voltage is rising or falling and adjust the threshold based on that.</p>

<pre class="lang-c prettyprint-override"><code>int ledPin = 13;   //pin 13 will be connected to the MOSFET SS relay

void setup() {
    Serial.begin(9600);
    pinMode(ledPin, OUTPUT);
}

void loop() {
    int sensorValue = analogRead(A0); // This is the main battery voltage sensor
    int RLA1;   //this will be connected to the MOSFET SS relay
    float threshold; //  To enable some hysteresis and prevent the relay from chattering, we move the threshhold, depending on whether we are going up or down

    float Vmainold;  //  Used to detect whether we are going up or down
    float  Vmain;   // Main battery voltage.
    float Vaux;     // Auxillary battery voltage

    Vmain = sensorValue / 204.6 + 9.8;   // Add back the ~10V that the zener shifts for higher resolution

   if (Vmain &gt; Vmainold) threshold = 13.2;  // If the voltage is rising, set threshhold to 13.2
   else
    if (Vmain &lt; Vmainold) &amp;&amp; (Vmainold &gt; 12.8) threshold = 12.8 // If the voltage is falling and previous voltage is above TH, set theshhold to 12.8
    else
        if (Vmain = Vmainold) threshold = 13.2;  // If the voltage is stable, set threshhold to 13.2

   if (Vmain &gt;= threshold) RLA1 = 1; //  Charging

   else
    if (Vmain &lt; threshold) { RLA1 = 0;  Vmainold = Vmain; }  // Not connected

   delay(1000);
   Serial.print(Vmain);
   Serial.print("  Main  ");
   Serial.print(Vmainold);
   Serial.print("  old  ");
   Serial.println();
   Vmainold = Vmain;
   digitalWrite(ledPin, RLA1);
}
</code></pre>

<p>`</p>
 3742: <p>The state machine is a solid approach.</p>

<p>For this simple case, you can also solve this by implementing small dead bands around the change levels.  When the value is in a range near the transition threshold, do nothing.  Only when the value is certainly above or below the transition, make the change.  Your code would be:</p>

<pre><code>// Variables will change:
int currentVoltage = 0;         // current voltage value
int previousVoltage = 0;     // previous voltage value    

void loop() {
  int deadband = 5;
  // on very first loop, start with no dead band
  // this is necessary in case starting voltage is in 
  // middle of a transition range
  if (0 == previousVoltage) {
    deadband = 0;
  }

  // read the voltage across the battery voltage pin:
  currentVoltage = analogRead(BatteryVoltagePin);

  // test the voltage against the three ranges
  // value above maximum threshold
  if ((699+deadband) &lt; currentVoltage) {   
    digitalWrite(GreenLedPin, HIGH);
    digitalWrite(OrangeLedPin, LOW );
    digitalWrite(RedLedPin, LOW );
  }

  //value between two thresholds (middle region)
  if (((628+deadband) &lt; currentVoltage) &amp;&amp; (currentVoltage &lt;= (699-deadband))) {          
    digitalWrite(GreenLedPin, LOW);
    digitalWrite(OrangeLedPin, HIGH);
    digitalWrite(RedLedPin, LOW);
  }

  // value below minimum threshold
  if (currentVoltage &lt; (628-deadband)) {
    digitalWrite(GreenLedPin, LOW);
    digitalWrite(OrangeLedPin, LOW );
    digitalWrite(RedLedPin, HIGH);
  }

  // Note that at this point, none of the if cases above
  // might have been true.  When the voltage is right near the
  // thresholds, do nothing.  Only when the voltage is definitively
  // in the range does the LED state change.

  // save the current state as the last state, 
  //for next time through the loop
  previousVoltage = currentVoltage;
  delay(10);

  return;
}
</code></pre>

<p>In function, this will achieve the same result as hysteresis.</p>
 1677: <p>Adding hysteresis behavior to your code is not difficult. You just need to store the state you're in and make the thresholds for transitioning into another state dependent on that.</p>

<p>You can use an enum to store the state:</p>

<pre><code>enum BatteryStates {
  Red, Orange, Green
};
</code></pre>

<p>Then, instead of defining and checking against one threshold value, define two thresholds for each transition, separated by so much that you don't observe the undesired flip-flopping behavior.</p>

<p>For example, when transitioning from Green to Orange you could do something like this:</p>

<pre><code>if ((state == Green) &amp;&amp; (battery &lt; 690))
  state = Orange;
</code></pre>

<p>And the other direction would use a slightly higher threshold</p>

<pre><code>if ((state == Orange) &amp;&amp; (battery &gt; 700))
  state = Green;
</code></pre>

<p>so that small fluctuations of the voltage do not cause flip-flopping.</p>

<p>(Note that my code assumes</p>

<pre><code>int battery = analogRead(BatteryVoltagePin);
</code></pre>

<p>The variable <code>state</code> should be declared and initialized like so:</p>

<pre><code>enum BatteryStates state = Green;
</code></pre>

<p>Instead of an <code>enum</code> you could use a simple <code>int</code> and map each state to a number (e.g. red = 1, orange = 2, green = 3), but using <code>enum</code> makes the code easier to read and write. (In fact <code>enum</code> does use integer numbers.)</p>

<p>I might also use a <code>switch</code> statement instead of an <code>if</code> chain to implement the transitions, but that's a matter of taste.)</p>
