diy mpg gauge - Page 10 - Fuelly Forums

Click here to see important news regarding the aCar App

Reply
 
Thread Tools Display Modes
 
Old 06-24-2008, 11:05 AM   #91
Registered Member
 
sonyhome's Avatar
 
Join Date: Jul 2007
Posts: 150
Country: United States
Try to load the applet on it, and just run it. You then also need to connect the car onto the microphone input.
__________________

__________________

sonyhome is offline   Reply With Quote
Old 07-23-2008, 10:22 PM   #92
Registered Member
 
Join Date: Jul 2008
Posts: 2
Country: United States
Quote:
Originally Posted by skewbe View Post
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:
http://opengauge.org/diympggauge/
***

*tank will persist when window is closed


Using this circuit, with right and left switched



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

*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
I am new to this forum and I have been reading the thread about diy mpg gauge using a laptop. Quite an ingenious idea! Very clever. I am ready to put this circuit together but I have a few questions: 1. What kind of diodes should be used? 2. The injector wire; is this an injector wire from an individual injector or the wire that controls all of the injectors? 3. Is it possible to hook this up to a palm pilot?

I am planning to set this up on a 1996 Chrysler concorde and if successful I will publish photos and a tutorial for this car.
__________________

jtiner is offline   Reply With Quote
Old 07-23-2008, 11:15 PM   #93
Registered Member
 
sonyhome's Avatar
 
Join Date: Jul 2007
Posts: 150
Country: United States
[QUOTE=jtiner;112351]
1. What kind of diodes should be used? 2. The injector wire; is this an injector wire from an individual injector or the wire that controls all of the injectors? 3. Is it possible to hook this up to a palm pilot?
[QUOTE]
So I'm not the expert but I'll pitch in:
1- any diode, for example some from a power supply.
2- I think it's directly from one of the injectors.
3- Try to run the applet first. Load it on palm & I say save an audio file on an mp3 player, and play it back to the palm via a wire conecting both. If it works you should be OK.
__________________

sonyhome is offline   Reply With Quote
Old 07-24-2008, 09:37 AM   #94
Registered Member
 
Join Date: Jul 2008
Posts: 2
Country: United States
Thanks for the advise.

Are there parameters within the software that I need to program to the specifics of my car? In other words, if I am using an injector wire from one injector do I need to program the software for 6 cylinders (x6)? I am thinking of the calculations it needs to make for the entire engine, not just one cylinder.
jtiner is offline   Reply With Quote
Old 07-24-2008, 05:23 PM   #95
Registered Member
 
sonyhome's Avatar
 
Join Date: Jul 2007
Posts: 150
Country: United States
Don't expect to have it right off the bat: I think there's a small config file to define parameters and tune to your car... Injector size, delay between open and gas flow, # cylinders, tire rotation speed, etc will impact the MPG reading. I think it's all in the original post/thread. You can also contact the guy who wrote this instead of my 2nd hand flaky info.
__________________

sonyhome is offline   Reply With Quote
Old 08-26-2008, 09:01 AM   #96
Registered Member
 
Join Date: May 2008
Posts: 1
Country: United States
I've recently gotten this to work just fine. Here's my take on it.

1)Any silicon small signal diode will do. Radio Shack or scavenge. (Actually, a germanium diode will work, but you'll get a maximum signal of about 0.3 volts instead of 0.6 volts.)

2) Yes, use the injector wire from just one cylinder, whichever wire is easiest to get to is fine.

3) If your Palm Pilot has a stereo line level sound card input, you can do it. Otherwise, no deal. You'd also have to get the Java app ported to Palm OS. (I don't know how that would be done).

There are only four variables that need to be calibrated to your vehicle. These are called fuelFudge, distanceFudge, injThreshold, and vssThreshold.

They are found in the mpg.properties file that the program creates the first time you run it. You can open this file with any text editor, (with the program NOT running) and then save your changes before running mpg.java again.

I found some details that are scantily covered in the information above, and these are relevant.

Once you get the interface electronics wired up and connected to a soundcard, it's a good idea to run a recording of the signal. I use CoolEdit or Adobe Audition, but anything that will let you record and then zoom in on the waveform will do.

A peek into the java code reveals that the waveform is decoded for the program as numbers from -127 to +127. This number is the number of samples above or below zero that the waveform goes. This number is also what is referered to as the threshold variables in the program.

In my case, the injector waveform makes a pretty clean vertical line at the opening/closing of the injector, (like a square wave), so a threshold of near zero works OK. I adjusted mine to -8, which prevents false injector readings when the engine is off (noise signals will vary around the zero line by some amount.)

The vehicle speed sensor waveform in my car is a steep sided quasi-sinewave. A look at the waveform shows that it varies from -65 to plus 65 or so, and a threshold of about 10 works for me.

After you have set the threshold factors, you can set the fuelFudge and distanceFudge to correspond to your car.

Set the distanceFudge first by running down the road and having a helper (for safety's sake) monitor the speedometer versus the program's calculated speed. The program counts the number of speeds sensor pulses in a one second interval, then divides this by the distanceFudge to get the speed.

So, if the program shows that you are going faster than the speedometer, INCREASE the fudge factor. If it shows a calculated speed lower than the actual, DECREASE the fudge factor.

You can get pretty close with a little math. If the distance Fudge is 3200, (the beginning default value), you're going 60, and the program shows 70, then you're off by (70/60)*3200, or about 373. So try a fudge factor of 3573. When you get within a few percent, it's easier to just tweak the fudge factor by two to five units at a time, say from 3573 to 3575, then 3580, etc.

Over a long trip the TANK total miles (bottom box in the program) will be more accurate to tweak the fudge factor. So if you have 400 miles on the tank, and the program has calculated 375, you will have to decrease the fudge factor a bit.

Now that you have the speed calibrated, it's time to get the fuel factor set up. It works the same way, the program divides the total number of fuel injector pulses by the fuelFudge to get the actual fuel usage. You can get pretty close by topping off the tank, running the program while driving a quarter to half a tank off, then comparing the total gallons calculated with what it actually takes to fill the tank back up.

Same math will get you close, so if the program says it took 10 gallons, and it actually takes 8, you have to increase the fuelFudge by about 1.25 times. (The default is 8 million, so you'd want to try 10 million) It takes a bit of tweaking to get this one set up, but just a tank or so of fuel should get you pretty close indeed.

I hope this helps you all out.

Jim
jim-frank is offline   Reply With Quote
Old 09-02-2008, 05:46 AM   #97
Registered Member
 
curjones's Avatar
 
Join Date: Aug 2008
Posts: 14
Country: United States
I'm kinda lost here. May never get what you are doing so be gentle. Are you using the sound card already in the computer. Then do you have to enter some data to make this program work on the computer. Im trying to understand the basic concept. I have seen where you can buy programs that read gauges and sensors on the lap top.
curjones is offline   Reply With Quote
Old 09-02-2008, 06:12 AM   #98
Registered Member
 
theholycow's Avatar
 
Join Date: Apr 2008
Posts: 6,624
Country: United States
Send a message via ICQ to theholycow Send a message via AIM to theholycow Send a message via MSN to theholycow Send a message via Yahoo to theholycow
The idea is pretty cool: You use the existing sound card, since what comes over the injector wire resembles sound enough to be accurately recorded by the sound card. There's a program that analyzes that input, designed for this purpose; you just need to adjust that program.
__________________
This sig may return, some day.
theholycow is offline   Reply With Quote
Old 09-02-2008, 07:10 AM   #99
Registered Member
 
curjones's Avatar
 
Join Date: Aug 2008
Posts: 14
Country: United States
So you buy the program, name,where and how much. Do you have to have a specific sound card.
curjones is offline   Reply With Quote
Old 09-02-2008, 08:12 AM   #100
Registered Member
 
theholycow's Avatar
 
Join Date: Apr 2008
Posts: 6,624
Country: United States
Send a message via ICQ to theholycow Send a message via AIM to theholycow Send a message via MSN to theholycow Send a message via Yahoo to theholycow
That's a good question about the program. I didn't know it existed until jim-frank posted about it above. Before that, I just knew that others have connected to sound cards, as in this thread:
http://www.gassavers.org/showthread.php?t=7608
(that link is in my thread about using the HF multimeter, too)

To do it that way, no specific sound card is necessary. The same is almost certainly true of the program jim-frank uses, which he says runs on Java; Java is somewhat hardware-agnostic, and uses the OS to deal with stuff like sound cards. I hope he comes back and posts the name of the program and tells us where to find it. A few minutes of googling failed to produce it for me.

I'd recommend trying it on a computer you're not afraid to hurt, first, just in case your fuel injection system uses high voltage or current or could otherwise damage the computer...after all, you are making a connection that no engineer ever expected you to make.
__________________

__________________
This sig may return, some day.
theholycow is offline   Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Not very precise mpg calculation larjerr Fuelly Web Support and Community News 4 08-20-2012 02:03 AM
epa estimates cseverens Fuelly Web Support and Community News 2 06-09-2010 04:48 AM
Keeping my distance in traffic khurt General Fuel Topics 8 09-07-2008 04:23 AM
Electrical power and cars. DracoFelis Automotive News, Articles and Products 2 09-16-2006 02:31 PM
"active" aero grille slats on 06 civic concept MetroMPG General Fuel Topics 21 01-03-2006 01:02 PM

» Fuelly iOS Apps
» Fuelly Android Apps
Powered by vBadvanced CMPS v3.2.3


All times are GMT -8. The time now is 04:19 PM.


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