Odd division problem

Hi guys,

I'm trying to get a bit of code working that will take a range of values from an analogRead, and 'normalise' them so they fall within a 0-100 range.

I have a formula to do this which works in excel, but not when coded in the sketch I'm writing.

Here's the code. The formula in question is in the function normalise:

#define G_PWM 6                  // define gauge pwm on digital pin 6
#define L_OUT_Y 2                // define yellow LED output on digital pin 2
#define L_OUT_R 4                // define red LED output on digital pin 4
#define SN_IN 0                  // define sender input on analog pin 0

const int fuelThresholdLow = 12; // 1/8th tank %
const int fuelThresholdInt = 25; // quarter tank %

const int analogFull = 184;      // lowest possible input value given sender / R1 voltage divider
const int analogEmpty = 841;     // highest possible input value given sender / R1 voltage divider

const int gaugeFull = 148;       // PWM duty cycle required to show full tank on gauge
const int gaugeEmpty = 58;       // PWM duty cycle required to show empty tank on gauge

int sender = 0;                  // current sender reading (will be in range of analogFull - analogEmpty)
int normal = 0;                  // 'normalised' sender reading (will be in range of 0 - 100)

void setup()
{
  
  pinMode(G_PWM, OUTPUT);
  pinMode(L_OUT_Y, OUTPUT); 
  pinMode(L_OUT_R, OUTPUT); 
  Serial.begin(9600);
}

void loop()
{
  // read value 
  sender = analogRead(SN_IN);
  
  // normalise
  normal = normalise(sender);
  
  // display
  gaugeDisplay(normal);
}

int normalise(int valRead)
{
  // normalise the input value from the sender to fall within 0-100 range
 
  // float normalisedSender = 100 * (1 - (valRead - analogFull) / (analogEmpty - analogFull));
  int topExpression = valRead - analogFull;
  int bottomExpression = analogEmpty - analogFull;
  double divideResult = topExpression / bottomExpression;
  double minusOperation = 1 - divideResult;
  double normalisedSender = 100 * minusOperation;
  
  // add .5 to get correct rounding
  //normalisedSender = normalisedSender + 0.5;
  
  Serial.print("SND: ");
  Serial.print(valRead, DEC);
  Serial.print(" TOP: ");
  Serial.print(topExpression, DEC);
  Serial.print(" BOT: ");  
  Serial.print(bottomExpression, DEC);
  Serial.print(" DIV: ");  
  Serial.print(divideResult, DEC);
  Serial.print(" MIN: ");  
  Serial.print(minusOperation, DEC);  
  Serial.print(" NORM: ");
  Serial.println(normalisedSender, DEC);
  
  // cast to an int to do the rounding
  return int(normalisedSender); 
}

void gaugeDisplay(int averagedTank)
{
  // take percentage value from normalisation & averaging and turn back into pwm 
  // duty cycle. Also determine each LED status
  
  int dutyCycle;
 
  dutyCycle = gaugeEmpty + ((gaugeFull - gaugeEmpty) * averagedTank / 100);
  
  // Gauge
  analogWrite(G_PWM, dutyCycle); 
  
  // Warning LEDs
  if (averagedTank <= fuelThresholdInt)
  {
    if (averagedTank <= fuelThresholdLow)
    {
      // Fuel low, light red LED
      digitalWrite(L_OUT_Y, LOW);
      digitalWrite(L_OUT_R, HIGH);
    }
    else
    {
      //Fuel intermediate, light yellow LED
      digitalWrite(L_OUT_Y, HIGH);
      digitalWrite(L_OUT_R, LOW);
    }
  }
  else
  {
    // both LEDs off
    digitalWrite(L_OUT_Y, LOW);
    digitalWrite(L_OUT_R, LOW);
  }
}

In an attempt to debug the calculation, I split the expression into different parts and did them in isolation, so I could spit the values out to the serial monitor to see what was going on.

What I get is my valRead variable changing as expected when the analog 'sender' is moved, as do the variables topExpression and bottomExpression. It's the divide that throws out a weird result - it's always either 0 for the entire range of analog values or 1 when we get to the bottom end, with nothing in between.

This has the effect of my normalised value only ever being 0 or 100.

I have no idea what I've done wrong here, and I've been staring at for hours. Can anyone with a fresh set of eyes help please? :slight_smile:

Thanks in advance,

Jason

The type of arithmetic performed depends on the type of variables being used in the calculation, not the type of variable the result will be stored in.

  int topExpression = valRead - analogFull;
  int bottomExpression = analogEmpty - analogFull;
  double divideResult = topExpression / bottomExpression;

An integer will be computed, and stored in divideResult.

This is probably not what you expect, or want. Either make topExpression and bottomExpression float (double is same size), or cast them in the calculation.

Thanks, that's now working. :slight_smile:

Use the function map perhaps also constrain. It does exactly what you want and comes in the Arduino box at no extra cost.

Korman