DIY digital speedometer using PIC microcontroller

Digital speedometer schematic available here (PDF, 34KB).
C source code available here under GPL (ZIP, 22KB).
I like knowing how fast my car is going, but the stock analog speedometer only goes up to 140kph. Plus, I suspect its accuracy isn't all that great, it doesn't register speeds below 15kph, and there's no way to calibrate it. I looked at digital speedometers online, but most of them were backlit LCD displays (almost illegible in the sunlight atop my dashboard, and an eyestrain even when you can read them). The ones that weren't were just too expensive for what should be a rather simple piece of electronics. I wanted a three digit 7-segment LED display, like my buddy Takahashi has in his Lancer EVO 6.
I looked at frequency counter chips, figuring I could use BCD decoder and a trio of 7 segment driver chips to display everything, but they were outdated and the amount of external timing circuitry I'd need was a bit ridiculous. I looked around at the local electronics supply store, and stumbled across some cheap programmable microchips. At first I thought it would be overkill, but considering a simple microcontroller is only $2 or $3 and reduces the number of parts significantly, it actually turns out to be the best option. Plus, you can add extra features like in-software calibration, 1/4 mile "drag strip" times, storing top speed, display in kph or mph, and whatever else you can think of. The drawback is the initial investment of a PIC programmer so that you can use your computer to burn your programs to the chip. You can now get an official PICKit 2 programmer for about $35 plus shipping, and it can be used on a variety of microchips all the way up through DSP microchips. If you're into hobbyist electronics, there's really no reason you shouldn't get one. Cheap, easy to program, and powerful enough for most stuff.
The cheapest microcontroller I could find was the PIC16F648A, which is an 8 bit microcontroller with 16 input/output pins and 3 hardware timers, more than enough for this project. It has 256 bytes of RAM, 256 bytes of EEPROM permanent storage, and programming storage space for about four thousand instructions, and best of all, it doesn't require any external oscillator hardware. PIC microcontrollers have a very minimal instruction set, meaning that any operation more complex than addition or subtraction requires a lot of instructions, but since this chip defaults to 1 million instructions per second that's not usually a problem, assuming you have a compiler capable of generating those sequences. As well, almost every input and output is reprogrammable to different hardware functions such as voltage comparison, interrupt triggering, edge counting, timer capture, or even serial communication. It's really quite a powerful little package, especially if you compare it to what was available just 5 years ago.
Your basic 7 segment LED has 10 pins. Two of those are the same, connected to either the anode or the cathode of all the LEDs, and the other 8 are the other end of each of the 8 LEDs. Since 24 LEDs is too many to control with 16 pins, I multiplexed them; that is, the 8 individual pins are all connected through resistors to 8 of the microcontroller pins, and I use 3 other pins to select which of the three displays to light up (via transistors since the PIC pins can't source that much current). If you switch between the displays fast enough, the human eye can't even tell they're being switched on and off.
Obviously the whole thing runs off 5 volts, so to step down the 12-14 volts from a car battery you need a voltage regulator (I used an LM7805 because it was what I had on hand). A couple capacitors also help, as cars tend to have lots of voltage transients. If I wanted to be a bit safer I could have also used a zener diode for overvoltage protection, but the power supply area of the circuit board was already a bit tight for space and the LM7805 and associated components are cheap enough to replace if something bad happens.
Here's a quick parts list of what I used:
1 - PIC16F648A microcontroller
1 - 18 pin socket (not needed if you're just breadboarding it)
3 - 7-segment displays, common cathode
8 - LED resistors (I used 120 ohm, but you should design with the max LED current in mind.)
3 - NPN transistors, anything should work
3 - 1k resistors (to use with the base of each transistor)
1 - LM7805 5 volt voltage regulator
2 - 22uF 50V capacitors (maybe overkill, but if you have noisy wiring you will need to adjust this)
1 - button (for software control)
2 - 10nF capacitor (button debounce and speedo input filtering)
1 - 100k resistor (button pullup)
AND
a board to put it all on, and cables to string it together. You should be able to get all this stuff for under $20.
If you're hooking this directly to a reed switch with no external driving circuitry (like a stock ECU), you will have to add another pullup resistor.
The easiest way would just be to hook up all the 8 LED leads to the same 8 bit port (PORTA or PORTB), but because we're using some ports of A and some of B to do other things, we can't be so lazy. So we'll spread those out and use a software bitmask to determine which ports to light up. Thankfully, it doesn't really matter that much what order they go in, because you can define it in software. The speedometer input has to be on a specific pin if we want to automatically log the timer when we get a pulse. And one of the pins cannot be used as an output, so we'll set that one to be our button input (and when we're putting our board together we'll use it as a reset pin). Aside from that, we can stick the three selector bits wherever we want them, and still have the two serial port pins left for CAN interfacing if we want it, and another for supply voltage sensing (so we can determine whether the headlights are on or off and dim the display accordingly). The parts for these last two options aren't included in the list above, because I haven't added them yet.
Once the hardware is all set up, you need some software to run it, and that's the tough part. The first order of business is reading the chip manuals thoroughly, and then finding yourself a C compiler, because programming in assembly is time consuming and rife with pitfalls. I started with cc5x but the free version only does up to 16 bit math, and it has a slew of other problems ("Can't generate code" is the chief among them, requiring you to manually simplify your code and manually define intermediate variables for calculations). But I tried out SourceBoost and the free version has far fewer limitations. The code should first set up all the interrupts and config registers, define the BCD and seven segment driver code, set up the timers, and tell the main loop to show something useful. It's best to stay simple; the first version of my code simply did a lamp test (all on, all off) and then displayed a rising sequence of numbers (which was actually just a spare timer I wasn't using). This makes sure your lamps all work and your wiring is correct. Then you can start adding in code to test that the pulses are being received and triggering properly without bounce, probably using a counter.
Update 1:
It seems one of the LED 7-segment displays I bought has a bad lamp (D, the one on the bottom). Of course the test lamp feature caught this easily, but only after I soldered everything to a board. Note to self: in the future, use sockets instead of soldering 7 segment displays directly to a board.
Update 2:
It turned out the lamp wasn't bad at all. It was just a short from overzealous soldering. Unfortunately I didn't catch this until AFTER I had ripped out the display element, trashing it in the process. Oh well, there goes 200 yen. But the good news is that it works now, and I've worked out the software bugs I've been able to find.
Update 3:
I finally wired everything into the car. My wiring was fine, but I had lots of noise in the input signal, causing a small interrupt storm that sent the microcontroller into fits. A small capacitor (10nF) between the signal and ground wires at the speedometer fixed that problem. Driving around, the speedometer was just fine below 10kph, but above that there was a lot of jitter in the time between pulses. I'm tweaking the algorithm to average more and more pulses at higher speeds, but since memory is limited this is an interesting problem.
Update 4:
I've had a chance to run the speedometer in my car for several months, and it's given me a chance to test it out. It works pretty well, is a lot more visible than my stock speedometer, and turns a few heads to boot. ("You built that YOURSELF??")
Since several people have asked me to release the source, I will do so. The source is released under GPLv3. You are free to take the code and use it, modify it, and improve it. If you fix any bugs let me know so I can fix them on my speedometer too! Also if you build your own DIY speedometer and put it in a car or bike or whatever, I'd love to see it. Please ask me before using it in a commercial product; I'll probably say OK but I would like to see the end result! The source does have known bugs which I haven't gotten around to fixing; these are listed at the top of the source file in the comments. The biggest one is that quarter mile calibration still doesn't work properly; with snow and ice on the ground I wasn't too motivated to fix them. Now that spring has arrived, I can do so.
As the GPL works, if you redistribute assembled code including hardware with the code installed, you must distribute the source along with it. You got it for free, so you can't complain.
The test modes included in my source code all let you test your wiring easily; simply set MODE_DEFAULT to MODE_TEST in the code, recompile and flash, and the tests will run when you apply power. The first test should display a constantly increasing number which wraps at 255. This makes sure your lamps are wired correctly and set up in software correctly. Press the button to go to the second test. The second test shows how long the button has been held down; a count of 30 is about one second. Use this to make sure your button works properly and isn't bouncing. After about 15 seconds the pulse counter mode is activated. This will show how many speedometer input pulses have been received. This is handy to verify that noise isn't triggering as pulses, and the pulses are registering properly. If all three of these tests work, then your wiring is correct and it should be possible to calibrate the speedometer (drive 50 and enter calibration mode) and display your speed.
Update 5
The schematic I'd posted before was using the wrong parts in the wrong configuration. I'm not sure how I screwed this up, but it's fixed now. Thanks, Velson.
Since I've moved back from Japan and have changed cars, I don't have a working testbed anymore. Feel free to submit patches to the code or modifications to the schematic, and of course if something doesn't look right please let me know so I can fix it.
October 4th, 2007 at 7:31 pm
I'm glad you finally updated your post so we know you're still alive---even though I couldn't understand anything you were talking about! What ELSE are you doing (that I might understand)?
October 5th, 2007 at 9:39 am
I added a photo so you can see what I'm talking about. Remember the red digital speedometer from "Back to the Future"? It's kinda like that, but with more features. And mine is green, but really you could make it whatever color you want. This photo is on my desk running one of the test modes, which is why the dots are all turned on.
October 6th, 2007 at 1:39 am
Great Scott!! Your story reminds me of when I invented the Flux Capacitor!!
October 31st, 2007 at 10:13 pm
hi there, your digital speedometer is kind of interesting...do you have a program in microC with this, can this be applicable to a wind meter too?
November 1st, 2007 at 10:41 am
Unfortunately, MicroC does not support the PIC16 series, but you don't really need a full operating system for a project that simple. You could do a wind speed sensor with this circuit, though I'd use a pulses per unit time approach (the longer time you sample over, the more accuracy you can get). Have one timer drive interrupts to refresh the 7 segment displays. Set up the CCP in counter mode. Have another timer average in the number of pulses somehow, and update the display number buffer every half second or so, clear the CCP timer, and exit. In this setup, your main loop doesn't have to do anything, just loop forever.
This circuit is not designed for minimum power use. If you're running off a battery you should use LCDs instead, because they draw much less power and don't need to be constantly refreshed. That means you could use sleep mode liberally and run for weeks or months off a single battery. But in that case you'd also need to tweak the reed switch resistor in order to minimize leakage current, and also use a more efficient power supply IC. Basically it would need a total circuit redesign.
February 12th, 2008 at 2:39 am
hi
sir could u give the programme used for this project to programme the 16F84a chip..
thanks
February 13th, 2008 at 2:08 pm
hi..
could you give the program use to programme that 16F84a chip?
thans
February 13th, 2008 at 2:16 pm
Unfortunately the code still has some bugs and isn't ready for release. Also, it uses TMR1 and TMR2 which are not present in the 16F84A. As soon as the bugs are fixed I'm going to release the source code under GPL, but you will still need to use the newer 16F648A. (The 648A should actually be cheaper too.) In the meantime, if you'd like help coding, I'll be happy to help you out. What part are you having trouble with?
March 14th, 2008 at 4:49 am
Hello,
Which source do you use?
Asm, or Jal?
I did use normally Jal, but asm can it too.
I'll wait with smart of your source code for my project. (K.I.T.T.)
March 15th, 2008 at 4:18 pm
It uses neither; the source is written in C and compiled with SourceBoost C compiler as linked above. Of course as with any C compiler you can have it generate asm no problem. I haven't used Jal so I can't comment on it either way.
April 23rd, 2008 at 7:51 pm
Where i can get source code...
September 27th, 2008 at 5:26 pm
hi this is interesting but one question, if i use a reed switch and a magnet, on my driveshaft how can i get it to work out the speed? x revolutions of driveshaft will equal x revolutions of wheel?
September 27th, 2008 at 5:55 pm
It will depend on how you have the driveshaft linkage set up. The ratio is not usually 1 to 1. You can determine it experimentally if you stick the car in neutral, jack up the drive wheels of the vehicle and rotate them both together exactly once. Hook the switch/magnet through something like a light that will tell you how many times it triggers every wheel rotation.
I suggest reading this article. In this case the article suggests locking one wheel in place and rotating the other wheel twice; depending on your differential you might not be able to do it that way.
The default calibration in the source code assumes 4 triggers per wheel revolution, with a very small tire size (kei car wheels are tiny). Most wheels will be larger, thus with the same number of trigger points a longer distance is covered between triggers. The built-in calibration cannot handle wheels much larger than 15" or fewer than 4 triggers per revolution because the calib_factor will be too big for a 16-bit variable. If you have trouble calibrating the speedometer because of this overflow, you can either add more trigger points onto the sensor (2 per driveshaft revolution, or 6-8 trigger points per wheel revolution) or you can modify the source code. Choosing to modify the software instead of your hardware triggers might mean sacrificing accuracy and/or response time. You'd have to make substantial edits to make it work properly-- unfortunately I couldn't make it as generic as I wanted because of memory limitations.
October 3rd, 2008 at 2:11 pm
Dear Jeff,
I know it's been a year but I stumbled across this page a few days ago and since I've put together your speedo. If you don't mind I have to ask you if that circuit you used in your car was the exact same as you presented here. You see, starting from the pdf with the schematic the displays are marked as CC and are connected as CA (pnp, sourcing). Now this was obvious and I corrected that but still the prblem with truncated and unreadable display remains (among other things).
If you read this, please send me the final version of your work, that is if you're not too busy and are willing to help me. I've been trying to put something like this together for years but I got no time on my hands, I have to do it in some reasonable time.
Regards
October 3rd, 2008 at 4:54 pm
Wow, I certainly feel stupid. The posted schematic was for an earlier revision of the board, back when I had common anode 7-segments and PNP transistors. In the final version I switched to common cathode 7 segment displays and NPN transistors because those were the parts which were available. The parts list on this page was correct, but for some reason I didn't update the schematic. Velson, I owe you one.
The 7 segment displays I used were dual-color; if you run a reverse-bias current through them, they glow red instead of green. That can be a handy debugging tool, or if used cleverly you can make them glow any color combination of those two, including any shade from red through yellow to green. If I were designing an AFR gauge for example I'd change color toward red as the mixture got more lean.
The new schematic should get you going in the right direction. If it still doesn't work, remove the microcontroller from its socket. First, make sure the voltage regulator is working properly using a multimeter. It's the most obvious thing, but of course if it's not working nothing else will. Tie one of the now empty RB7, RB6, or RB0 pins to ground (through the base resistor), and then apply +5V to one of the 7-segment control pins, such as RB4 or RB5, on the far side of the 120ohm resistor. One of the segments should light up on the activated digit, depending on which control pin you apply current through. If not, make sure you've got the proper pin diagram for the 7 segment display. Every maker uses a different convention.
Since you picked up that error in the schematic I'm sure you have a good background in circuit debugging. The microcontroller datasheet is definitely worth reading if you want to modify the circuit at all; for example, the RA4 pin cannot pull up to 5V without external circuitry. Weird quirks like that can sneak up on you. Good luck on your project!
October 4th, 2008 at 4:09 pm
Hi Jeff,
thanks for the tips but I really tried out everything there was to it.
First of all I did the debugging in SourceBoost with the 7seg plugin turned on and this showed the strange behavior I was writing about. Here I could specify which segment connects to which pin on the MCU so there was no mistake, I simply followed the schematic. I breadboarded it just to see if the SourceBoost has gone wrong somewhere but I got the same results.
I suspect there's a glitch in the source code somewhere, and as I'm not very good with C would you kindly check if you made some changes to the code on the fly and by some chance didn't update the link? The version I downloaded is dated May 29 2008.
I repeat, the connections are all by the schematic. Could you check also if the segments on the displays are correctly labeled (if A stands for segment "a", and so on)?
I don't want to modify the circuit, I just want it to work properly as yours does (or did).
Thanks a bunch and sorry if I'm a pain in the neck :)
October 4th, 2008 at 10:54 pm
The pin assignments for the 7 segment displays are NOT correct. Unfortunately I can't tell you the proper pin order because each manufacturer's display has different pin assignments. Do you have a datasheet for your 7 segment display? If not, test using a 5V power supply in series with a small resistor, 1k should be good but don't go under 470 ohm (most LEDs don't tolerate more than 10mA for long). Connect one pin to ground (negative terminal) through the resistor, and touch the other pins to the +5V rail in sequence. If each one lights up in sequence, congratulations, you've found one of the common cathode pins (usually there are two, for convenience). If one segment lights up twice, then those two are the common cathodes. You will have to map out which pins correspond to which segments. From the top going clockwise, label the segments A through F. The middle is G, and the decimal is H. Find out which pin corresponds to each one.
Thankfully it doesn't matter what order you hook them to the microcontroller in, if you use the I/O pins as listed on the schematic. But you will have to edit a few lines in the code so that it knows which pins go where. The rule is: for A through G, through the 120 ohm resistors, you can use any pins on either ports A or B, but you can't use the same port for A and B. For example, you can use A0, B1, B2, B3... but you can't use both A0 and B0 or both A1 and B1 for the segment connections. You can use any pin you want for the digit illumination (connected to the base of the transistor for each digit). I wouldn't recommend using A4 because it has no pullup resistor, but you can use any other pins you want.
As you can see, by default I use A1, A2, A3, B4, B5, A6, A7. Decimal is handled separately, so you can hook it to whatever you want.
The definitions are all at the top of the code to make it easier. If you follow those rules you shouldn't have to modify the code at all, just change the #define lines to match your pin assignments. If you need help with that, just ask!
October 5th, 2008 at 4:15 am
That's all clear to me, Jeff, what I asked you was that if the LABELS on the drawing were correct. I'm familiar with 7segs and I know their pin assignments but thanks anyways for the trouble of getting it through to me. I followed your markings and I hooked the pin marked A (on your drawing) to the "a" segment on my 7seg and so on and so forth.
What I don't understand is why I'm getting weird displays despite the correct connections. That's why I thought the problem was in the code. I checked that too and it seems OK to me but I still get:
segment "a" and "f" lit for number 1,
"c, d, e, f, g" for 2,
"a, c, d, e, f" for 3,
"a, b, c, f" for 4,
"a, b, c, d, e" for 5,
"a, b, c, d, e, g" for 6,
"a, e, f" for 7,
8 is good :) every segment goes on, they have no choice in that matter :)))
"a, b, c, d, e, f" for 9 and
"a, b, d, e, f, g" for 0.
If you see a pattern here let me know. A weird thing, though, 6 and 7 are horizontally flipped. Strange...
Also, could you explain this line to me:
#define SEVSEG_BITFIELD(H,G,F,E,D,C,B,A) 0b ## E ## A ## D ## G ## F ## C ## B ## H
I couldn't understand the right side of the line, beginning with "0b". I don't know C very well as I mentioned before.
You see, I wasn't going to change anything if it worked, I just don't get it if it's not different from your circuit and the code is the same (my connections are good, I triple checked it) why doesn't it work correctly.
Thanks for your patience. Oh, and you can write freely of electronics on expert level, that is my profession, only programming in C is something I'm not familiar with but I'm getting to it.
Regards
October 5th, 2008 at 12:07 pm
Hey, the good news is that your 7 segs all work! :)
The line you pasted is a map that says what is plugged in where. The left part says "There is a macro that looks like SEVSEG_BITFIELD(H,G,F,E,D,C,B,A)" and everything after that indicates how it rearranges that bitfield. This is using what's called the C preprocessor to do the dirty work (it's part of the compiler), so that the chip doesn't have to do any remapping calculations on the fly.
The right portion works like this. The A7/B7 line is mapped to E. The A6/B6 line is mapped to A. The A5/B5 line is mapped to D. And so on. The ## are concatenation operators only used by the preprocessor. If you search through the code you'll see lines like {SEVSEG_BITFIELD(0,0,1,1,1,1,1,1) which is the bitfield to light up F, E, D, C, B, and A (that would be the zero digit). The preprocessor changes {SEVSEG_BITFIELD(0,0,1,1,1,1,1,1) to 0b11101110 which is a binary number; the 0b at the beginning is notation for binary, and the digits proceed from most significant to least significant. H is handled separately, so acts like a dead bit.
So if you wired up things _exactly_ like the diagram, you should use:
#define SEVSEG_BITFIELD(H,G,F,E,D,C,B,A) 0b ## G ## E ## D ## C ## B ## A ## F ## H
Judging by the information you've provided, that should be the correct mapping. Try recompiling with that line changed.
October 5th, 2008 at 12:59 pm
Works like a charm! I know I was on to something when I got stuck on that line of code...
Thank you for your time, I'll let you know when I complete this project.
October 12th, 2008 at 12:59 pm
hi there, your digital speedometer is kind of interesting...you can sand the hex. program for me.thx
October 15th, 2008 at 2:36 pm
it is very intteresting project,but i'm a beginer so without HEX. source code i have no chance.so pls
October 15th, 2008 at 2:53 pm
Unless your wiring is exactly the same as mine (it won't be, seeing as the schematic's bus wiring doesn't exactly match my prototype) you'll have to set the #define statements according to how you've wired it, and compile the program from source. For this reason I'm not providing a binary-- it wouldn't be much use to you anyway.
You should download BoostC and compile it yourself. I believe it should install and run under Wine if you don't have a copy of Windows.
October 19th, 2008 at 7:27 am
hy all.i can't use the boostC.how can write the speedo c in pic.i have no idea how work.i use icprog.this prog write only hex. file :( somebody can convert to hex file an send me.thx b.lewy86@freemail.hu
December 11th, 2008 at 10:40 am
hey jeff!! i made one of your speedos but cannot get a proper digit out. i havnt tried the #define SEVSEG_BITFIELD(H,G,F,E,D,C,B,A) 0b ## G ## E ## D ## C ## B ## A ## F ## H thing. In any case would it be possible to mirror image the characters because i actually intend to use it as a HUD device and will eventually want to flip all digits for tht purpose. unfortunately i am very noob in C and got no idea how to rewrite the code for that part. Thanx in advance if you could help me out
December 11th, 2008 at 2:47 pm
If your digits aren't coming out properly (but the right number of segments are lit up for each number) then you need to modify the SEVSEG_BITFIELD macro to match your wiring, and recompile it. You can easily mirror the displays by changing that macro as well; there are three pairs you need to swap, mirroring vertically and leaving the center alone. No other modifications to the code are necessary. But keep in mind if you want to use decimals, the reflected dots will appear reversed as well.
You could rotate the displays to make the dots appear on the lower left corner of each display. In that case you'd have to mirror each digit horizontally by modifying that macro. Also, any code that lights up a decimal would have to be modified to use a different digit-- the place that comes to mind is the 1/4 mile timing code (which I never got to work properly).
Good luck with your project, and if you get it working I'd like to see a photo!
December 11th, 2008 at 10:11 pm
Just to check from my understanding that if i were to change the original line
#define SEVSEG_BITFIELD(H,G,F,E,D,C,B,A) 0b ## G ## E ## D ## C ## B ## A ## F ## H (because i followed your diagram EXACTLY but mapping ur diagram's A to my 7seg A appropriately) to #define SEVSEG_BITFIELD(H,G,F,E,D,C,B,A) 0b ## F ## A ## B ## C ## D ## E ## G ## H my image should be vertically flipped?
Is it possible to code this into one of the button modes? so i can select this while driving? And i should be compiling it with MODE_TEST instead to do testing right?
Thank You so much for helping me out, sorry i had to bother you with an old project! will mail u a pic of my proj IF it gets complete in the first place!
December 11th, 2008 at 10:46 pm
The typical way of labeling the segments of a 7 segment display is to start with 'A' at the top, go clockwise in order through 'F', and 'G' at the center. The decimal is sometimes labeled 'H' and sometimes something else. You need to swap A and D, B and C, and E and F. Leave G alone. So your line would be:
#define SEVSEG_BITFIELD(H,G,F,E,D,C,B,A) 0b ## G ## F ## A ## B ## C ## D ## E ## H
for a vertical flip. But since it's easier to verify digit operation in normal mode, do that first, then start swapping.
The macro allows the bitfields to be coded in statically while at the same time allowing for wiring swaps for convenience. If you want to flip dynamically, that will be too costly in terms of operations. Instead, you should create a duplicate set of bitfields for the numbers 0-9 and the letters used (with the fields set properly to display mirrored segments), and write code that displays from the mirrored set if a "mirrored" flag is on in software. It would be up to you to write this code and fit it in, and you'll have trouble compiling in the MODE_TEST code as well. I ran out of space to use with the free compiler. You can free up some by compiling without MODE_TEST as default, or by removing or optimizing some functionality.
Definitely compile with MODE_TEST when verifying your wiring, though. It makes it easy to test the 7-segment displays, your SEVSEG_BITFIELD, the button, and the speedometer input. The last one can be prone to noise, so the "tick counter" will help you verify you're getting only one tick every time the reed switch goes off.
December 12th, 2008 at 4:54 am
YEAH! HUD speedo works. not plugged in car but has passed all tests. now its just figuring out where to tap in my car, which is a 92 civic and i think my vss is in the tranny.
December 13th, 2008 at 12:58 pm
hey jeff, sorry to bother you again but i don't seem to be able tp get a reading for my car. i tapped my vehicle's vss to pin 9 of my PIC of my speedo but the reading stays zero. ALL tests passed in ur test mode but nothing in SPD mode. What could be wrong? port B 3 has positive pulses but stays at 0. i compiled and wired and rechecked my wiring many2 times but nothing wrong. The signal i tapped is correct. Am i missing sumthing or is there some code that i need to enable before i compile?
Thanks Lots!
December 13th, 2008 at 11:03 pm
Most likely either you have a wiring fault (the wrong pin maybe?) or the speedometer pin does not output 0-5V. If the former, the most common problem would be either a short in the bridging capacitor (a bad capacitor or bad wiring) or you simply have the wrong wire on the car. The latter would depend on your ECU and how it's set up. I assume you have some sort of shop manual or wiring diagram so you know which wire you're tapping into.
Get a digital multimeter, set it to voltage, and measure between ground and the "speed in" pin (the easiest way to do this is to pull the PIC chip out of its socket, and measure between the PIC ground (VSS) and your speedometer in. Jack the sensor wheel(s) of the car up, put it in neutral, and turn the key to ON without starting the car. While watching the DMM's readout, slowly rotate the tire(s) with the speed sensor. It should flip back and forth between 0 and 5V several times with each rotation. If it doesn't flip back and forth, then either you're not rotating the correct wheel(s) or something is wrong with the wiring. If it flips back and forth between 0 and some other value, you'll need to modify the circuit a bit; I don't have the PIC648A spec sheet open in front of me but the interrupt may not trigger if the voltage is too low, and I think a high voltage (12V) will put the chip in programmable mode -- this is a bad thing. Some newer vehicles might use 0-3.3V, some older ones might use 0-12V or something even higher.
In vehicles with an ECU, the ECU drives the sensor voltage through an internal resistor. This design relies on something else driving that part of the circuit. You didn't cut the speedometer wire, did you? If your stock analog speedometer still works you're probably OK.
December 14th, 2008 at 12:22 am
I did not CUT the wire and my analog is fine. I tapped directly into the VSS on my transmission which has a ground, +12 and signal which i beleive is a pulse wire. i wired my DMM to the ground and the SPEEDO out wire and get 0.2v at standstill and slowly climbs up to 1.7v before my DMM is not fast enough to catch the bouncing signal. I am going to try using an Analogue instead today and see. my first attempt was to use the VCC and tap the pin9 (RB3) and see if i get pulses but still nothing. i emulated it by tapping a stray wire from VCC to it many times but still no pulses. Should i be tapping from my ECU instead not sure if this would make any difference.
my civic is an OBD1 and i'd say its one of the older cars you were talking about.
December 14th, 2008 at 12:30 am
Hmm... try rolling forward REALLY slowly to see if you can get it to read high, like 3V or 5V or something like that. It will only happen for a split second. Jacking the car up and rotating the wheels by hand might be easier. What you're looking for would look like this under an oscilloscope (pardon the bad ASCII drawings):
___-___-___-___-__You could also try switching your DMM to "frequency" or "clock" if it has a setting like that, to confirm it's a pulsed signal and not an analog 0-5V or something.
December 14th, 2008 at 1:42 am
it has been confirmed. using my analog meter it pulses to 5v at low speed. So its probably my PIC not reading it. i soldered this wire to my pin9 please confirm thjis is correct? everything is per the schematic. What could be wrong? Faulty PIC?
December 14th, 2008 at 2:03 am
Yes, RB3 is correct (pin 9).
A faulty PIC is possible, but not likely. Usually they fail all at once or not at all.
Without a wiring schematic for your car it's hard to say what the issue is. You might try adding a pulldown resistor between the speedometer input and ground, in case the thing is alternating between +5V and high impedance. Too high a value and it won't work, too low and it could cause the analog speedometer or power steering to not work (or something to burn out, which is not good). Try 47k first, and 10k if that doesn't work; both of those should be safe.
If you're worried that your buffer capacitor is shorted out, you can remove it completely for now and the circuit will still work. You'll see lots of ringing in the input (false positive triggers) but it will eliminate that as a possible point of failure.
Keep at it! It sounds like you're almost done!
December 14th, 2008 at 2:11 am
that is the problem... i removed the buff cap and still no ringing .. pulses stay at 0. Are the NC pins on your schematic to be grounded or stay as NC? the speedo does not respond even to noise. apparently i was wrong about passing all tests, it passed first 2 tests but not the third where its supposed to be pulse detection. if u have an instant msger maybe i could webcam the project to you if ur free enough! : ) thank you lotsa so far! really appreciate it.
December 18th, 2008 at 3:32 am
can i get the hex file so i can program it because i don't have c compiler ..
Thank you sir ..
My email : viva.ohms@gmail.com
December 21st, 2008 at 2:58 am
mr jeff mentioned that he used SourceBoost which has a C compiler in it.
December 21st, 2008 at 3:11 am
Thanks, Sham.
I sent you an email to the address provided about how to contact me via IM if you want to. Did you get it?