Fuelly Forums

Fuelly Forums (https://www.fuelly.com/forums/)
-   Experiments, Modifications and DIY (https://www.fuelly.com/forums/f9/)
-   -   diy mpg gauge (https://www.fuelly.com/forums/f9/diy-mpg-gauge-5319.html)

skewbe 07-08-2007 08:16 AM

diy mpg gauge
 
Update, skip ahead to a working model:
https://www.gassavers.org/showthread....32#post6473232


It seems a simple enough task, take a vehicle speed sensor "reading" and divide it by the injector duty cycle and put it on a meter. In fact my el-cheapo tach/dwell meter has both circuits in it (and a meter) and could be made to reflect vehicle speed (perhaps with an op amp on the vss) or injector duty cycle (which probably isn't much more than an inductor). Throw in some pots for calibration and an op amp to combine the signals and...

So has anyone come up with a simple mpg gauge circuit for the masses? I suppose digital would be better (i.e. keep track of every duty cycle for every vss pulse and add a "trip" type function to it), but I kind of like the "gomi"-ness of dissecting my old tach/dwell meter and making an mpg gauge out of it ;)

Thoughts?

P.S. Scangauge is in my wifes hands and I don't have another $160, that's why I'm considering this :o , though something for the DIY sector would be useful.

MnFocus 07-08-2007 09:06 AM

Came across a link on pg 4 & 5 has the circuit diagrams(originally posted by retrorocket) . It appears to use a sunpro tach . Add a vaccum gauge along with some fabbing skill you *might* save a few dollars .

skewbe 07-08-2007 09:32 AM

Yah, that would be an obd approach, I was thinking analog stuff (and about $5 in parts added to my extremely simplistic sunpro dwell/tach). Mebbe those days are gone?

MnFocus 07-08-2007 09:43 AM

Didn't SVOboy(I think it was anyway) do a fuel gauge with a dwell tach ? I'd be willing to bet that the same thing *can* be done the way you described . You just need to take the time to get the calibrations down .

landspeed 07-08-2007 11:22 AM

The cheapest way to do it would be to...

(1) Get an Atmel processor, and programming kit from ebay. Get the flash-reprogrammable processor, so you can experiment.
(2) Find some code + circuit diagram for wiring it to a calculator screen (8-digit LCD)
(3) Connect it to the Auto power supply (using the info in that PDF). Use code to simply read the injector pulse duration, and the vehicle speed sensor reading.
(4) Have one or two buttons on it. You could make a simple user interface, so you can 'reset' the 'TANK' when you refill, and reset the 'journey' each time you make a journey. Display instant MPG on the left of the calc display, and tank/journey MPG on the right hand side!

This is the basic idea behind the SuperMID, except that a lot more work has gone into it, in particular in interfacing it to a much more complicated display.

thisisntjared 07-08-2007 05:43 PM

Quote:

Originally Posted by landspeed (Post 62513)
The cheapest way to do it would be to...

(1) Get an Atmel processor, and programming kit from ebay. Get the flash-reprogrammable processor, so you can experiment.
(2) Find some code + circuit diagram for wiring it to a calculator screen (8-digit LCD)
(3) Connect it to the Auto power supply (using the info in that PDF). Use code to simply read the injector pulse duration, and the vehicle speed sensor reading.
(4) Have one or two buttons on it. You could make a simple user interface, so you can 'reset' the 'TANK' when you refill, and reset the 'journey' each time you make a journey. Display instant MPG on the left of the calc display, and tank/journey MPG on the right hand side!

This is the basic idea behind the SuperMID, except that a lot more work has gone into it, in particular in interfacing it to a much more complicated display.

so how much do you think that will run??? if its less than $50 i might just have to try it...

sonyhome 07-08-2007 09:17 PM

Looking at the Mnfocus linky, I'd say the design could be simplified for a laptop:

There's 1 signal line from the ODB-2 picked up. Just pass it on to a laptop's serial port and have a program scan that serial port and do the computation, logging, and display.

That way it's ALL SOFTWARE, with $2 worth of parts. May need a pull down 12V->5V resistor bridge, or at worst an op-amp to decouple it all.

Just need a guy who knows how to code with visual basic or visual C a serial port reader...

If you wanna do it digital, replace their analog display with a cheap LCD bar display.

skewbe 07-08-2007 10:24 PM

Yah, the laptop->obd route is a well traveled path. Problem is obdii is a hodgepodge of protocols, and laptops aren't exactly cheap.

Also, I'm not ready to sort out PICs and deal with programmer compatabilities,specs,etc.


However, there may still be a dirt cheap option for iso, an old blackberry 957 perhaps (or mebbe a serial based palm) and something to convert 5v<->12v. In that way it is relatively easy to program/reprogram and comes with a display,input system, and a serial port based on the windows iso stuff:
https://www.andywhittaker.com/ECU/OBD...9/Default.aspx
BUT, it ony works with iso vehicles.



Here is another laptop idea, tap into the vss and injector pulses via the line-in right and left channels on the sound card and sort it out from there. They are basicaly A/D converters.

sonyhome 07-09-2007 12:13 AM

Most people have laptops nowadays, and all have serial ports.

If there's an explanation of what to monitor on the ODB-2, then a simple program can be made, which then will be ported etc.

I'll ask a friend when I have a chance if he knows free PC software to monitor ODB2... Maybe we can find a free one that does the trick or can be modded for FE analysis.

Google Examples:

https://www.er-forum.de/obd-diag-dl
But it needs:
https://www.obdpros.com

https://jdash.ludicrous-speed.com/wik....php/Main_Page
https://www.tactrix.com/

https://www.scantool.net/?mode=displa...rd&#37;20Party

A good explanation:

https://www.thinkythings.org/obdii/

landspeed 07-09-2007 03:21 AM

Quote:

Originally Posted by thisisntjared (Post 62562)
so how much do you think that will run??? if its less than $50 i might just have to try it...

No idea, but, I know I could get the raw materials for $50 if I look around on ebay + other places. LCD screens seem quite expensive, but, if you find somewhere that sells simple calculator ones, it should be pretty cheap.

landspeed 07-09-2007 03:25 AM

Quote:

Originally Posted by skewbe (Post 62602)
Yah, the laptop->

Here is another laptop idea, tap into the vss and injector pulses via the line-in right and left channels on the sound card and sort it out from there. They are basicaly A/D converters.

I've thought of this and looked it up - you would need to make circuits to protect the laptop soundcard, especially as injector pulses can hit +50/+100v due to inductive effects when the power supply is cut off (at the end of the injector pulse).

I found somewhere, a USB device that had about 16 A-D convertors and D-A convertors too. It was about $150 though. Shortly after this I found the SuperMID on this site (in fact, it was research into homebrew MPG gauges that led me to this site!)

skewbe 07-09-2007 05:07 AM

2 Attachment(s)
Quote:

Originally Posted by landspeed (Post 62610)
I've thought of this and looked it up - you would need to make circuits to protect the laptop soundcard, especially as injector pulses can hit +50/+100v due to inductive effects when the power supply is cut off (at the end of the injector pulse).

Yah, worth mentioning, don't want people frying their line in ports.

I would think taking the signal from a pair of diodes in parallel, which are in series with a largish value resistor which leads to , oh nevermind, let me draw a picture :) Were talking pennies worth of parts to limit (clamp) the voltage to .7 volts.

https://www.gassavers.org/attachment....1&d=1183986302

I've got some old assembler routines I wrote for high resolution recording in dos (windows recording always make skips), I can dredge those up, mebbe a linux port would be in order.

I think we have enough info for a laptop based mpg/mph/trip/and rpm program, once you tell it some info about your car like:
1. how many vss pulses per wheel rotation
2. how many injectors
3. how many cylinders (if it is tbi)

but dang if a laptop isn't a lot of luggage for an mpg gauge :(

skewbe 07-09-2007 05:29 AM

Quote:

Originally Posted by sonyhome (Post 62606)
Most people have laptops nowadays, and all have serial ports.

If there's an explanation of what to monitor on the ODB-2, then a simple program can be made, which then will be ported etc.

Yah, it isn't that simple. there are many OBDII protocols, only iso (asian cars)can be handled by the laptops serial uart chip with only the scantiest of circuitry, and less and less laptops have such a serial port available. The other protocols take $100 adapters (and you might as well get a scangauge/supermid at that point).

I'm looking for cheap and simple, that can be adapted to any electronic fi car (regardless of obd status) using surplus parts/etc.

jwxr7 07-09-2007 07:35 AM

Quote:

I'm looking for cheap and simple, that can be adapted to any electronic fi car (regardless of obd status) using surplus parts/etc.
I was just talking with the guys at work about doing something similar to that. Goal was As long as the vehicle has a vss and efi the gauge will work. Just have to do some calibrations for fuel use. I just want a DIY route for my 94 metro since it is all DIY so far :) + I'm cheap. The scangauge I bought should offer enough to be worthwhile on my newer gas hogs :o .

skewbe 07-09-2007 08:10 AM

a vss is easy to fabricate if the car doesn't have one, basically zip-tie a small magnet to a drive shaft or axle and bracket up a coil to pick it up.

Some cars will have one for a cruise control even if it isn't an obd car.

VXrunner 07-10-2007 12:13 PM

I'd love to see what you come up with, as i would like to make one for my 94 VX...

sonyhome 07-10-2007 12:37 PM

Let's recap, assuming you don't want to tap the ODB2 codes (would work for all cars!):

For MPG you need actual distance and gas consumption (duh!)

- distance: count wheel axle rotations

Count rotations R with a magnet or an optical reader
Calibration: multiply count by the circumference Ctire of the tire in inches. That's easy to get with a chalk mark on the tire.

D = R * Ctire /63360

- gas consumption: collect duty cycle of injectors

Can we track it by monitoring the duration of the electromagnetic pulse on the injector electric wires somehow? Maybe with a pickup from the speaker of
an old walkman headset taped to an injector wire? Else tap the wire directly to measure voltage shifts.

Calibration: Need the max volume of gas Vmax the injector can feed divided by the max duty cycle DCmax. Those parameters are probably known by the racers.

V = Vmax * DC/DCmax

Bill in Houston 07-10-2007 01:03 PM

In a way, you're making it too tough. You really just work off a couple of assumptions. 1- injector pulse width is proportional to fuel flow 2- number of pulses from the vehicle speed thingy is proportional to speed. And then, you just lay a constant on top of it.

Instant MPG = A constant * speed / flow

Less elegant than your idea, though. :-)

skewbe 07-10-2007 01:36 PM

Quote:

Originally Posted by sonyhome (Post 62894)
...assuming you don't want to tap the ODB2 codes (would work for all cars!):

that is incorrect, not all cars by a long shot. It won't work on pre-96, didn't even work on my 97 until I swapped ECU's (car worked fine though), it didn't work on my neighbors car. It's ugly too as it is several protocals under one name, some needing more circuitry than others. Check it out.

Having a layer of ECU and whatnot between the mpg gauge and the actual sensors also means a lot more can (and will) go wrong, in my experience.

Note, however, my metro uses ISO (I'm using an OBDII specific term here, so be careful), and you can use a standard serial port (found on older laptops and even old blackberries/palm pilots) with ISO for a few transistors, i.e.: https://prj.perquin.com/obdii/ So there may be an old palm pilot gorilla glued to my dashboard in the not too distant future anyway :)

skewbe 07-10-2007 07:38 PM

revisiting the analog stuff
 
2 Attachment(s)
so rethinking the analog stuff and reusing a tach dwell as a mpg gauge, I found this reference about using op amps to divide.
https://www.national.com/an/AN/AN-30.pdf


So we would use the rpm circuit to create a voltage proportional to the speed (like the rpm circuit does already to drive the meter, only it is connected to an amplified vss signal), and take the dwell circuit to create another voltage (like the dwell circuit does to drive the meter, only it is hooked up to an injector instead of a coil) and divide the speed voltage (E1) by the injector duty cycle voltage (E2) using op amps in a logarithmic mode with a fudge multiplier (calibrator) on E3. Easy cheesey, right? :)

https://www.gassavers.org/attachment....1&d=1184124933

skewbe 07-10-2007 09:04 PM

more analog
 
2 Attachment(s)
and if you are wondering what tach and dwell circuits might look like:

https://www.gassavers.org/attachment....1&d=1184130175
from: https://www.4qdtec.com/Automob/TachDwell.html

skewbe 07-15-2007 01:27 PM

status
 
I'm realizing that this isn't quite a comprehensive DIY article yet, I'll have to clean it up when I get something working.

Status, instant mpg isn't nearly as good as a short term average, so I'm shying away from the analog/tach dwell approach.

I was going to persue obdII/ISO after assembling a real trivial circuit. BUT the scangauge stopped working on the saturn (AGAIN?!?) so I need a non obd solution for that car as the scangauge is back in the metro.

So currently I'm trying to load up Visual C++ 6.0 on an old win 98 laptop that has a line-in jack and will try and modify some simple windows based oscilloscope source I found to keep track of how long the injectors have been open and how many clicks we've travelled. It may miss a few beats under windows, but it should be close enough (and provide a reasonable platform for keeping other useful apps on, i.e. some maps and whatnot)

thisisntjared 07-15-2007 03:04 PM

Quote:

Originally Posted by skewbe (Post 63755)
Status, instant mpg isn't nearly as good as a short term average, so I'm shying away from the analog/tach dwell approach.

i agree, as long as it is accurate.

keep us updated on the progress :):thumbup:

MetroMPG 07-15-2007 06:02 PM

Forgive my ignorance, but would a Basic Stamp be a good platform for a DIY FE gauge? Anyone know about these?

skewbe 07-15-2007 06:27 PM

A more hardcore embedded person would do it with a handful of counters and a PIC (i.e. basic stamp) and have a standalone device. But the problem becomes the fact that they have to put more complicated circuts together and purchase a special programmer to load the BASIC (or C++ or assembler or whatever) program onto the chip and learn how to operate the programmer, or someone has to sell chips to the "Do It yourselfers".

I see a lot of utility in having a full fledged computer handy though, play mp3 files, talk to your lan from your driveway, run maps/whatever. All my portable computers can run on 12 volts directly (no accident). I've even got a ramline 510 touchscreen (used to be in a cop car) that needs to find a second life which would be ideal for this. But the ramline is a PITA to develop on (as are embedded chips), which may be my real motivation for this approach :)

skewbe 07-15-2007 06:50 PM

Ooh yah, and a with a well positioned display you can plug in a $20 web cam that is pointing backwards and shave off those mirrors :)

sonyhome 07-15-2007 09:51 PM

LOL!

So back to an OBD solution then, instead of tapping the injector's duty cycle directly?

Too bad for my '93 OBD-1...

This ALDLcable store sells cables using these schematics except it's voltage adaptation uses a cig. lighter, instead of hacking the DTR line (pin 4 of the serial port):

https://winaldl.joby.se/interface.gif

They sell a $10 OBD2-Serial cable:
OBD2-serial cable

They also list a bunch of freeware used to monitor OBD data.

Quote:

Useful links for diagnostic and tuning software:

TTS Datamaster - https://www.ttspowersystems.com/DataM...downloads.html
WinALDL - https://winaldl.joby.se/
EFILive - https://store.efilive.com/download.aspx#downloads3
TunerPro - https://www.tunerpro.net/
TunerCat - https://www.tunercat.com/
FreeScan - https://andywhittaker.com/ECU/FreeSca...0/Default.aspx
CarBytes - https://store.efilive.com/download.aspx#utilties
Moates Free GMECM - https://www.moates.net/gmecm/software.html
ALDL_LOG - https://www.lotus-carlton.fsnet.co.uk/aldl_basics.htm
Pontiac-interface.de - https://www.pontiac-interface.de/
ALDMON for 1227727 and 1227730 - pweb.de.uu.net/pr-meyer.h/aldl.htm
EASE Diagnostics - https://www.easesim.com/
Diacom Plus - https://www.rinda.com/auto/auto.htm
PCMComm 16188051 - https://www.geocities.com/MotorCity/S...24/95cam2.html
ElanScan - https://members.lycos.co.uk/mcnica01/M100_ALDL.html
LT1-Edit - https://www.carputing.com/
GM 6.5 Turbo Diesel Scan- https://www.enghmotors.com/basic/default.aspx

Driver software for our USB cables:

VCP Drivers - https://www.ftdichip.com/Drivers/VCP.htm

OBDII software for our ELM327 based OBD2 allinone scan tool:

OBD2allinone - https://www.obd2allinone.com/sc/pages.asp?pageid=60
Othe OBD-1 links:

https://cable.invisibill.net (schematics, used on datamaster, freescan, winaldl)

skewbe 07-16-2007 02:08 AM

Quote:

Originally Posted by sonyhome (Post 63841)
LOL!

So back to an OBD solution then, instead of tapping the injector's duty cycle directly?

Too bad for my '93 OBD-1...

I'm NOT currently planning on doing OBD, it won't help me as my saturn is not happy with OBD MPG attempts, for whatever reason, and I'd like to get something out of my efforts.

I'm planning on the audio approach on a laptop for ease of implementation and more universal application. Any any car with electronic FI should work. One just need a laptop with a Line-In to run the mpg program on and a simple circuit to limit the voltage going in.

skewbe 07-20-2007 11:28 PM

1998 geo metro TBI injector pulse analysis:
 
6 Attachment(s)
44100/8 bit/mono recording using a diode clamp interface and a 10k resistor on a 133mhz laptop with integral sound card via line in left channel . Car in neutral in driveway. Probe connected to yellow wire between fuel injector resistor and fuel injector.

3 samples, 1 low rpm, 1 accalerating to higher rpm, 1 high rpm. Images stretched horizontally for easier duty cycle visualization/comparison.

https://www.gassavers.org/attachment....1&d=1185002121
steadyish @ ~1200
period 1714 bytes
pulse width 119 bytes
duty cycle 0.0694


https://www.gassavers.org/attachment....1&d=1185002139
just starting to ramp up on the way to 2000rpm in neutral
period 1273 bytes
pulse width 137 bytes
duty cycle 0.1076


https://www.gassavers.org/attachment....1&d=1185002153
steadyish @ ~2000rpm
period 833 bytes
pulse width 73 bytes
duty cycle 0.0876
(duty cycle increased for higher rpm and throttle setting.

sanity checks:
(3 pulses/2 revolutions)*2000 rpm=3000 injector pulses/minute = 50 pulses/second
44100/833 = 52.94 pulses/second. Enh, close enough for a single wave analysis.

accelerating had the largest duty cycle (most time spent squirting fuel)

hi rpm has a proportionally larger duty cycle than low rpm.

833 byte sized samples @ 2000 rpm equates to a potential 99.75&#37; accuracy at 4000rpm

Note: this signal doesn't look very clamped to me, maybe 10k is too much or my diodes fried. Agc is having fun with the signal too.

skewbe 07-21-2007 04:59 AM

Here's the actual recording
 
2 Attachment(s)
for the above images. It was a raw wav, so I could pipe it through a program for development, but it is here converted to mpeg 3 compression for space considerations. Recorded with windows sound recorder and subsequently compressed with sound recorder.

if you run it in windows media player, set the visualizations to "scope" by:
views->visualizations->bars and waves->scope

OOPS, this is the recording of the wrong channel!! The other side records a bit cleaner. :o I sure hope there isn't this much crosstalk when the other channel is plugged into the VSS.

sonyhome 07-21-2007 12:12 PM

Pretty cool ... but I don't quite understand your diode clamp interface you used.

Could you explain how you make it work?

You connected directly to the injector via a 10K resistor?
And then you grounded the signal via a diode bridge? Is that to avoid having signals above 0.6V? Don't understand...

And what's VSS for?

I though you'd use a coil to detect the pulses so the laptop would be totally independant from the car's electrical circuit...

All you have to do now to compute duty cycle is count the number of samples above a threshold vs all the samples.
You may need to adjust with a constant, or adjusting the threshold since the ramp up slope is not vertical, but seems constant.

skewbe 07-22-2007 12:40 AM

We have gui
 
4 Attachment(s)
Tada!!, it's somewhere in the ballpark for a 98'tro!! Now anyone who has a laptop or tablet in their car can monitor MPG

***you need to be logged in to see the pictures,
You can go here to see the pictures without logging in:
https://opengauge.org/diympggauge/
***
https://www.gassavers.org/attachment....1&d=1185090285
*tank will persist when window is closed


Using this circuit, with right and left switched :rolleyes:
https://www.gassavers.org/attachment....1&d=1183986302


Zoom in on recording of line in (44100 8 bit stereo) for anylizing the waveform (vss* on top, injector on bottom) and general futzing in response. I don't think the diodes are doing much on the vss side :eek:
https://www.gassavers.org/attachment....1&d=1185091266
*Yellow line is default threshold for the vss,
*Cyan "..." injector
*I adapted the code to the latest wave form (inj pulse was on other channel and right side up?!?)
*vss is the misnamed Vehicle Speed Sensor. It really only measures distance. The computer watching the vss still has to keep track of time to figure out the velocity.



Speaking of code, here it is in it's entirety, 6 drama filled pages to chew on in one file called Mpg.java :
Code:

import java.awt.Color;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.NumberFormat;
import java.util.Properties;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.TargetDataLine;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Mpg extends Thread {
        static String propFile = "./mpg.properties";        // place to persist confguration and trips.
                                                                                                //Will be created on first run if it doesnt exist.

        static int injThreshold = Integer
                        .parseInt(getProperty("injThreshold", "-30")); // value above the noise

        static int vssThreshold = Integer
                        .parseInt(getProperty("vssThreshold", "100")); // value above the noise

        static double distanceFudge = Double.parseDouble(getProperty("distanceFudge", "3200.0"));

        static double fuelFudge = Double.parseDouble(getProperty("fuelFudge",        "8000000.00"));

        static String dummyFile = getProperty("dummyFile", "");

        // low level stats tracked in the "trip" class.
        class Trip {
                String name;

                long sampleCount; // num samples, used to compute elapsed time, good
                                                        // for about 58 billion hours @ 44100hz

                long injHi; // stores number of samples that were "HI" (injector was
                                        // open)

                long vssTot; // how many pulses from the vss, indication of distance
                                                // travelled

                public Trip(String _name) {
                        name = _name;
                }

                // real lightweight update process, gets called at end of audio chunk
                public void Update(long _sampleCount, long _injHi, long _vssTot) {
                        sampleCount += _sampleCount;
                        injHi += _injHi;
                        vssTot += _vssTot;
                }

                public String toString() {
                        return "name=" + name + ";sampleCount=" + sampleCount + ";injHi="
                                        + injHi + ";vssTot=" + vssTot;
                }

                public void reset() {
                        sampleCount = 0;
                        injHi = 0;
                        vssTot = 0;
                }

                public Trip load() {
                        sampleCount = Long
                                        .parseLong(getProperty(name + ".sampleCount", "0"));
                        injHi = Long.parseLong(getProperty(name + ".injHi", "0"));
                        vssTot = Long.parseLong(getProperty(name + ".vssTot", "0"));
                        return this;
                }

                public void save() {
                        properties.put(name + ".sampleCount", "" + sampleCount);
                        properties.put(name + ".injHi", "" + injHi);
                        properties.put(name + ".vssTot", "" + vssTot);
                }

                public double miles() {
                        return (double) vssTot / distanceFudge;
                }

                public double hours() {
                        return ((double) sampleCount) / (44100.0D * 3600.0D);
                }

                public double gallons() {
                        return (double) injHi / fuelFudge;
                }

                public double mpg() {
                        return gallons() > 0.0D ? (miles() / gallons())
                                        : Double.POSITIVE_INFINITY;
                }
        }

        class TripPanel extends JPanel {
                Trip trip = null;

                JLabel name = new JLabel("name");

                JLabel miles = new JLabel("miles");

                JLabel gallons = new JLabel("gallons");

                JLabel mpg = new JLabel("mpg");

                JLabel hours = new JLabel("gallons");

                JLabel mph = new JLabel("mph");

                JButton reset = new JButton("reset");

                /** used for limiting numbers to 4 decimal places*/
                NumberFormat fm = NumberFormat.getNumberInstance();

                public TripPanel(Trip _trip) {
                        trip = _trip;
                        setLayout(new GridLayout(1, 8));
                        setBorder(BorderFactory.createLineBorder(Color.BLACK));
                        add(name);
                        add(miles);
                        add(gallons);
                        add(mpg);
                        add(hours);
                        add(mph);
                        add(reset);
                        reset.addActionListener(new ActionListener() {
                                public void actionPerformed(ActionEvent e) {
                                        trip.reset();
                                }
                        });
                        fm.setMaximumFractionDigits(4);
                }

                public void upDateLabels() {
                        name.setText(" " + trip.name);
                        miles.setText(fm.format(trip.miles()));
                        gallons.setText(fm.format(trip.gallons()));
                        mpg.setText(fm.format(trip.mpg()));
                        hours.setText(fm.format(trip.hours()));
                        mph.setText(fm.format(trip.miles() / trip.hours()));
                }

        }

        private TargetDataLine m_line;

        protected boolean m_bRecording = true;

        Trip instant = new Trip("instant");

        TripPanel instantPanel = new TripPanel(instant);

        Trip current = new Trip("current");

        TripPanel currentPanel = new TripPanel(current);

        Trip tank = new Trip("tank").load();

        TripPanel tankPanel = new TripPanel(tank);

        public Mpg(TargetDataLine line, AudioFileFormat.Type targetType) {
                m_line = line;

                new Thread(new Runnable() {// thread to update the view every second
                                        public void run() {
                                                while (m_bRecording) {
                                                        instantPanel.upDateLabels();
                                                        instant.reset();// reset the instant trip after
                                                                                        // displaying it
                                                        currentPanel.upDateLabels();
                                                        tankPanel.upDateLabels();
                                                        try {
                                                                Thread.sleep(1000);
                                                        } catch (Exception e) {
                                                        }
                                                }
                                        }
                                }).start();

        }

        public void start() {
                m_line.start();
                super.start();
        }

        public void stopRecording() {
                m_line.stop();
                m_line.close();
                m_bRecording = false;
                System.out.println(" inj sampleCount = " + current.sampleCount
                                + " inj hi = " + current.injHi + " inj vssTot = "
                                + current.vssTot);
        }

        boolean ig = true;

        boolean vg = true;

        void processChunk(byte[] b, int c) {
                long ih = 0;
                long vt = 0;

                for (int x = 0; x < c; x += 2) {
                        int val = ((int) b[x] & 255) - 127;
                        if (val > vssThreshold && vg) {
                                vt++;
                                System.out.println(" vss going hi "
                                                + (current.sampleCount + (x / 2)));
                                vg = false;
                        }
                        if (val < 0) {
                                vg = true;
                        }

                        val = ((int) b[x + 1] & 255) - 127;
                        if (val < injThreshold) {
                                ig = true;
                        }
                        if (val > 0)
                                ig = false;
                        if (ig)
                                ih++;
                }
                instant.Update(c / 2, ih, vt);
                current.Update(c / 2, ih, vt);
                tank.Update(c / 2, ih, vt);
        }

        public void realrun() {
                byte[] buffer = new byte[m_line.getBufferSize()];
                while (m_bRecording) {
                        int c = m_line.read(buffer, 0, m_line.available());
                        if (c != 0) {
                                processChunk(buffer, c);
                        }
                }
        }

        public void run() {
                if ("".equals(dummyFile))
                        realrun();
                else
                        dummyrun();
        }

        public void dummyrun() {
                try {
                        String strFilename = dummyFile;
                        File soundFile = new File(strFilename);
                        AudioInputStream audioInputStream = null;
                        audioInputStream = AudioSystem.getAudioInputStream(soundFile);

                        int nBytesRead = 0;
                        byte[] abData = new byte[44100];
                        while (nBytesRead != -1) {
                                nBytesRead = audioInputStream.read(abData, 0, abData.length);
                                if (nBytesRead >= 0) {
                                        processChunk(abData, nBytesRead);
                                }
                                try {
                                        Thread.sleep(1000);
                                } catch (Exception e) {
                                }
                        }
                } catch (Exception e) {
                        e.printStackTrace();
                }
        }

        public static void main(String[] args) throws Exception {

                AudioFormat audioFormat = new AudioFormat(
                                AudioFormat.Encoding.PCM_SIGNED, 44100.0F, 8, 2, 2, 44100.0F,
                                false);
                DataLine.Info info = new DataLine.Info(TargetDataLine.class,
                                audioFormat);
                TargetDataLine targetDataLine = null;
                targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
                targetDataLine.open(audioFormat);
                AudioFileFormat.Type targetType = AudioFileFormat.Type.WAVE;

                final Mpg recorder = new Mpg(targetDataLine, targetType);
                JFrame j = new JFrame("MPG Monitor!!!");
                j.setSize(640, 125);
                Container c = j.getContentPane();
                c.setLayout(new GridLayout(4, 1));

                JPanel hd = new JPanel();
                hd.setLayout(new GridLayout(1, 8));
                hd.add(new JLabel(""));
                hd.add(new JLabel("MILES"));
                hd.add(new JLabel("GAL"));
                hd.add(new JLabel("MPG"));
                hd.add(new JLabel("HRS"));
                hd.add(new JLabel("MPH"));
                hd.add(new JLabel(""));

                c.add(hd);
                c.add(recorder.instantPanel);
                c.add(recorder.currentPanel);
                c.add(recorder.tankPanel);

                j.addWindowListener(new WindowAdapter() {
                        public void windowClosing(WindowEvent e) {
                                recorder.stopRecording();
                                recorder.tank.save();//this just adds the trip fields to the properties object
                                try {
                                        properties.store(new FileOutputStream(new File(propFile)),"");
                                } catch (Exception f) {
                                }
                                System.exit(0);
                        }
                });

                j.setVisible(true);
                recorder.start();

        }

        static Properties properties;

        static String getProperty(String tag, String dflt) {
                String s = "";

                try {
                        if (properties == null) {
                                properties = new Properties();
                                try {
                                        properties.load(new FileInputStream(new File(propFile)));
                                } catch (Exception e) {
                                }
                                ;
                        }
                        s = properties.getProperty(tag);
                        if (s == null) {
                                s = dflt;
                                properties.put(tag, s);// will propogate default values to the
                                                                                // file
                        }
                } catch (Exception e) {
                }
                return s;

        }

}

So, believe it or not, it's all there. I think its a solid proof of concept anyway. Every car will be different, and there's plenty else that can be done to it: RPM column, invert signal/swap channel from mpg.properties file. A a collection of presets for different cars... But I, personally, am gonna try and do other stuff for a while :)

skewbe 07-22-2007 07:26 AM

Quote:

Originally Posted by sonyhome (Post 64702)
Pretty cool ... but I don't quite understand your diode clamp interface you used.

Could you explain how you make it work?
You connected directly to the injector via a 10K resistor?
And then you grounded the signal via a diode bridge? Is that to avoid having signals above 0.6V? Don't understand...

the diodes are supposed to limit the max voltage going into the sound card, yes. The resistor is supposed to prevent the diodes from trying to clamp the vss and injector to .6 volts. The VSS side could use some work in my case.


Quote:

Originally Posted by sonyhome (Post 64702)

And what's VSS for?

I though you'd use a coil to detect the pulses so the laptop would be totally independant from the car's electrical circuit...

To do Miles per Gallon, you need to know how many miles you have gone. A direct signal is much easier to parse than an induced signal in a coil. The resistor provides enough independance.


Quote:

Originally Posted by sonyhome (Post 64702)
All you have to do now to compute duty cycle is count the number of samples above a threshold vs all the samples.
You may need to adjust with a constant, or adjusting the threshold since the ramp up slope is not vertical, but seems constant.

Yah, I just have a fudge number, there probably is a constant component to the injector pulse that could be factored in for greater accuracy.

*Note, if one were to add a "injectorPulseCount" field to the Trip class, and detect it like the vss pulses, then RPM and a constant value adjustment per pulse could be accomplished.

*also note that it is trivial to add more trips, like "trip 1", "trip 2", etc, and have them save to disk when the window is closed.

Here is the sample a mpg.properties file it creates in the current directory, you can tweak the thresholds and fudge factors (and even pipe in a .wav file of a recording of your probes):
#
#Sun Jul 22 11:13:47 CDT 2007
dummyFile=
tank.injHi=3984869
tank.vssTot=1076
fuelFudge=8000000.00
injThreshold=-30
vssThreshold=100
tank.sampleCount=3984876
distanceFudge=3200.0

thisisntjared 07-22-2007 01:55 PM

thanks for the open source project :)

MetroMPG 07-22-2007 05:37 PM

I am duly, duly impressed! (And in over my head.) Congratulations are in order!

skewbe 07-23-2007 05:29 PM

MPG cruise control
 
Thanks yall, I wanted to get this idea down somewhere after looking up DWL again.


Ok, so now the computer knows the mpg, big whup. BUT, that old parallel port... It is great for driving, say, a stepper motor, which could, say, be chained up to, say, the throttle to...

Yah, you got it...


Maintain a pre-determined MPG, exactly :)

MetroMPG 07-23-2007 05:40 PM

Inspired. Creativity is cool.

skewbe 07-23-2007 07:59 PM

Heh, a couple more goodies that could be added by providing things like car weight:

1. monitor acceleration (based on change to vss pulses) and other dynomometer/ET type stuff.

2. provide indication of acceleration/fuel consumption (find the peak when accelerating?) Might be good to have an audio signal for this so you can watch the road while accelerating. Make small adjustments in the gas pedal till the pitch frequency tops out.

3. Compute CDA, accelerate to 60 on a flat road and coast to a stop, let it figure out the rest.

MetroMPG 07-24-2007 05:04 AM

Ooo! I like the audio signal idea. Sort of like version 1.0 of the DWL cruise control.

An audio tone to help you stay near your target FE, rather than spending a lot of time glancing at a screen.

psyshack 07-24-2007 05:18 AM

Boy there are some smart folks in this old world. WOW


All times are GMT -8. The time now is 09:48 PM.

Powered by vBulletin® Version 3.8.8 Beta 1
Copyright ©2000 - 2024, vBulletin Solutions, Inc.