I'm doing a project with a 16F628 and a GPS receiver. The only problem is that I need to get a reading in MPH rather than KMH as given by the receiver so I need to do a conversion on the PIC. It's relatively simple to do (when not dealing with asm that is!) as it's only a multiplication by 0.621.
I have a number that can be from 000.0 to 999.9 stored in BCD, using 4 registers with one digit in each, so I guess ill need to convert that to a 16 bit binary number and then multiply it before changing it back to BCD, but i'm really unsure about dealing with numbers less than 1 in binary and the multiplication.
Any help appreciated! I'm sure someone must have come across this before so I thought there would be code snippets around to help, but i've not managed to find any.
First convert to 16 bit as you suggest. However, forget the decimal point – treat the last digit at the units – IE multiply your value by 10. Better still if your input value will NEVER exceed 655 then multiply by 100.
So, 123.4 KM/H becomes 1234 in binary = 0x4D2 (or *10 = 12340 = 0x3034)
Then, the equation you need is
y=x-(x*256+x*8192+x*16384-x-x*16)/65536
While this may seem complicated, it's fairly easy in assembler.
To multiply by 256 you shift it left 8 bits = shift left one byte.
To multiply by 8192 you shift left 13 bits = shift left 2 bytes and right 3 bits.
To multiply by 16384 you shift the last number (*8192) left once.
To multiply by 16 you shift left 4 bits.
You then add and subtract the various bits and shift the whole thing right 2 byte (divide by 65536).
Add this to your original value and convert back to BCD. (Nigel has a very good binary to BCD conversion routine in his tutorial).
Now shift the digits right once or twice (divide by 10 or 100) and you have MPH.
When you put 0x3034 into the above algorithm you get 0x1DF4 = 7668 out.
So, 123.4 km/H = 76.68 MPH. – Should be 76.677205122087 using 1.609344 km = 1 Mile
Wow, thanks guys, I actually get what is going on which is pretty rare - you explain it well!
The value in KMH will never be above 655, if I do find myself going 406 MPH on land I probably wont be looking at my little GPS! So I have multiplied by 100 and converted to 16 bit binary. Now trying to work out the multiply/divide.
Could you point out where the 16 bit binary to BCD routine is on Nigel's site? I can't see it.
Have a look at and scroll down to a routine called convert. This takes a 16 bit value and returns 5 digits which are BCD. It is very clever in the way it works.
Have a look at and scroll down to a routine called convert. This takes a 16 bit value and returns 5 digits which are BCD. It is very clever in the way it works.
Sorry, but I can't take the credit for the routine being 'clever' (which I agree it is), I got it from the PICList. As I recall there was a bit of a private competition on the PICList, with far cleverer people than me trying to create the best BIN/BCD routine - this was one I really liked, and I always use it.
Wow I just signed up today and already you gave me an idea!
a friend of mine has just bought a import and its in kph and he wants mph, his conversion was simple, its a new sticker for the speedo!
Problem is this leaves him with mph and the odometer/trip in kph.
I thought about using an old pic to take the signal from the gearbox and convert it, count pulses in, after X pulses send out Y pulses.
I have seen circuits like this on sale but usually cost much more than what they are worth etc, I may get round to building one one day.
Little harder than number crunching as the output needs to be their all the time, IE I cant wait for a 1000 pulses then output 621 etc, I guess I need to measure the number of pulses in say 0.5 seconds and then work out a frequency to output, but then I'm doing 2 things at once, I think I just found why these gadgets are expensive....
But, may I ask do you want with MPH since I had asssumed since the UK was in the EEC and was a party to metirification(sloppy) I would have assumed most of the speed signs were now in K/H. Are just pandering to a ludite?
But, may I ask do you want with MPH since I had asssumed since the UK was in the EEC and was a party to metirification(sloppy) I would have assumed most of the speed signs were now in K/H. Are just pandering to a ludite?
We still have pounds and new pence, although most of Europe has changed to the Euro.
Although all weights in shops have to be in kg, even after all these years most shops still price goods in both kg and lb's. I always ask for a 1/4lb of ham or whatever, NEVER in kg
Mind you, I was brought up on pounds, shillings and pence!.
Little harder than number crunching as the output needs to be their all the time, IE I cant wait for a 1000 pulses then output 621 etc, I guess I need to measure the number of pulses in say 0.5 seconds and then work out a frequency to output, but then I'm doing 2 things at once, I think I just found why these gadgets are expensive....
Not hard at all. A PIC18 is 10 million instructions/sec.
You'd set up an interrupt when the tach signal transitions. You can either count the number of pulses for each 250mS block and then the display routine looks at how many pulses have happened over the last 2 sec or so. The downside here is that you need a lot of pulses to get good resolution (particularly for low rpm), and that mean a slower response.
Or you can use a CCP module and its interrupt to check how many clock cycles happen between tach pulses. It's potentially more susceptible to noise (averaging helps) and there are also some resolution issues.
Little harder than number crunching as the output needs to be their all the time, IE I cant wait for a 1000 pulses then output 621 etc, I guess I need to measure the number of pulses in say 0.5 seconds and then work out a frequency to output, but then I'm doing 2 things at once, I think I just found why these gadgets are expensive....
You don't have to wait for 1000 pulses to output 621 pulses. You can perform a part of the conversion on every pulse. The equation for conversion from Kilometer to Mile is:
KM = 0.6214 x Mile
KM pulse count = 0.6214 x Mile pulse count.
Earlier, 0.6214 = 40722/65536
First, you assign a 16-bit register as an accumulator. For every Mile pulse detected, you add 40722 to that register. Everytime the register overflows (i.e., generates a carry), you generate a KM pulse.
The name of this algorithm escapes me right now but it is a form of electronic gearing.
You don't even need interrupts to detect Mile pulses. You can use timer0 to count incoming pulses. You scan it periodically for any change in value and any change in value from the previous scan is the pulse count.
The pulses are coming from a rotational counter such as a magnet on a wheel. If the wheel travels one mile it will give out more pulses than if it travels one km. Therefore mile pulses arrive faster than km pulses and Motions calculations are correct.