View previous topic :: View next topic |
Author |
Message |
Ray
Joined: 22 Jul 2007 Posts: 12 Location: Australia
|
making a 32bit CCP out of CCP4 for a tacho |
Posted: Sun Jul 22, 2007 5:53 pm |
|
|
Hi,
Can anyone out there show me where I am going wrong with this. In the PIC sim it works perfect but on the bench, occasionally the MSB goes walkies and I just end up with an RPM based on the LSB. I need it to be 100% and at this stage am getting a bit frazzled. I did try some code from another post re a 24bit capture but it didn't pan out too well
timer is set up with a prescale of 1 and CCP4 is divide by 4,
#int_ccp4
void rpm_isr()
{
disable_interrupts(int_timer1);
if (!bit_test(PIR1,0))
{
rpmlsb = ccp_4;
rpmmsb = timer;
vrpm = make32 (rpmmsb, rpmlsb);
vrpm = (800000000/vrpm);
}
set_timer1(0);
timer=0;
bit_clear(PIR1,0);
enable_interrupts(int_timer1);
}
#INT_TIMER1
void msbrpm_isr() //one timer loop = 6.5ms
{
disable_interrupts(int_ccp4);
if(timer<65535)
{
timer++;
}
enable_interrupts(int_ccp4);
} |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 22, 2007 6:03 pm |
|
|
Post the PIC that you're using, and post your compiler version. |
|
|
Ray
Joined: 22 Jul 2007 Posts: 12 Location: Australia
|
version and chip |
Posted: Sun Jul 22, 2007 7:42 pm |
|
|
18F8722 and Version 3.249 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 22, 2007 9:38 pm |
|
|
The other code with the 24-bit timer extension should work. I don't want
to do it over again, so I'm just going to say use that code. |
|
|
Ray
Joined: 22 Jul 2007 Posts: 12 Location: Australia
|
|
Posted: Sun Jul 22, 2007 11:28 pm |
|
|
Oh well, I'll try it again, it was just that it was unsteady at higher frequencies,
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 22, 2007 11:48 pm |
|
|
What's the frequency of the input signal ?
Also, what voltage is your PIC running at ?
What are the high and low voltages of the input waveform ?
Is the input waveform a clean signal ? (no noise) |
|
|
Ray
Joined: 22 Jul 2007 Posts: 12 Location: Australia
|
|
Posted: Mon Jul 23, 2007 2:52 am |
|
|
I was running it today at 322hz and 150hz. Voltage is 5V. I'm running the input signal from a tti function generators TTL output at 50% duty and have also tried it from the 600ohm and 50ohm outputs at .3V to 4.5V squarewave. I scoped the crystal, 5V (at the processor), earth and input on our 4ch DSO and can see nothing untoward unfortunately. I cut down the code to run a bare minimum and still no joy. Can you see anything wrong with my code at all? I have a tell tail for max rpm and I set a breakpoint there in my code and had the simulator running for half the day and didn't hit it once, but obviously the bench is different. power is generated from a tti programmable power supply via some spike protection, a 78L05, decoupling caps by the reg and processor. Thanks for taking the time to help. I'm at home at present, but I'll load in you code again tomorrow morning and see if anything has changed as my code is slightly different to when I last tried it. Last time it was unsteady above 300hz but I had a divide by of 1, so it may have been due to interupt latency (just guessing though). |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 23, 2007 3:24 am |
|
|
What's the oscillator frequency of your PIC ? |
|
|
Ttelmah Guest
|
|
Posted: Mon Jul 23, 2007 4:24 am |
|
|
Some other comments though on what you were trying to do.
There is no point in the disable/enable interrupt lines. Unless you are using high priority interrupts, an interrupt can't interrupt another.
There is unecessary work, in the 'make32'. Just write the words into parts of the int32 - example below.
Big problem though, is the division in the interrupt handler. 32bit division, is slow. Even on a 40Mhz chip, a 32bit division, will take typically 106uSec. Now, having a division here, will imply that interrupts will be disabled in the external code in any similar division routine. I'd be suspicious that this is causing the problem...
Code: |
union access {
int32 lword;
int16 parts[2];
} counter;
int1 update=false;
#int_ccp4
void rpm_isr(void) {
//surely, if the timer1 interrupt has occured, you just want to
//increment the MSB?.
if (bit_test(PIR1,0))
counter.parts[1]=timer+1;
else
counter.parts[1]=timer;
counter.parts[0] = ccp_4;
vrpm = counter.lword;
update=true;
set_timer1(0);
timer=0;
clear_interrupts(int_timer1);
enable_interrupts(int_timer1);
}
|
Then in your main, if 'update' is true, perform the division to get your required number, and clear update.
Best Wishes |
|
|
Ray
Joined: 22 Jul 2007 Posts: 12 Location: Australia
|
|
Posted: Mon Jul 23, 2007 2:20 pm |
|
|
Thanks heaps for the feedback, I'll try that coding change this morning. I am running 10mhz + PLL, so 40mhz and I am using a high priority on CCP4 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 23, 2007 3:32 pm |
|
|
I was able to make the code in this post work with a 150 Hz input signal.
http://www.ccsinfo.com/forum/viewtopic.php?t=29963&start=3
I tested it with an 18F452 running at 40 MHz (10 MHz crystal in H4 mode).
To make it work, I had to make the following changes:
1. Change the Timer1 divisor to divide by 2:
Quote: | setup_timer_1(T1_INTERNAL | T1_DIV_BY_2); |
2. Change the numerator in the frequency equation to 5 MHz:
Quote: | frequency = (int16)(5000000L / current_ccp_delta);
|
Then I connected a function generator to pin C2 (CCP1 input pin) and
set it for a little below 150 Hz. Then I slowly adjusted the fine tuning
knob upwards in frequency. Here's the result, displayed in a terminal window:
Quote: |
148 Hz
148 Hz
148 Hz
148 Hz
149 Hz
149 Hz
149 Hz
149 Hz
150 Hz
150 Hz
150 Hz
151 Hz
151 Hz
151 Hz
151 Hz
|
Note that the example code in the link uses CCP2 to create a test signal
for the tachometer (which takes its input from CCP1). I didn't use CCP2
in this test. I used an external B&K function generator to create the
150 Hz input signal for the tachometer.
The reason for changing the Timer1 pre-scaler is:
With a 40 MHz oscillator frequency, Timer1 runs at 10 MHz.
With a 150 Hz input signal, Timer1 will count up to:
Code: |
10 MHz
------- = 66667 counts
150 Hz
|
This is greater than the maximum size of the 16-bit Timer1, which
can only count up to 65535.
The solution is to setup Timer1 to use a pre-scaler of 2. Then it will
only count up at a rate of 5 MHz. With a 150 Hz input, the count value is:
Code: |
5 MHz
------- = 33333 counts
150 Hz |
This value is easily contained within the 16-bit Timer1. This also adds
a considerable amount of slack, so you can use an input signal that
is lower than 150 Hz by a fair amount without hitting any limits.
To implement this, you need to make the two changes shown at the
start of this post. You set the Timer1 pre-scaler to 2 and you change the
numerator in the frequency calculation to be 5 MHz (instead of 10 MHz).
This also shows why you had a problem. With a signal of roughly 150 Hz,
you're right in the vicinity of overflowing Timer1. That's probably why
things appeared to be flakey to you. But with the changes shown above,
it works very well. |
|
|
Ray
Joined: 22 Jul 2007 Posts: 12 Location: Australia
|
|
Posted: Mon Jul 23, 2007 4:16 pm |
|
|
thanks for your efforts. I need to measure from 16hz to 600hz. I have changed my code to the previously mentioned code above...
#int_ccp4
void rpm_isr(void) {
disable_interrupts(int_timer1);
if (bit_test(PIR1,0))
counter.parts[1]=timer+1;
else
counter.parts[1]=timer;
counter.parts[0] = ccp_4;
vrpm = counter.lword;
update=true;
set_timer1(0);
timer=0;
bit_clear(PIR1,0);
enable_interrupts(int_timer1);
}
#INT_TIMER1
void msbrpm_isr()
{
disable_interrupts(int_ccp4);
if(timer<65535)
{
timer++;
}
enable_interrupts(int_ccp4);
}
and again, on the simulator it is perfect, but on the bench it turns to custard, so essentially, just to save you any hassle as I am absolutely sure you have much better things to do , in your opinion, is this a hardware thing or settings/software thing. If you can just please point me in the best direction, I'll go forward and hopefully sort it. With the above code it is steady everywhere but intermittently jumps to rediciously high revs e.g. 38373 presently with 385hz which is meant to and normally does display 7699rpm,
Thanks again for all your efforts
p.s. when is the dsPIC compiler going to be released |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 23, 2007 4:37 pm |
|
|
You keep changing your requirements. The new lower frequency of
16 Hz would require a 24-bit timer. I posted the changes to make that
work, later on in the thread that I linked to above. I'm out of time.
I can't afford to spend any more time on this thread. |
|
|
Ray
Joined: 22 Jul 2007 Posts: 12 Location: Australia
|
|
Posted: Mon Jul 23, 2007 4:49 pm |
|
|
thanks Ttelmah for that code, I've put it in and after I sorted a little mistake on my part it is working brilliantly, your a genius, thanks for that |
|
|
|