View previous topic :: View next topic |
Author |
Message |
tvnorm
Joined: 29 Aug 2006 Posts: 6
|
speedohealer tachometer kmh/mph converter divide by N.xxx |
Posted: Tue Jul 07, 2009 9:46 pm |
|
|
Hi all, I haven't done a PIC project in awhile and I am wondering if it is time.
There is a product called a "speedohealer". I would like to duplicate it's functionality for personal use. I think I should have all the ingredients laying around.
Essentially I want to intercept pulses from the speed sensor on a motorcycle to account for a gearing change, and on a car to convert a natively KMH speedometer to MPH.
Both are hall effect sensors, I Have a map of frequency input vs speedometer readout for both gauge clusters.
For instance on the motorcycle a 150Hz input reads 5 MPH, and it tops out at 3500Hz input = 189 MPH. It's basically linear.
To rescale this I would basically need to divide the transient input frequency by 1.121 and send it back out. If I had a "knob to tweak" the constant from between say 1.111 and 1.131 that would be great.
It seems the easiest thing would just be a divide by type IC, the trouble is I need to divide by a non-integer in both cases.
I have previously managed to write a preamplifier control scheme involving a relay based attenuator and source selection with lcd readout and remote control and rotary encoder inputs. So this project should be doable.
Do I need a PIC or is there an IC that does this? Any ideas or snippets of code would be greatly appreciated.
Sorry for the book, too much coffee I guess.
I'm a MechE so forgive me if this is trivial. |
|
|
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
|
Posted: Tue Jul 07, 2009 11:19 pm |
|
|
Based on the description for the Speedohealer on http://www.healtech-electronics.com/ , I would say that a PIC is more suited for this than simple hardware.
For the 'Programmable Calibrator' you could have a rotary knob, or push buttons, or even DIP switches to select the required divide-by constant.
The PIC would be able to do the calculations; the lower end PIC sometimes struggle with tedious float-type arithmetic that need a fast update rate. In your case, however, you could average out the pulses per minute from the hall sensor over a short time period and then perform the float arithmetic.
I suppose an LCD would be used for the display. While selecting a PIC keep in mind that at least 6 pins are required to communicate with the LCD; 7 pin communication is recommended.
You should search for the term 'tachometer' in the forum for hints on how to go about doing this.
A quick note: the Speedohealer's website claims "100% accurate readings". The degree to which your tires are inflated will also affect the speed and odometer readings. I know that taxi drivers in Bombay used to run smaller tires to get advantageous trip-meter readings!
Rohit |
|
|
tvnorm
Joined: 29 Aug 2006 Posts: 6
|
|
Posted: Wed Jul 08, 2009 4:00 pm |
|
|
Ok then PIC it is.
Rohit de Sa wrote: | A quick note: the Speedohealer's website claims "100% accurate readings". The degree to which your tires are inflated will also affect the speed and odometer readings. I know that taxi drivers in Bombay used to run smaller tires to get advantageous trip-meter readings!
Rohit |
That is funny, but I only need accuracy +/- about 3%. |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Wed Jul 08, 2009 8:30 pm |
|
|
For something like this I would use the software technique called a "Numerically Controlled Oscillator". In this case every pulse would add a small integer number to a long integer accumulator. Once per second, or some other fixed time interval, the accumulator value is moved to a display register and the accumulator is zeroed.
You can do all of this with simple fast integer math. If you want the results to look like 12.34 MPH then use integer math to calculate 1/100's of MPH. A unsigned long will go to 65000/100 MPH which is likely big enough. Then just use the print function to put the decimal point where it needs to be. No need for big ugly floating point numbers. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
|
Posted: Wed Jul 08, 2009 9:07 pm |
|
|
Quote: | For something like this I would use the software technique called a "Numerically Controlled Oscillator". In this case every pulse would add a small integer number to a long integer accumulator. Once per second, or some other fixed time interval, the accumulator value is moved to a display register and the accumulator is zeroed.
You can do all of this with simple fast integer math. If you want the results to look like 12.34 MPH then use integer math to calculate 1/100's of MPH. A unsigned long will go to 65000/100 MPH which is likely big enough. Then just use the print function to put the decimal point where it needs to be. No need for big ugly floating point numbers. |
I like the method described by SherpaDoug a lot. Its very useful when you want fast calculations. I've used it in a temperature measurement device where I'd take 100 readings and then printf to an LCD as described.
Quote: | but I only need accuracy +/- about 3% |
What you probably mean is that you only want an accuracy with +/- 3% error. The statement "100% accurate readings" means 0% error.
Rohit |
|
|
tvnorm
Joined: 29 Aug 2006 Posts: 6
|
|
Posted: Wed Jul 08, 2009 9:20 pm |
|
|
SherpaDoug, At the moment that is over my head but I will look into it.
What I want is a black box to splice in between the speed sensor and the existing speedometer.
The speedometer is calibrated from the factory for a certain final drive (chain reduction after the speed sensor). If this final drive is changed the the speedo will be off.
At a ground speed of 76mph the speed sensor outputs a 1500 Hz signal, and the speedometer reads 76mph.
Now with the change in final drive at an actual ground speed of 76mph the speed sensor will be putting out about 1700Hz causing the speedo to read 88mph.
At this point I'm thinking use CCP to time 1 incoming pulse, in this case 558us, multiply that value by the appropriate constant (~1.121), elongating the pulse to 667us, sending this out and making the speedometer again read 76mph.
The highest speedo display is 189mph at 3500Hz, so the fastest pulse will be 286us. I can ignore a few pulses while the ISR/math/pulseout are occuring. The refresh rate on the speedo now is very slow anyway.
So I need a pulse train in and a pulse train out.
I will look into the Numerically controlled oscillator just because I have never heard of it!
Thanks. |
|
|
tvnorm
Joined: 29 Aug 2006 Posts: 6
|
|
Posted: Wed Jul 08, 2009 9:31 pm |
|
|
Rohit de Sa wrote: |
Quote: | but I only need accuracy +/- about 3% |
What you probably mean is that you only want an accuracy with +/- 3% error. The statement "100% accurate readings" means 0% error.
Rohit |
Right on Rohit.
You've got me there, What I meant was at highway cruising speed an error of +/- 3% (75mph +/- 2.25mph) is acceptable. 12mph, however is not. |
|
|
tvnorm
Joined: 29 Aug 2006 Posts: 6
|
|
Posted: Wed Aug 12, 2009 10:37 pm |
|
|
Okay, so I have finally got a chance to work on this. I shamelessly stole the Tachometer code from PCMProgrammer and modded for my needs.
For now I am just trying to repeat a square wave from a function generator to the CCP1 pin on the 16f690, and output it to an oscilloscope with frequency measurement capabilities.
The trouble with this code is the output is off. For instance:
Fnc Gen freq|PIC output freq
100Hz | ~96.5 Hz
200 | ~191
300 | ~285
400 | ~375
1000 | ~885
2000 | ~1639
3000 | ~2174
3500 | ~2466
Any of you Gurus have any hints for the N00b?
Code: |
#include <16F690.H>
#fuses INTRC_IO,NOWDT, NOPROTECT, NOPUT, NOBROWNOUT, NOMCLR
#use delay(clock = 4000000)
#zero_ram
int16 isr_ccp_delta;
#int_ccp1
void ccp1_isr(void)
{
int16 current_ccp;
static int16 old_ccp = 0;
current_ccp = CCP_1;
isr_ccp_delta = current_ccp - old_ccp;
old_ccp = current_ccp;
}
void main()
{
int16 current_ccp_delta;
int16 width;
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_ccp1(CCP_CAPTURE_RE);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_2(T2_DISABLED,0,1);
setup_spi(FALSE);
setup_comparator(NC_NC_NC_NC);
setup_oscillator(OSC_4MHZ);
clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
while(1)
{
disable_interrupts(GLOBAL);
current_ccp_delta = isr_ccp_delta;
width =current_ccp_delta/2;
enable_interrupts(GLOBAL);
output_high(PIN_A2);
delay_us(width);
output_low(PIN_A2);
delay_us(width);
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 12, 2009 11:22 pm |
|
|
You have the following sources of error in your output signal timing:
1. The overhead of the while() loop and the lines of code in it.
This is about 25 usec.
2. The delay injected into the while() loop, when the interrupt
occurs and is serviced. This is probably at least 80 usec.
3. The internal oscillator of the 16F690 is only rated at +/- 2%
accuracy at +5v over the industrial temperature range. |
|
|
|