View previous topic :: View next topic |
Author |
Message |
Ttelmah
Joined: 11 Mar 2010 Posts: 19605
|
|
Posted: Thu Nov 20, 2014 4:43 am |
|
|
It is perhaps worth pointing out that the count the oscillator approach is always going to be more accurate at these sorts of rates.
At 180Hz incoming frequency, if you are measuring for 1 second, the 'break even' point (where counting the clock will be exactly as accurate potentially as the count the pulses approach, will come when the clock is 180* the frequency of the signal. So 32400Hz. As soon as the clock is faster than this, the potential resolution of the clock approach exceeds that of the count over time approach.
With the 4MHz clock, if the clock was accurate, at 180Hz, the count the oscillator approach could be over 100* as accurate as the count over time approach. However the limiting accuracy is the oscillator. All the code shows you using the internal oscillator. This is only specified to give about a +/-2% accuracy, and is what will be limiting your measurements.
If you want better accuracy, go back to the count the oscillator approach, and switch to using a crystal, rather than the internal oscillator. Otherwise you are just wasting your time.... |
|
|
carl
Joined: 06 Feb 2008 Posts: 240 Location: Chester
|
|
Posted: Thu Nov 20, 2014 7:52 am |
|
|
Understood Ttelmah and thanks for your input.
The primary goal is within 1% and if it is achievable without changing the hardware, then that is the main priority. The PCB design is already in use for other encoder applications - so a change in the hardware would be a last resort.
I acknowledge the error rate on the internal crystal, but just wanted to see if 1% was achievable. So far the counting method gives better results, and I can greatly improve this by increasing the PPR Maybe upto 2048. So F = 2048 * 2000/60. F = 68.266KHz.
Of course the drawback is I am always going to loose resolution at lower speeds using the counting method, so I need to determine the minimum speed/tolerance allowed (probably end up being a split tolerance for different min/max speeds). Also the counting method has a long delay.
But I am getting there!
Thanks |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9282 Location: Greensville,Ontario
|
|
Posted: Thu Nov 20, 2014 8:02 am |
|
|
Don't know if you considered this but...
IF you get your 1% solution running on one PIC it may(probably) won't work on the next one. This goes back to using the internal oscillator and 'batches' of PIC will be 'close' but not 100% the same.
I know you've saved a few pennies by not using a crystal and 2 caps but whenever you need accurate and repeatable performance,especially in a commercial product, using a crystal/caps combo will save you a lot of grief,time and money in the long run.
jay |
|
|
carl
Joined: 06 Feb 2008 Posts: 240 Location: Chester
|
|
Posted: Thu Nov 20, 2014 8:27 am |
|
|
Hi Jay,
Its not the cost, but the application is very lower power (WiFi Encoder) that lasts for over a year from battery and ordinarily 'critical' timing is not required for the current applications. So I am trying to see if it is possible to utilise the current hardware (by modifying the firmware) for this new application (tacho + direction) first before considering new hardware.
Thanks
Carl |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19605
|
|
Posted: Thu Nov 20, 2014 8:45 am |
|
|
You have a simple answer. No.
If you start with a clock with a 2% accuracy, you can't get better than this (except by things like 'working short term', and calibrating from a known source).
However if the measurement doesn't need to be made very often, remember you could enable a crystal oscillator, run from this, perform the measurement, then switch it off, and go down to the internal oscillator. |
|
|
carl
Joined: 06 Feb 2008 Posts: 240 Location: Chester
|
|
Posted: Thu Nov 20, 2014 8:59 am |
|
|
Agreed.
Thanks for all your help guys! |
|
|
SuperDave
Joined: 22 May 2008 Posts: 63 Location: Madison, TN
|
|
Posted: Fri Nov 21, 2014 5:09 pm |
|
|
Code: |
#int_TIMER2
void TIMER2_isr(void)
{
if(loops)
{loops--;}
else
{meas_done=true; }
}
|
could be better written
Code: |
#int_TIMER2
void TIMER2_isr(void)
{
loops--; //decrement every time in so 10 is 10 not 11. BIGGEST ISSUE.
if (!loops) { //when zero
stored_sensor_pulses = sensor_pulses; //Freeze it NOW - accuracy tweak
sensor_pulses = 0; //reset immediately - accuracy tweak
meas_done=true; //flag for main to calculate
loops = 10; //value for next interrupt entry, here or main not important
// set_timer2(0); not needed it's already zero that's why we are here.
//note all of these are very fast operations
}
}
|
and main (which seems to be missing a } ) changed to
Code: |
while(meas_done){ //0.5s Tick has occurred
RPM = stored_sensor_pulses * 2.3114; //Accuracy and precision Crystal dependent, note use of stored_sensor pulses
//note: the above is a floating point operation that takes a relatively long time, especially at 4MHz, but we have half a second.
sendData( RPM); //send the data via external hardware
output_low(DAV); //THIS PIN GOES HIGH ON THE FIRST PULSE AND LOW JUST AFTER THE LAST PULSE - WHY?
meas_done=false; //reset
// loops = 10; done in interrupt
// sensor_pulses = 0; done in interrupt
// set_timer2(0); automatic in interrupt
}
|
From a maintenance standpoint, the WHILE could better be IF since it only happens once and most of Main() should be moved to a void called Initialize since that is what it is doing. Neither change has any effect on operation or accuracy. |
|
|
|