Go Down

Topic: Fuel gauge smoothing help (Read 3771 times) previous topic - next topic

SXRguyinMA

Jul 26, 2015, 05:37 pm Last Edit: Jul 26, 2015, 05:42 pm by SXRguyinMA
Hey guys. I'm working on retrofitting my bike from just a low fuel warning light (which doesn't work anyway) to a float level guage from a later year of the same bike. I have the fuel sender and I have a gauge working on a 16x2 LCD. What I want is to smooth the readings so the gauge isn't all over the place going down the road.

I had implemented it in code but the problem is the gauge starts off form the bottom as the readings and average pile up. Also for some reason with the smoothing once the values started to pile up my LCD display would go all screwy and every portion would fill up with a full square and random divide signs and space invader characters would pop in and out.

Here's the code as I have it now which works perfectly, just with no smoothing.

Code: [Select]
/*
 *LCD Fuel Gauge for Honda SuperHawk 16L Tank
 *http://www.superhawkforum.com/forums/technical-discussion-28/fuel-gauge-mods-33365/
 *Basic concept found at http://www.pddnet.com/articles/2014/01/designing-arduino-fuel-gauge-warning-lights
 *Code by Will Lyon 7/26/2015. Contact: will.lyon12584@gmail.com
 *Uses the LcdBarGraph1.5 Library for Arduino. Author:  Balázs Kelemen. Contact: prampec+arduino@gmail.com
 *LCDBarGraph library can be found here: http://playground.arduino.cc/Code/LcdBarGraph#Download
 *Designed to be used with the Adafruit 16x2 RGB LCD (both negative and positive work properly)
 *5V to fuel sensor Grn/Blk
 *Fuel sensor Gry/Blk to Analog 0 with 10k resistor to GND
*/

#include <LiquidCrystal.h> // Include Liquid Crystal library
#include <LcdBarGraph.h> // Include LCD Bar Graph library

byte lcdNumCols = 16; // 16 columns in the 16x2 LCD
byte sensorPin = A0; // Fuel float sensor 5V input with 10k resistor to GND and Analog 0

LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // LCD connected to digital 7-12
LcdBarGraph lbg(&lcd,16,0,1); // Parameters for LCD bar grah library
const int redPin = 5; // Red LCD backlight on Digital pin 5
const int grnPin = 6; // Green LCD backlight on Digital pin 6

void setup() {
  Serial.begin(9600); // Initialize communication with PC via serial monitor
  pinMode(redPin, OUTPUT); // Configure red LED pin as output
  pinMode(grnPin, OUTPUT); // Configure green LED pin as output
  pinMode(sensorPin, INPUT); // Configure the fuel level sensor pin (A0) as an input
  lcd.begin(2, lcdNumCols); // Define LCD as having 2 rows and refer to the above byte for number of columns
  lcd.clear(); // Clear the LCD display
  delay(100); // Wait 100ms
}

void loop() {
  int level = analogRead(sensorPin); // Label sensor reading as "level"
  level = map(level, 624, 946, 0 ,1023); // Map the sensor's 624E/946F readings to 0-1023 for proper graph display
  lcd.setCursor(0, 0); // Set cursor to top left of display
  lcd.print("E      ||      F"); // Static full/empty readout on the LCD
  lbg.drawValue( level, 1023); // Draw graph as fuel level reading
  if (level < 200) // If the mapped value is below 200 (approx. 3L fuel remaining)
  {
    analogWrite (grnPin, 255); // Turn the green LCD backlight off
    analogWrite (redPin, 0); // Turn the red LCD backlight on
  }
  else // Otherwise
  {
    analogWrite (grnPin, 0); // Turn the green LCD backlight on
    analogWrite (redPin, 255); // turn the red LCD backlight off
  }
  delay(100); // Delay between readings
}


Any help is greatly appreciated. Thanks!

Here's a video of how it works currently: https://photos.google.com/share/AF1QipPTjZQtcFW9HBCw5SEVOGHq9Fh1uWIqKFjy_9rUXuSbnHad5mt_8jSzTAJaN2pwcA?key=Vllfd2JkRTE3ejNVTlFRcG1QbGhUM21lVV9FaDBn

robtillaart

#1
Jul 26, 2015, 06:17 pm Last Edit: Jul 26, 2015, 06:20 pm by robtillaart
try this  ( I removed the most obvious comments for readability)

Code: [Select]
/*
 *LCD Fuel Gauge for Honda SuperHawk 16L Tank
 *http://www.superhawkforum.com/forums/technical-discussion-28/fuel-gauge-mods-33365/
 *Basic concept found at http://www.pddnet.com/articles/2014/01/designing-arduino-fuel-gauge-warning-lights
 *Code by Will Lyon 7/26/2015. Contact: will.lyon12584@gmail.com
 *Uses the LcdBarGraph1.5 Library for Arduino. Author:  Balázs Kelemen. Contact: prampec+arduino@gmail.com
 *LCDBarGraph library can be found here: http://playground.arduino.cc/Code/LcdBarGraph#Download
 *Designed to be used with the Adafruit 16x2 RGB LCD (both negative and positive work properly)
 *5V to fuel sensor Grn/Blk
 *Fuel sensor Gry/Blk to Analog 0 with 10k resistor to GND
*/


#include <LiquidCrystal.h>
#include <LcdBarGraph.h>

byte lcdNumCols = 16;
byte lcdNumRows = 2;
byte sensorPin = A0;        // Fuel float sensor 5V input with 10k resistor to GND and Analog 0

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
LcdBarGraph lbg(&lcd,16,0,1);         

const int redPin = 5;    // Red LCD backlight on Digital pin 5
const int grnPin = 6;    // Green LCD backlight on Digital pin 6

void setup() {
  Serial.begin(9600); // Initialize communication with PC via serial monitor

  pinMode(redPin, OUTPUT); // Configure red LED pin as output
  pinMode(grnPin, OUTPUT); // Configure green LED pin as output

  lcd.begin(lcdNumRows, lcdNumCols);
  lcd.clear();
  delay(100);
}


void loop() {
  int level = 0;
  for (int i=0; i< 16; i++)   // average 16 readings
  {
    level += analogRead(sensorPin);
  }
  level = level / 16;
  level = map(level, 624, 946, 0, 1023); // Map sensor's 624E/946F readings to 0-1023 for proper graph display

  lcd.setCursor(0, 0);               // Set cursor to top left of display
  lcd.print("E      ||      F");     // Static full/empty readout on the LCD
  lbg.drawValue(level, 1023);        // Draw graph as fuel level reading
 
  if (level < 200)                   // If the mapped value is below 200 (approx. 3L fuel remaining) adjust back color
  {
    analogWrite (grnPin, 255);
    analogWrite (redPin, 0);
  }
  else
  {
    analogWrite (grnPin, 0);
    analogWrite (redPin, 255);
  }
  delay(100); // Delay between readings
}
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

#2
Jul 26, 2015, 06:20 pm Last Edit: Jul 26, 2015, 06:22 pm by robtillaart
you can use the colour display also in this way

Code: [Select]
  if (level > 512)
  {
    analogWrite (grnPin, 0);
    analogWrite (redPin, 255);
  }
  else
  {
    analogWrite (grnPin, 255-level/2);
    analogWrite (redPin, level/2);
  }


the colour now smoothly goes from green to yellow to red
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

SXRguyinMA

#3
Jul 26, 2015, 08:03 pm Last Edit: Jul 26, 2015, 08:04 pm by SXRguyinMA
It would seem 16 samples isn't nearly enough as it's still almost instantaneous. I tried upping it to 32 and it worked but anything higher and the screen gets all wonky again.

Also that color change part doesn't work - when full it's red then just under full is green which fades to red at 1/2 tanks, then it's back to green under 1/2 lol

robtillaart

#4
Jul 26, 2015, 08:55 pm Last Edit: Jul 26, 2015, 08:55 pm by robtillaart
if you need more samples you need to make level of the type long
or use a low pass filter - see code below.

(colour changed too)

Code: [Select]
/*
 *LCD Fuel Gauge for Honda SuperHawk 16L Tank
 *http://www.superhawkforum.com/forums/technical-discussion-28/fuel-gauge-mods-33365/
 *Basic concept found at http://www.pddnet.com/articles/2014/01/designing-arduino-fuel-gauge-warning-lights
 *Code by Will Lyon 7/26/2015. Contact: will.lyon12584@gmail.com
 *Uses the LcdBarGraph1.5 Library for Arduino. Author:  Balázs Kelemen. Contact: prampec+arduino@gmail.com
 *LCDBarGraph library can be found here: http://playground.arduino.cc/Code/LcdBarGraph#Download
 *Designed to be used with the Adafruit 16x2 RGB LCD (both negative and positive work properly)
 *5V to fuel sensor Grn/Blk
 *Fuel sensor Gry/Blk to Analog 0 with 10k resistor to GND
*/


#include <LiquidCrystal.h>
#include <LcdBarGraph.h>

byte lcdNumCols = 16;
byte lcdNumRows = 2;
byte sensorPin = A0;        // Fuel float sensor 5V input with 10k resistor to GND and Analog 0

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
LcdBarGraph lbg(&lcd,16,0,1);         

const int redPin = 5;    // Red LCD backlight on Digital pin 5
const int grnPin = 6;    // Green LCD backlight on Digital pin 6

int level = 0;

void setup() {
  Serial.begin(9600); // Initialize communication with PC via serial monitor

  pinMode(redPin, OUTPUT); // Configure red LED pin as output
  pinMode(grnPin, OUTPUT); // Configure green LED pin as output

  lcd.begin(lcdNumRows, lcdNumCols);
  lcd.clear();
  delay(100);

  level = analogRead(sensorPin);
}


void loop() {
  // LOW PASS FILTERING; NEW VALUE COUNT FOR 1/16'th

  level = (level*15 + analogRead(sensorPin)) / 16;

  level = map(level, 624, 946, 0, 1023); // Map sensor's 624E/946F readings to 0-1023 for proper graph display

  lcd.setCursor(0, 0);               // Set cursor to top left of display
  lcd.print("E      ||      F");     // Static full/empty readout on the LCD
  lbg.drawValue(level, 1023);        // Draw graph as fuel level reading
 
  if (level < 200)                   // If the mapped value is below 200 (approx. 3L fuel remaining) adjust back color
  {
    analogWrite (grnPin, 0);
    analogWrite (redPin, 255);
  }
  else
  {
    analogWrite (grnPin, 255);
    analogWrite (redPin, 0);
  }
  delay(1000); // Delay between readings
}


give it a try
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

SXRguyinMA

Yea that made the LCD go nuts. It's flashing back and forth from red to green and all the boxes are filled once again with randome characters popping in here and there

SXRguyinMA

I modified it slightly so that if the bike is in neutral (neutral indicator on) it will read instantly but if it's in gear (indicator off) I want it to smooth the reading to keep tha gauge steady:

Code: [Select]
/*
 *LCD Fuel Gauge for Honda SuperHawk 16L Tank
 *http://www.superhawkforum.com/forums/technical-discussion-28/fuel-gauge-mods-33365/
 *Basic concept found at http://www.pddnet.com/articles/2014/01/designing-arduino-fuel-gauge-warning-lights
 *Code by Will Lyon 7/26/2015. Contact: will.lyon12584@gmail.com
 *Uses the LcdBarGraph1.5 Library for Arduino. Author:  Balázs Kelemen. Contact: prampec+arduino@gmail.com
 *LCDBarGraph library can be found here: http://playground.arduino.cc/Code/LcdBarGraph#Download
 *Designed to be used with the Adafruit 16x2 RGB LCD (both negative and positive work properly)
 *5V to fuel sensor Grn/Blk
 *Fuel sensor Gry/Blk to Analog 0 with 10k resistor to GND
*/

#include <LiquidCrystal.h> // Include Liquid Crystal library
#include <LcdBarGraph.h> // Include LCD Bar Graph library

byte lcdNumCols = 16; // 16 columns in the 16x2 LCD
byte sensorPin = A0; // Fuel float sensor 5V input with 10k resistor to GND and Analog 0
byte neutralPin = A1; // Neutral indicator to Analog 1 with 10k resistor to GND

LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // LCD connected to digital 7-12
LcdBarGraph lbg(&lcd,16,0,1); // Parameters for LCD bar grah library
const int redPin = 5; // Red LCD backlight on Digital pin 5
const int grnPin = 6; // Green LCD backlight on Digital pin 6

void setup() {
  Serial.begin(9600); // Initialize communication with PC via serial monitor
  pinMode(redPin, OUTPUT); // Configure red LED pin as output
  pinMode(grnPin, OUTPUT); // Configure green LED pin as output
  pinMode(sensorPin, INPUT); // Configure the fuel level sensor pin (A0) as an input
  pinMode(neutralPin, INPUT); // Configure the neutral indicator pin as an input
  lcd.begin(2, lcdNumCols); // Define LCD as having 2 rows and refer to the above byte for number of columns
  lcd.clear(); // Clear the LCD display
  delay(100); // Wait 100ms
}

void loop() {
  int gear = analogRead(neutralPin); // Label neutral pin as "gear"
  if (gear = HIGH) // If the neutral light is on
  {
    int level = analogRead(sensorPin); // Label sensor reading as "level"
    level = map(level, 624, 946, 0 ,1023); // Map the sensor's 624E/946F readings to 0-1023 for proper graph display
    lcd.setCursor(0, 0); // Set cursor to top left of display
    lcd.print("E      ||      F"); // Static full/empty readout on the LCD
    lbg.drawValue( level, 1023); // Draw graph as fuel level reading
    if (level < 200) // If the mapped value is below 200 (approx. 3L fuel remaining)
    {
      analogWrite (grnPin, 255); // Turn the green LCD backlight off
      analogWrite (redPin, 0); // Turn the red LCD backlight on
    }
    else // Otherwise
    {
      analogWrite (grnPin, 0); // Turn the green LCD backlight on
      analogWrite (redPin, 255); // turn the red LCD backlight off
    }
  }
  else // If the neutral indicator is off (bike in gear)
  {
    int level = analogRead(sensorPin); // Label sensor reading as "level"
    level = map(level, 624, 946, 0 ,1023); // Map the sensor's 624E/946F readings to 0-1023 for proper graph display
    lcd.setCursor(0, 0); // Set cursor to top left of display
    lcd.print("E      ||      F"); // Static full/empty readout on the LCD
    lbg.drawValue( level, 1023); // Draw graph as fuel level reading
    if (level < 200) // If the mapped value is below 200 (approx. 3L fuel remaining)
    {
      analogWrite (grnPin, 255); // Turn the green LCD backlight off
      analogWrite (redPin, 0); // Turn the red LCD backlight on
    }
    else // Otherwise
    {
      analogWrite (grnPin, 0); // Turn the green LCD backlight on
      analogWrite (redPin, 255); // turn the red LCD backlight off
    }
  }
  delay(100); // Delay between readings
}

johnwasser

Your current code doesn't do any smoothing at all.  Wasn't that the problem you were trying to solve?



Try putting this code at the top of loop() to smoothe 'level' over about a second.


Code: [Select]

    static int rawLevel = 624;  // default to empty
    static unsigned long levelReadTime = 0;
    static int level = 0;   // default to empty

   if (millis() - levelReadTime >= 100) {  // Sample level 10 times per second
     rawLevel = (rawLevel * 9 +  analogRead(sensorPin)) / 10;
    level = map(rawLevel, 624, 946, 0 ,1023); // Map the raw values (624=E, 946=F) to 0-1023 for proper graph display[color=#222222][/color]
    level = constrain(level, 0, 1023);  // Just in case it goes out of the expected range
    levelReadTime = millis();
  }
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp
See who has no social life: https://forum.arduino.cc/index.php?action=stats :)

SXRguyinMA

Yea that's what I want, I've got it split into the two parts so I can add in the smoothing for the second section (in gear/neutral light off)

SXRguyinMA

Your current code doesn't do any smoothing at all.  Wasn't that the problem you were trying to solve?



Try putting this code at the top of loop() to smoothe 'level' over about a second.


Code: [Select]

    static int rawLevel = 624;  // default to empty
    static unsigned long levelReadTime = 0;
    static int level = 0;   // default to empty

   if (millis() - levelReadTime >= 100) {  // Sample level 10 times per second
     rawLevel = (rawLevel * 9 +  analogRead(sensorPin)) / 10;
    level = map(rawLevel, 624, 946, 0 ,1023); // Map the raw values (624=E, 946=F) to 0-1023 for proper graph display[color=#222222][/color]
    level = constrain(level, 0, 1023);  // Just in case it goes out of the expected range
    levelReadTime = millis();
  }


That doesn't work. If the gauge is all the way down the LCD goes all screwy until the float gues up for a bit so it will amass some readings. Also the calibration is off for some reason now, where 1/2 float height isn't 1/2 on the LCD - it just drops right down to E at 1/2 float height. It's also still way too fast. I may just need a low pass filter on the hardware side I think as any software filtering makes the LCD go all weird.

johnwasser

I see that the example on the page for the bar graph library says:
Code: [Select]
 // -- do some delay: frequent draw may cause broken visualization
Perhaps if the LCD was updated ten times per second instead of every time through loop() it would not get corrupted.  Just move the bar graph call up to where 'level' is calculated.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp
See who has no social life: https://forum.arduino.cc/index.php?action=stats :)

SXRguyinMA

#11
Jul 29, 2015, 03:46 am Last Edit: Jul 29, 2015, 04:13 am by SXRguyinMA
Ok so I got it working with the delay. I increased the delay to 2 seconds to further slow the graph movement and it works good.

Now I want to implement the neutral light. If the bike is in neutral I don't want any smoothing (similar to a car). But if the bike is in gear I want it to smooth.

So I edited the code to read whether or not the neutral indicator is lit and if it is to read it as I had it previously and if it's nto to use the smoothing code. However it doesn't seem to work, it seems to skip over the smoothing part and just work without it as before. I have a 10k to ground on A1 and a jumper from A1 to ground to simulate the light being off (bike in gear).

Code: [Select]
/*
 *LCD Fuel Gauge for Honda SuperHawk 16L Tank
 *http://www.superhawkforum.com/forums/technical-discussion-28/fuel-gauge-mods-33365/
 *Basic concept found at http://www.pddnet.com/articles/2014/01/designing-arduino-fuel-gauge-warning-lights
 *Code by Will Lyon 7/26/2015. Contact: will.lyon12584@gmail.com
 *Uses the LcdBarGraph1.5 Library for Arduino. Author:  Balázs Kelemen. Contact: prampec+arduino@gmail.com
 *LCDBarGraph library can be found here: http://playground.arduino.cc/Code/LcdBarGraph#Download
 *Designed to be used with the Adafruit 16x2 RGB LCD (both negative and positive work properly)
 *5V to fuel sensor Grn/Blk
 *Fuel sensor Gry/Blk to Analog 0 with 10k resistor to GND
 *Neutral indicator to Analog 1 with 10k to ground
 *This will smooth the readings while the bike is in gear
*/

#include <LiquidCrystal.h> // Include Liquid Crystal library
#include <LcdBarGraph.h>   // Include LCD Bar Graph library

byte lcdNumCols = 16; // 16 columns in the 16x2 LCD
byte fuelPin = A0;    // Fuel float sensor 5V input with 10k resistor to GND and Analog 0
byte smoothPin = A1;  // Neutral light connected to A1 with 10k to ground

LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // LCD connected to digital 7-12
LcdBarGraph lbg(&lcd,16,0,1);           // Parameters for LCD bar grah library
const int redPin = 5;                   // Red LCD backlight on Digital pin 5
const int grnPin = 6;                   // Green LCD backlight on Digital pin 6
static int rawLevel = 624;              // Default to empty

void setup() {
  pinMode(redPin, OUTPUT);   // Configure red LED pin as output
  pinMode(grnPin, OUTPUT);   // Configure green LED pin as output
  pinMode(fuelPin, INPUT);   // Configure the fuel level sensor pin (A0) as an input
  pinMode(smoothPin, INPUT); // Configure the neutral indicator light (D3) as an input
  lcd.begin(2, lcdNumCols);  // Define LCD as having 2 rows and refer to the above byte for number of columns
  lcd.clear();               // Clear the LCD display
  delay(100);
}

void loop() {
  digitalRead(smoothPin);                     // Read the neutral indicator
  if (smoothPin = LOW) {                      // If the neutral light is OFF (in gear)
    static unsigned long levelReadTime = 0;   // Smooth the reading
    static int level = 0;                     // Default to empty
    if (millis() - levelReadTime >= 2000) {   // Sample level once every 2 seconds
    rawLevel = (rawLevel * 9 +  analogRead(fuelPin)) / 10;
    level = map(rawLevel, 624, 946, 0 ,1023); // Map the raw values (624=E, 946=F) to 0-1023 for proper graph display
    level = constrain(level, 0, 1023);        // Just in case it goes out of the expected range
    levelReadTime = millis();
    }
    lcd.setCursor(0, 0);                   // Set cursor to top left of display
    lcd.print("E      ||      F");         // Static full/empty readout on the LCD
    lbg.drawValue( level, 1023);           // Draw graph as fuel level reading
    if (level < 200)                       // If the mapped value is below 200 (approx. 3L fuel remaining)
    {
      analogWrite (grnPin, 255); // Turn the green LCD backlight off
      analogWrite (redPin, 0);   // Turn the red LCD backlight on
    }
    else
    {
      analogWrite (grnPin, 0);   // Turn the green LCD backlight on
      analogWrite (redPin, 255); // turn the red LCD backlight off
    }
  }
  if (smoothPin = HIGH) {                  // If the neutral light is ON (in neutral), don't smooth the reading
    int level = analogRead(fuelPin);       // Label sensor reading as "level"
    level = map(level, 624, 946, 0 ,1023); // Map the sensor's 624E/946F readings to 0-1023 for proper graph display
    lcd.setCursor(0, 0);                   // Set cursor to top left of display
    lcd.print("E      ||      F");         // Static full/empty readout on the LCD
    lbg.drawValue( level, 1023);           // Draw graph as fuel level reading
    if (level < 200)                       // If the mapped value is below 200 (approx. 3L fuel remaining)
    {
      analogWrite (grnPin, 255); // Turn the green LCD backlight off
      analogWrite (redPin, 0);   // Turn the red LCD backlight on
    }
    else
    {
      analogWrite (grnPin, 0);   // Turn the green LCD backlight on
      analogWrite (redPin, 255); // turn the red LCD backlight off
    }
  }
  delay(100);
}

SXRguyinMA

#12
Jul 29, 2015, 04:30 am Last Edit: Jul 29, 2015, 04:35 am by SXRguyinMA
OK I have it working almost 100%. The only problem is that if I hold the float up (full tank) with A1 to 5V (light on) the gauge reads full instantly. However if I then remove the 5V from A1 (light off) while still holding the float up (full) the gauge starts off low until it amasses some readings. How can I get it to stay at the "light on" level when it switches to "light off"?

EDIT: If I leave it in "light off" mode and let it get to full it stays when I go to "light on" then back. However if I start with "light on" as you'd normally start the bike - in neutral - and then switch to "light off" it goes to empty then works it's way back up.

Code: [Select]
/*
 *LCD Fuel Gauge for Honda SuperHawk 16L Tank
 *http://www.superhawkforum.com/forums/technical-discussion-28/fuel-gauge-mods-33365/
 *Basic concept found at http://www.pddnet.com/articles/2014/01/designing-arduino-fuel-gauge-warning-lights
 *Code by Will Lyon 7/26/2015. Contact: will.lyon12584@gmail.com
 *Uses the LcdBarGraph1.5 Library for Arduino. Author:  Balázs Kelemen. Contact: prampec+arduino@gmail.com
 *LCDBarGraph library can be found here: http://playground.arduino.cc/Code/LcdBarGraph#Download
 *Designed to be used with the Adafruit 16x2 RGB LCD (both negative and positive work properly)
 *5V to fuel sensor Grn/Blk
 *Fuel sensor Gry/Blk to Analog 0 with 10k resistor to GND
 *Neutral indicator to Analog 1 with 10k to ground
 *This will smooth the readings while the bike is in gear
*/

#include <LiquidCrystal.h> // Include Liquid Crystal library
#include <LcdBarGraph.h>   // Include LCD Bar Graph library

byte lcdNumCols = 16; // 16 columns in the 16x2 LCD
byte fuelPin = A0;    // Fuel float sensor 5V input with 10k resistor to GND and Analog 0
byte smoothPin = A1;  // Neutral light connected to A1 with 10k to ground

LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // LCD connected to digital 7-12
LcdBarGraph lbg(&lcd,16,0,1);           // Parameters for LCD bar grah library
const int redPin = 5;                   // Red LCD backlight on Digital pin 5
const int grnPin = 6;                   // Green LCD backlight on Digital pin 6
static int rawLevel = 624;              // Default to empty

void setup() {
  pinMode(redPin, OUTPUT);   // Configure red LED pin as output
  pinMode(grnPin, OUTPUT);   // Configure green LED pin as output
  pinMode(fuelPin, INPUT);   // Configure the fuel level sensor pin (A0) as an input
  pinMode(smoothPin, INPUT); // Configure the neutral indicator light (D3) as an input
  lcd.begin(2, lcdNumCols);  // Define LCD as having 2 rows and refer to the above byte for number of columns
  lcd.clear();               // Clear the LCD display
  delay(100);
}

void loop() {
  int light = digitalRead(smoothPin);         // Read the neutral indicator
  if (light == LOW) {                         // If the neutral light is OFF (in gear)
    static unsigned long levelReadTime = 0;   // Smooth the reading
    static int level = 0;                     // Default to empty
    if (millis() - levelReadTime >= 2000) {   // Sample level once every 2 seconds
    rawLevel = (rawLevel * 9 +  analogRead(fuelPin)) / 10;
    level = map(rawLevel, 624, 946, 0 ,1023); // Map the raw values (624=E, 946=F) to 0-1023 for proper graph display
    level = constrain(level, 0, 1023);        // Just in case it goes out of the expected range
    levelReadTime = millis();
    }
    lcd.setCursor(0, 0);                   // Set cursor to top left of display
    lcd.print("E      ||      F");         // Static full/empty readout on the LCD
    lbg.drawValue( level, 1023);           // Draw graph as fuel level reading
    if (level < 200)                       // If the mapped value is below 200 (approx. 3L fuel remaining)
    {
      analogWrite (grnPin, 255); // Turn the green LCD backlight off
      analogWrite (redPin, 0);   // Turn the red LCD backlight on
    }
    else
    {
      analogWrite (grnPin, 0);   // Turn the green LCD backlight on
      analogWrite (redPin, 255); // turn the red LCD backlight off
    }
  }
  delay(100);
  if (light == HIGH) {                     // If the neutral light is ON (in neutral), don't smooth the reading
    int level = analogRead(fuelPin);       // Label sensor reading as "level"
    level = map(level, 624, 946, 0 ,1023); // Map the sensor's 624E/946F readings to 0-1023 for proper graph display
    lcd.setCursor(0, 0);                   // Set cursor to top left of display
    lcd.print("E      ||      F");         // Static full/empty readout on the LCD
    lbg.drawValue( level, 1023);           // Draw graph as fuel level reading
    if (level < 200)                       // If the mapped value is below 200 (approx. 3L fuel remaining)
    {
      analogWrite (grnPin, 255); // Turn the green LCD backlight off
      analogWrite (redPin, 0);   // Turn the red LCD backlight on
    }
    else
    {
      analogWrite (grnPin, 0);   // Turn the green LCD backlight on
      analogWrite (redPin, 255); // turn the red LCD backlight off
    }
  }
  delay(100);
}

SXRguyinMA

OK so I decided to ditch to LCD and go for a 10-segment LED instead due to size. I've got it working in dot mode however I want to see if I can change it at all. What I'd like is for it to dot through the first 5 (green) then through the next 3 (yellow). However when it gets tot he last two (red) I want them to both come on then as the level drops be left with a single blinking red LED. How can I do this? Here's my modified code (still have to add smoothing back in):

Code: [Select]
/*
 *LED Fuel Gauge for Honda SuperHawk 16L Tank
 *http://www.superhawkforum.com
 *Code by Will Lyon 7/24/2015. Contact: will.lyon12584@gmail.com
 *5V to fuel sensor Grn/Blk
 *Fuel sensor Gry/Blk to Analog 0 with 10k resistor to GND
 *220 ohm resistor to each led and GND
*/

const int sensorPin = A0;   // the pin that the potentiometer is attached to
const int ledCount = 10;    // the number of LEDs in the bar graph

int ledPins[] = {
  2, 3, 4, 5, 6, 7,8,9,10,11 };   // an array of pin numbers to which LEDs are attached


void setup() {
  // loop over the pin array and set them all to output:
  for (int thisLed = 0; thisLed < ledCount; thisLed++) {
    pinMode(ledPins[thisLed], OUTPUT);
  }
}

void loop() {
  // read the potentiometer:
  int level = analogRead(sensorPin);
  // map the result to a range from 0 to the number of LEDs:
  level = map(level, 575, 945, 0, ledCount);

  // loop over the LED array:
  for (int thisLed = 0; thisLed < ledCount; thisLed++) {
    // if the array element's index is less than ledLevel,
    // turn the pin for this element on:
    if (thisLed == level-1) {
      digitalWrite(ledPins[thisLed], HIGH);
    }
    // turn off all pins higher than the ledLevel:
    else {
      digitalWrite(ledPins[thisLed], LOW);
    }
  }
  delay(100);
}

SXRguyinMA

Got it working nicely :)

Code: [Select]
/*
 *LED Fuel Gauge for Honda SuperHawk 16L Tank
 *http://www.superhawkforum.com
 *Code by Will Lyon 9/23/2015. Contact: will.lyon12584@gmail.com
 *5V to fuel sensor Grn/Blk
 *Fuel sensor Gry/Blk to Analog 0 with 10k resistor to GND
 *220 ohm resistor to each led and GND
*/

const int sensorPin = A0;       // the pin that the potentiometer is attached to
const int ledCount = 10;        // the number of LEDs in the bar graph
const int numReadings = 30;     // use this value to determine the size of the readings array

int ledPins[] = {
  2, 3, 4, 5, 6, 7,8,9,10,11 }; // an array of pin numbers to which LEDs are attached
int readings[numReadings];      // the readings from teh fuel level gauge
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average


void setup() {
  for (int thisLed = 0; thisLed < ledCount; thisLed++) {  // loop over the pin array and set them all to output:
    pinMode(ledPins[thisLed], OUTPUT);
  }
  Serial.begin(9600);
  for (int thisReading = 0; thisReading < numReadings; // initialize all readings to zero
thisReading++) {
  readings[thisReading] = 0;
  }
}

void loop() {
  total = total - readings[readIndex];        // subtract the last reading
  readings[readIndex] = analogRead(sensorPin);// read from the sensor
  total = total + readings[readIndex];        // add the reading to the total
  readIndex = readIndex + 1;                  // advance to the next position in the array
  if (readIndex >= numReadings) {             // if we're at the end of the array
    readIndex = 0;                            // wrap around to the beginning
  }
  average = total / numReadings;              // calculate the average
  Serial.println(average);                    // send it to the pc as ASCII digits
  delay(1000);                                // delay in between readings for stability
//  int level = analogRead(sensorPin);  // read the potentiometer:
  average = map(average, 580, 913, 0, ledCount); // map the result to a range from 0 to the number of LEDs:

  // loop over the LED array:
  for (int thisLed = 0; thisLed < ledCount; thisLed++) {
    // if the array element's index is less than ledLevel,
    // turn the pin for this element on:
    if (thisLed == average-1) {
      digitalWrite(ledPins[thisLed], HIGH);
    }
    // turn off all pins higher than the ledLevel:
    else {
      digitalWrite(ledPins[thisLed], LOW);
    }
  }
  delay(100);
}

Go Up