EcoModder.com

EcoModder.com (https://ecomodder.com/forum/)
-   OpenGauge / MPGuino FE computer (https://ecomodder.com/forum/opengauge-mpguino-fe-computer.html)
-   -   t vago's MPGuino workspace thread (https://ecomodder.com/forum/showthread.php/t-vagos-mpguino-workspace-thread-26469.html)

t vago 07-24-2013 03:04 AM

t vago's MPGuino workspace thread
 
1 Attachment(s)
In the course of modifying the original MPGuino 0.86 code to incorporate the fuel injection correction factor for Chrysler vehicles with returnless fuel systems, I've been fiddling with the code, doing this and that and the other thing.

Since that other thread is really only meant for addressing that issue with Chrysler returnless fuel systems, it became increasingly apparent that a separate thread was needed to describe the other things I have done with the code. So, here it is. (All CPU workload figures assume a 20 MHz processor)

Hardware Support added (as of 10 December 2013):
  • Support for the Arduino Mega as a hardware platform. (via josemapiro)
  • Support for 5 different buttons via a single wire, while freeing up the TWI (Two-Wire Interface) pins for use for other functionality. (via nickdigger)
  • Support for the Parallax 5-position switch.
  • Support for the Parallax serial UART LCD module. (Minor changes had to be made to the spiffy big number font to enable it to work with the Parallax LCD module - these changes do not appear if the legacy MPGuino LCD display is used).
  • Chrysler returnless fuel injector correction factor, based off of intake manifold pressure. Utilizes existing manifold pressure (MAP) sensor built into the existing engine control system, but requires an additional barometric sensor (in other words, a spare/extra MAP sensor).
  • Support for the TinkerKit LCD hardware as a commercially-produced MPGuino module, with enhanced 5-button functionality (see above).

Program Features added (as of 20 May 2015):
  • Eliminated requirement to know or look up microseconds/(gallons or liters) from somewhere on the web. Ability to calculate microseconds/(gallons or liters). # of injectors, reference injector flow rate in mL/min, reference fuel pressure for reference flow rate, and system fuel pressure are used to determine microseconds per unit volume figure. This figure can then be tweaked as necessary, as before.
  • Addition of fuel cost, fuel remaining cost, fuel cost per unit distance, distance per unit fuel cost, and fuel cost rate calculations for instant, current, and tank trips.
  • Addition of Instant Trip Distance-To-Empty, Current Trip Distance-To-Empty, and Tank Trip Distance-To-Empty large number displays.
  • Addition of Instant Trip Time-To-Empty, Current Trip Time-To-Empty, and Tank Trip Time-To-Empty large number displays.
  • 2-second temporary Status Line now shows real-time updating of lower LCD data display
  • Tank and Current trip save/load/reset menu now adds shortcuts to their respective pages for easy pen-and-paper logging.
  • Display labels have been changed to be more descriptive, a la OBDuino.
  • Debounced buttons, with a "long-press" feature that effectively doubles the number of addressable button presses.
  • Interface routines now take advantage of the above button enhancement to provide safeguards, such as requiring "long-press" button combinations to reset current and tank trip. Parameter editing has been enhanced with the addition of parameter reversion, and the ability to cancel settings changes instead of saving them to EEPROM.
  • Button shortcuts are also possible. "Long-press" of the right button can now cause the value display to go directly to the instant fuel economy screen. "Long-press" of the center button now briefly shows the CPU loading for that page.
  • The settings interface has been enhanced to allow stepping back and forth between different parameters, without having to go through editing them.
  • Metric/US functionality has been more tightly integrated into the display coding. Parameters and parameter labels also reflect the metric parameter setting.
  • Leading spaces instead of zeros (of course).
  • 8 user-programmable display screens. Any combination of 4 instant, trip, or tank readings may be displayed on any of 8 screens. These combinations may be stored in EEPROM.
  • Bar graphs for differential fuel economy vs. time (a la ScanGauge E), fuel economy vs. time, fuel economy vs. speed, total (tank) time travelled vs. speed, total (tank) distance travelled vs. speed, and total (tank) fuel used vs. speed. Bar graphs are plotted graphically on-the-fly, vs. using a clunky custom font. 15 elements are supported. FE vs. time and dFE vs. time periods are selectable via a single EEPROM parameter. FE vs. speed, fuel rate vs. speed, distance traveled vs. speed, and time spent travelling vs. speed have two EEPROM parameters (lower speed cutoff which is set at a default of 25 MPH, and speed bar length which is set at a default of 5 MPH).
  • Spiffy large numbers have been added from the MPGuino Code Hacks wiki page.
  • System clock, which is used as a "screen saver" once inactivity timeout has been reached.
  • Saving of complete current trip or tank trip data, into one of 10 EEPROM slots. Ability to view raw trip data stored in EEPROM.
  • Time values now show hhmmss, where they used to show mmm.ss
  • Ability to select current trip reset upon wakeup due to running engine only, current trip reset upon wakeup due to button press only, current trip reset upon wakeup due to both running engine or button press, or disable current trip reset upon wakeup.

Technical Features added (as of 25 October 2013):
  • Interrupt driven, buffered LCD character output. The LCD buffer is processed through the freewheeling ADC interrupt handler, which now causes LCD character processing to be transparent to the display update loop.
  • Interrupt driven, buffered serial character output. Serial output is now transparent to the display update loop. Serial output can be enabled or disabled via a dedicated parameter, if desired.
  • 64-bit math routines are all written in bytecode that is interpreted by a 64-bit pseudoprocessor that I've named SWEET64. All of the 64-bit math routines have been shrunk by about 70%, compared to the original code.
  • CPU workload per display update loop is now between 3.4% and 26.2%.
  • Interface coding has been re-written so that any display mode (primary display, clock set, settings edit, parameter edit, trip save/retrieval, or trip raw data view) will reliably allow fuel readings to be collected and updated, and serial logging data to be output (if selected), regardless of mode. The inactivity timeout function also works, regardless of mode.
  • Parameters can now be variable length, whereas before they were all 32-bit numbers. Parameters may be sized from 1 bit to 32 bits in length. The parameter entry/editing routine enforces this specified length. The EEPROM routines have been modified to read and write these variable length parameters along byte boundaries.
  • Arrays, consisting of strings and characters and program pointers, have all been moved into Flash memory, as opposed to RAM. This has freed up some 200 bytes of RAM.
  • A 2 second window filter, which can be enabled via a dedicated parameter, has been added to the instant fuel economy readout. This has greatly reduced jitter associated with this readout.
  • Time-to-empty, distance-to-empty, and idle-time-to-empty values have been added. Engine speed (RPM) value has also been added.
  • The decimal number output function now uses SWEET64 to perform conversions from 64-bit numbers into strings. The function can output 0 through 3 decimal places (dependent on the value to be output). Distance and speed values now have one decimal place, and engine speed and remaining available RAM have no decimal places.
  • Fuel injector pulse measurement has been made more robust. Two separate rationality checks have been added.
  • Display routines re-written to separate low-level LCD hardware support from higher-level character output. This should make it easier to modify the code to support alternate display devices.

Features in progress (as of 18 Jan 2016):
  • Add user-definable support for two separate output pins, that can either drive LEDs or be used as a variable voltage source for external gauges. Currently adding hardware support for this feature.
  • Add alert displays for up to 4 different programmable monitored variables. Currently modifying display code to support this feature.
  • Two-Wire Interface support. The Arduino Wire module takes up too much space, and does not support interrupt-driven coding. A small buffer class has been formally defined, with support for interrupt-driven servicing routines. The buffered LCD and Serial output now use this class.
  • A-B comparison mode for saved trip/tank data, based off of fuel rate vs. speed graphs. Debugging of bar graph code is in progress.
  • Coastdown variable determination. Currently working on adding matrix math support into SWEET64.

Features to be added (as of 12 May 2014):
  • Addition of RTC support
  • Addition of vehicle battery voltage display
  • System date setting, in conjunction with system time
  • ?

The attached source code was developed to be copied and pasted into an Arduino 1.6.4 IDE window. Also, the code is configured to work on a JellyBeanDriver board - a 20 MHz AtMega328 with the traditional MPGuino 3 direct-wired pushbuttons and 2x16 character LCD screen. Make changes to the "#define" section, beginning at line 226, as needed.

If you use the AVR command-line tools, use these settings for setting the programmable fuses to ensure that your MPGuino will work:
Quote:

Originally Posted by Ettore_M (Post 504940)
lfuse:0xf7 hfuse:0xd9 efuse:0x07


Quezacotl 07-24-2013 03:49 AM

You have been busy :D
And i'm still struggling and trying to make flow-meter mode, voltage and some temperature reading features :)

But a feature request, in case you dont notice, make those alert displays that they can be enabled and disabled.

t vago 08-15-2013 02:25 PM

Okay...

I've been on vacation, but I am back now. Work continues on my code.

These features have been added:
  • Saving of complete current trip or tank trip data, into one of 6 EEPROM slots. Ability to view raw trip data stored in EEPROM.
  • Addition of Tank Trip Time-To-Empty large number display.
  • 8 user-programmable display screens. Any combination of 4 instant, trip, or tank readings may be displayed on any of 8 screens. These combinations may be stored in EEPROM.

This has been modified:
  • 64-bit math routines modified for speed. All formatted data is now calculated once per display loop.
  • CPU workload per update loop is now between 2.1% and 3.1%.
  • Display routines re-written to separate low-level LCD hardware support from higher-level character output. This should make it easier to modify the code to support alternate display devices.

The code is becoming a monster, though. It's at 20178 bytes, and shows no sign that it's going to stop growing any time soon.

nickdigger 08-15-2013 08:03 PM

Quote:

Originally Posted by t vago (Post 385408)
All formatted data is now calculated once per display loop.
CPU workload per update loop is now between 2.1% and 3.1%.

FWIW, i did the calc-data-once thing, hoping to save resources, but it ended up wasting program space (plus the extra ram for the variables), so i de-changed it

I've also gotten my cpu load down to 3-5% on a 4x20 LCD, just by tweaking the LCD routines to meet the spec. The killer is delay2 (5 milliseconds) in LcdCommandWrite. It only needs to be 120 microsec. That should eliminate the need for that buffer you added.

BTW, replacing "sei" with "sreg=OLDsreg", as you recommended in the Chrysler thread, seems to have stopped my weely T2-overflow crashes. Thanks again!

t vago 08-15-2013 08:59 PM

Quote:

Originally Posted by nickdigger (Post 385508)
FWIW, i did the calc-data-once thing, hoping to save resources, but it ended up wasting program space (plus the extra ram for the variables), so i de-changed it

Unfortunately, the calc-data-once code changes I made are a necessary part of being able to provide editable display screens. Without them, it becomes a nightmare of providing an array of class procedure pointers, with all of the fun that implies. :rolleyes:

My code was actually about the same size as the 0.86 code was, for a few weeks. It took adding the ability to save/load/view trip data in multiple EEPROM slots, and the actual screen editing code, to cause my code to bloat out. At that, most of the bloat is text strings.

Quote:

Originally Posted by nickdigger (Post 385508)
I've also gotten my cpu load down to 3-5% on a 4x20 LCD, just by tweaking the LCD routines to meet the spec. The killer is delay2 (5 milliseconds) in LcdCommandWrite. It only needs to be 120 microsec. That should eliminate the need for that buffer you added.

I never did really look into tuning the LCD hardware support. This would be worth a couple hundred bytes of program space, and about 100 bytes of RAM.

Quote:

Originally Posted by nickdigger (Post 385508)
BTW, replacing "sei" with "sreg=OLDsreg", as you recommended in the Chrysler thread, seems to have stopped my weely T2-overflow crashes. Thanks again!

No problemo. Nested interrupt bugs are a royal PITA to debug. The best way to debug them, IMO, is to prevent any possibility of having nested interrupts in the first place.

t vago 08-15-2013 11:35 PM

Quote:

Originally Posted by nickdigger (Post 385508)
I've also gotten my cpu load down to 3-5% on a 4x20 LCD, just by tweaking the LCD routines to meet the spec. The killer is delay2 (5 milliseconds) in LcdCommandWrite. It only needs to be 120 microsec. That should eliminate the need for that buffer you added.

I tried it just now, and the results were not very encouraging.

Buffered LCD code (approximately 1 ms per character):
CPU loading = 2.2%
Free Mem: 1044
Program Size: 20178

Bare LCD code (80 us per character):
CPU loading = 3.2%
Free Mem: 1172
Program Size: 20548

To be fair, the Bare LCD code did seem to be a bit more crisp in response, than the buffered code. However, it would not be that big of an advantage, compared to the fact that the code grew by 370 bytes, while only gaining 128 bytes of RAM. Ugh.

nickdigger 08-16-2013 10:38 PM

i can't see how adding buffer code takes less flash space than the standard routines. Just glancing at my .sym file, the total space used for all LCD functions is 448 bytes. Then again, i did optimize the fornication out of it, stealing Arduino library bits where needed, and dropping alot of overhead.

I'm also running on a 168, so ram is at a much higher premium for me. Probably not the case with your 328. I'm still trying to squeeze in SD logging (512 just for the buffer) along with my bar graph and speed range tabulator.

Also, by buffering the LCD output, aren't you really just hiding the true load, which could hit you on future addons?

t vago 08-17-2013 12:47 AM

Quote:

Originally Posted by nickdigger (Post 385729)
i can't see how adding buffer code takes less flash space than the standard routines. Just glancing at my .sym file, the total space used for all LCD functions is 448 bytes. Then again, i did optimize the fornication out of it, stealing Arduino library bits where needed, and dropping alot of overhead.

I can. My code does not use any sort of loop-based delay2() function, nor does it use any sort of microSeconds() function. When I attempted last night to completely remove the buffered feature, I had to add back in a delay2() and a microSeconds() and a microSecondsLength() function. That is what caused the bloat to occur.

I attempted again to remove the buffering earlier today, and only gained about 50 bytes. However, CPU utilization went way up, to around 20%, even with using the smallest possible delay with writing LCD bytes. No thanks.

My LCD code takes up 460 bytes, including the buffering.

Quote:

Originally Posted by nickdigger (Post 385729)
I'm also running on a 168, so ram is at a much higher premium for me. Probably not the case with your 328. I'm still trying to squeeze in SD logging (512 just for the buffer) along with my bar graph and speed range tabulator.

I have 1072 bytes of RAM free. I think I had about the same as was with the original 0.86 code. At one point, I had over 1300 bytes free.

Quote:

Originally Posted by nickdigger (Post 385729)
Also, by buffering the LCD output, aren't you really just hiding the true load, which could hit you on future addons?

Not really. Within each loop, all of the true processor-intensive things are done first. Calculating all 15 different output values across three different Trip class variables, windowing the instant.fuelEcon value to smooth out loop variations that occur due to the engine controller doing its OBDII cat monitor/O2 refresh thing, and sending out the serial raw logging data (which is also buffered) - these things really do not take up much time at all (about 2.2% per loop). Formatting and buffering the output values, as needed, takes an additional amount of time - anywhere from 1% to 6%. That amount of time is highly dependent on the particular screen being displayed.

The "true load", as regards outputting LCD characters, consists of waiting. If the code is waiting, then the code is not really doing anything useful.

After all of that is done, the program patiently just sits there and waits for a button press, or for the loop to end. I figure, since the program is anyway not doing anything meaningful during that time, it can process the buffering.

I'm strongly tempted to use the timer2 overflow interrupt handler to handle processing the LCD and serial buffers. If the overflow handler would process the buffer, then there'd be no need at all to worry about CPU loading due to outputting.

nickdigger 08-17-2013 02:24 AM

Quote:

Originally Posted by t vago (Post 385750)
I can. My code does not use any sort of loop-based delay2() function, nor does it use any sort of microSeconds() function. When I attempted last night to completely remove the buffered feature, I had to add back in a delay2() and a microSeconds() and a microSecondsLength() function. That is what caused the bloat to occur.

Mine uses delay_us (20 bytes) and delay_ms (48 bytes), which calls milliseconds (48 bytes). Now that i look at it, i will probably merge milliseconds() into delay_ms(), since it basically just returns the timer count, and it is only ever called by delay_ms. (Edit: so far, no good. It's "so efficient" that the compiler wants to inline the new delay_ticks everywhere, costing me 300 extra bytes)

Quote:

I'm strongly tempted to use the timer2 overflow interrupt handler to handle processing the LCD and serial buffers.
I had assumed you were already doing something like that. It might be trivial to add another "event" chain to the handler, for each output.

nickdigger 08-17-2013 02:30 AM

This all makes me wonder if a multi-threading scheme could be based on the avr timers. I'll have to think about that some more later.


All times are GMT -4. The time now is 11:01 PM.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Content Relevant URLs by vBSEO 3.5.2
All content copyright EcoModder.com