View previous topic :: View next topic |
Author |
Message |
Guru Narasimha V S
Joined: 05 Aug 2022 Posts: 5
|
Reading the tacho values in PIC18F47Q43 |
Posted: Wed Aug 24, 2022 1:17 am |
|
|
Hello,
I am using PIC18F47Q43 for generating the 4 PWM signals.
The clock used is 32Mhz.
I had used 3 CCP modules and PWM slicing.
I have used timer 2 for generating PWM's.
I have referred this from the forum : https://www.ccsinfo.com/forum/viewtopic.php?t=59832
The fan which is connected has tacho pins. I have connected the tacho pins to PIN_B0, PIN_B1, PIN_B2 and PIN_D7.
I could not get how to read the pulses from the those pins.
And how to calculate the rpm of the FAN.
According to datasheet the MAX RPM of the FAN is 2000.
It would be really helpful if I get this issue solved.
Need to know how to read the pulses from those 4 pins. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Wed Aug 24, 2022 5:29 am |
|
|
You read a tacho by just timing the period between the pulses. So if
the two rising edges are 60mSec apart, then (assuming the unit gives
one pulse per rev), the unit is doing 1000RPM
60/period -> revs
60/0.06 = 1000
Now the easiest tool to read the period with is one of the CCP's.
Your big problem is just that you are using all your CCP's. Don't. Save
one by using the second slice on the sliced PWM, so you have a CCP left
to use for the tacho.
Then assuming you don't need to measure all the speeds all the time,
take advantage of PPS, and route the first input to this CCP. Wait for two
triggers, so the time is then 'genuine', and read the count. Reciprocate
this and you have the revs. You can save maths, by having a constant
giving how many clocks should occur in 60 seconds, and just dividing this
by the count. You then attach your second input, (by reselecting the
PPS), and repeat the measurement for this. Then the third, then the fourth.
Onviously the fuses have to b set to allow multiple PPS settings
(NOPPS1WAY), and use the inline PPS setting (read the sticky about
this at the top of the forum). |
|
|
Guru Narasimha V S
Joined: 05 Aug 2022 Posts: 5
|
|
Posted: Sat Aug 27, 2022 12:39 am |
|
|
Hi Ttelmah, Thank you for the reply.
I was able to free the ccp modules and tried to capture it.
I got confused how to implement the timers for 60ms.
With the help of the example program I captured in CCP module.
Here is the code which I implemented:
Code: |
long rise,fall,pulse_width;
#fuses NOPPS1WAY
#pin_select CCP3 = PIN_B0
#int_ccp3
void isr()
{
rise = get_capture(1);
fall = get_capture(3);
pulse_width = fall - rise;
}
void main()
{
setup_ccp1(CCP_CAPTURE_RE); // Configure CCP1 to capture rise
setup_ccp3(CCP_CAPTURE_FE); // Configure CCP2 to capture fall
setup_timer_1(T1_INTERNAL| T1_DIV_BY_8); // Start timer 1
enable_interrupts(INT_CCP3); // Setup interrupt on falling edge
enable_interrupts(GLOBAL);
while(TRUE)
{
// printed the value obtained from the capture
}
}
|
But the values were too fluctating . I could not get how to reselect the pps.
Could please let me know to how go further with it. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Sat Aug 27, 2022 1:04 am |
|
|
You only need one CCP.
You have to ignore the value on the first interrupt (since the value
then will be 'from' when the reading started), then take a reading at the
second interrupt. Then take a third reading at the third interrupt.
The time is then the third reading minus the second to get the time
between the interrupts.
You want the time between too successive rising edges. Not the rising and
falling.
The pulse frequency is what you are after, not the pulse width. |
|
|
Guru Narasimha V S
Joined: 05 Aug 2022 Posts: 5
|
|
Posted: Thu Sep 01, 2022 2:10 am |
|
|
Hi Ttelmah,
Sorry for the late reply as there was problem with my machine.
I tried to incorporate the things by setting 1 CCP and reading the data after 1 first interrupt.
Code: |
#fuses NOPPS1WAY
#pin_select CCP1 = PIN_B0
int counter =0 ;
#int_ccp1
void ccp1_isr()
{
counter++;
if(counter == 2)
{
FirstCapture = get_capture(1);
}
if(counter == 3)
{
SecondCapture = get_capture(1);
pulse_frequency = FirstCapture - SecondCapture;
counter = 1;
}
}
void main()
{
setup_ccp1(CCP_CAPTURE_RE); // Configure CCP1 to capture rise
setup_timer_1(T1_INTERNAL| T1_DIV_BY_8); // Start timer 1
enable_interrupts(INT_CCP1); // Setup interrupt on falling edge
enable_interrupts(GLOBAL);
while(TRUE)
{
// printed the value obtained from the capture
}
}
|
The values keeps on fluctuating as earlier.
but when the fans are off the values keeps a constant recent value.
I am not getting where its going wrong. Could you please help me through it. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Thu Sep 01, 2022 5:36 am |
|
|
Understand that the full count will be a large number, and will fluctuate at the
least significant digits. You are clocking off 1MHz (32MHz/4 /8).
Now if the thing is doing perhaps 1000RPM, a typical count will be perhaps
60000. You should set your timer up to maintain a LSB count (incrementing
when the timer wraps), and be including this in your count. I'd expect the
count to be fluctuating by several tens of counts, since motors are not
that stable. However if you include the extra bits from the potential wrap,
and then perform the division so:
RPM = 60000000/count
You should probably see a value fluctuating by only a couple of RPM.
You will need to handle the timer wrap, since otherwise at this count rate
you won't be able to handle anything below about 1000RPM without the
timer overflowing (915RPM will be where a wrap _will_ occur). |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Sep 01, 2022 12:24 pm |
|
|
Couldn't he temporarily reduce his CPU clock speed to 16 MHz ?
This would clock Timer1 at half the speed, so he wouldn't have Timer1
potentially overflowing. Then he could ignore the overflow problem
at least for now. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Thu Sep 01, 2022 10:28 pm |
|
|
Yes, but he needs to handle the wrap, or it won't work when the motor
is starting etc.. |
|
|
|