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?
Thanks in advance,
Jason