element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Arduino
  • Products
  • More
Arduino
Arduino Forum Help with Arduino timing problem
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Arduino to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 14 replies
  • Subscribers 392 subscribers
  • Views 1311 views
  • Users 0 members are here
  • gauge
  • millis()
  • arduino
Related

Help with Arduino timing problem

SXRguyinMA
SXRguyinMA over 10 years ago

Hey guys. I'm working on making a fuel gauge for my motorcycle. I have the basic concept working and I've added some averaging so that the gauge isn't going nuts while you're going down the road. Here's the current code:

/*

*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);

  }

  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

  delay(1000);                                // delay in between readings for stability

  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);

}

Now the problem I have is that when you first power it up (or turn the bike on) it takes about 5-10 seconds to gather enough readings to get the average high enough to get the gauge working. I tried implementing code that would read whether or not the neural light is on and only run the averaging if it was off and display real-time readings when it is on. The problem with this though is that when it switches from real-time to the average it starts at zero and works its way back up.

 

I'd like it to ideally use real readings for about 10 seconds after power up while at the same time accumulating readings for the average. Then after 10 seconds it would switch to using the average but it would have already accumulated enough readings to get the gauge to stay steady. Most cars do this - when in Park the gauge reads all over the place (if the car is moving and fuel is sloshing in the tank) but once you put it into gear the gauge implements some kind of smoothing or averaging, but it doesn't start from zero and then work its way up.

 

A member over on the Arduino forums suggested this:

Use millis() and a 'flag'.

When the flag = 0, use the initial value you get from wherever.

 

When millis() is > your startTime - add startTime = millis(); at the end of setup() - then make the flag = 1 and start using real numbers.

The only problem is I've got no idea how to implement that in my code. I've searched for examples using millis() but all I can find is basic timer and/or stopwatch code and I don't know how to modify/adapt that to work with my situation. Thanks in advance!

Attachments:
fuel_gauge.ino.zip
  • Sign in to reply
  • Cancel

Top Replies

  • Former Member
    Former Member over 10 years ago +1
    /* *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…
  • DAB
    DAB over 10 years ago in reply to SXRguyinMA +1
    I understand. A running filter will work at any update rate. You just set the initial value as average and then calculate the difference of the next reading from the average. After than you just establish…
  • Former Member
    Former Member over 10 years ago +1
    Sure thing Will, If I understand DAB's post correctly then I added a running filter. If you look at the differences between your original code and my modification you will see: (Starting at the end) I…
  • DAB
    DAB over 10 years ago

    A trick I used long ago was to do a pre-read value into the average and then use a running filter so that you always had a rough initial value that would correct over time.

     

    With most real time systems, you want them to be stable from the beginning without needing complex logic to make your decisions.

     

    It all depends upon the response time you want for the gages.

     

    DAB

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • SXRguyinMA
    SXRguyinMA over 10 years ago in reply to DAB

    Well I want the response time slow (like a car) so that it's not bouncing all over the place. Having an initial value raises the problem of a quick "key-on" to see the fuel level without having to sit there and wait. I wonder how setting an arbitrary initial value would affect the on-going averaging. How owuld I implement that to give it a shot?

     

    If I could have it use real-time readings for the first 10 seconds after power-on while at the same time accumulating readings to build up the average table then after 10 seconds switch to only the average table it'd be perfect.

     

    Here's a video of how it works currently: https://goo.gl/photos/Mx5LCCY2TSy4D3YC8

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • DAB
    DAB over 10 years ago in reply to SXRguyinMA

    If you use a running filter, it will quickly converge on the ambient reading.

    If you need it more responsive, then you should increase your sampling and update rate.

     

    Look at your flow rate.  If it is slow, then your current setting is OK.

    If it is fast, then you need a faster response time to prevent overflow conditions.

     

    DAB

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • SXRguyinMA
    SXRguyinMA over 10 years ago in reply to DAB

    I think you're missing the idea. I want it to run this slow normally. But when it first powers on I want it to be instant. I can make that happen. The problem is when it switches from instant to slow the gauge goes back to empty as it needs to accumulate readings for the average. I want it to read real-time for about the first 10 seconds while it's also accumulating readings for the average, then after 10 seconds use the average for the display.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Former Member
    Former Member over 10 years ago in reply to SXRguyinMA

    It shouldn't be to hard to run the averaging whilst displaying the real values until you have filled the buffer, but it would be more elegant to average the readings that you have until you have filled the buffer.

     

    if you keep the const int numReadings as a maximum value but add a variable that keeps track of how many readings you have taken (starts at 0 and increments by 1 until capping at a maximum value (as set in numReadings)) then you can use the incremental value as the divisor for calculating the average.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Former Member
    Former Member over 10 years ago

    /*

    *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 the fuel level gauge

    int readIndex = 0;              // the index of the current reading

    int total = 0;                  // the running total

    int average = 0;                // the average

    int averagingCount = 0;                     // checks the number of values in the Index

     

    void setup() {

      for (int thisLed = 0; thisLed < ledCount; thisLed++) {  // loop over the pin array and set them all to output:

        pinMode(ledPins[thisLed], OUTPUT);

      }

      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

      }

      averagingCount = averagingCount + 1;                  // increments the count for averaging

      if (averagingCount >= numReadings) {             // caps the averaging count to the array

        averagingCount = numReadings;                           

      }

      average = total / averagingCount;              // calculate the average

      delay(1000);                                // delay in between readings for stability

      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);

    }

    I hope this will work, I think it should.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • SXRguyinMA
    SXRguyinMA over 10 years ago in reply to Former Member

    PERFECT! Thank you! Now I just need to design a PCB and 3D print and enclosure then hook it all up so I can fine tune it but that's EXACTLY what I wanted. Thanks again!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • DAB
    DAB over 10 years ago in reply to SXRguyinMA

    I understand.

     

    A running filter will work at any update rate.

    You just set the initial value as average and then calculate the difference of the next reading from the average.

    After than you just establish how large a distance you need before you increment or decrement the average value.

    It is a simple technique to quickly establish a reliable value over time, regardless of the update cycle.

     

    DAB

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • SXRguyinMA
    SXRguyinMA over 10 years ago in reply to DAB

    Ah OK, now I understand, I apologize image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • SXRguyinMA
    SXRguyinMA over 10 years ago in reply to Former Member

    Hey Doug - could you explain what you did for me so I undestand it? Thanks!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube