View previous topic :: View next topic |
Author |
Message |
amit78
Joined: 17 Jul 2009 Posts: 22 Location: Kolkata, India
|
PIC18F46K80 as high Speed Counter |
Posted: Fri Nov 08, 2019 6:38 am |
|
|
Dear All,
I am trying to count pulses from one servo motor using one PIC18F46K80. I tried to connect one MC3486 output to PIC Ext Interrupt (EXT_1). But I found the counter is not working for high speed motor rpm.
I have used the following:
The main loop is running in 800ns. We have used 20MHz external crystal.
Code: |
#pragma fuses XT,HSH,NOPLLEN,WDT1024,NOPROTECT,NOBROWNOUT,NOFCMEN,NOIESO,NOPUT
#pragma use delay(clock=20000000,restart_wdt)
void main()
{
// Set up WDT.
setup_wdt(WDT_ON);
// Initialize External Interrupt.
InitExtInterrupt();
// Enable Global Interrupt.
enable_interrupts(GLOBAL);
// Restart WDT.
restart_wdt();
for(;;)
{
output_toggle(PIN_OUT_DO_00);
//g_ui32ServoPulseCounter_op_A++;
// Restart WDT.
//restart_wdt();
}
}
|
[img]https://ibb.co/n6f4kBJ[/img]
Then I tried the Following:
Code: |
void InitExtInterrupt(void)
{
// INT_EXT - 1.
clear_interrupt(INT_EXT1);
enable_interrupts(INT_EXT1);
ext_int_edge(1, INT_EXT1_L2H);
}
#INT_EXT1 // For Servo Output - A
void ext_int_1_isr(void)
{
output_toggle(PIN_OUT_DO_00);
}
// Inside main()
for(;;)
{
}
|
Red Line is my output, and yellow is the wave coming from Servo:
For 100 rpm
[img]https://ibb.co/mJCY2yC[/img]
For 500rpm
[img]https://ibb.co/n078SCL[/img]
For 1000rpm
[img]https://ibb.co/H4rjWwb[/img]
For 2000rpm
[img]https://ibb.co/qYVvR6r[/img]
For 3000rpm
[img]https://ibb.co/w7dXy3P[/img]
So, Can any one tell me how could I count the pulses? in 3000 rpm it is around 2us cycle. Is it possible to count this using PIC18F46K80?
Thanks in advance for helping me ....
Amit |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Fri Nov 08, 2019 7:15 am |
|
|
yes the PIC will do it...
1st get RID of the WDT ! You do NOT need the WDT during 'development'. WDT code should ONLY be added after program is 100% tested, ready for client. Then and ONLY then add WDT code...IF.. needed. |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Fri Nov 08, 2019 7:19 am |
|
|
It appears to be taking around 10us to enter your interrupt routine and toggle the pin. This will limit the maximum frequency you can count without missing edges. You can reduce this by writing your own global interrupt handler to eliminate the register save overhead and handle this yourself.
It would probably be best to use one of the hardware counters instead of an interrupt if you just need to count and not respond on every rising edge. |
|
|
amit78
Joined: 17 Jul 2009 Posts: 22 Location: Kolkata, India
|
|
Posted: Fri Nov 08, 2019 7:30 am |
|
|
Now Changed the code without WDT, But did not work ...
Code: |
#pragma opt 8
#pragma fuses XT,HSH,NOPLLEN,NOPROTECT,NOBROWNOUT,NOFCMEN,NOIESO,NOPUT
#pragma use delay(clock=20000000)
void InitExtInterrupt(void)
{
// INT_EXT - 1.
clear_interrupt(INT_EXT1);
enable_interrupts(INT_EXT1);
ext_int_edge(1, INT_EXT1_L2H);
}
#INT_EXT1 // For Servo Output - A
void ext_int_1_isr(void)
{
output_toggle(PIN_OUT_DO_00);
}
void main()
{
// Set up WDT.
//setup_wdt(WDT_ON);
// Initialize External Interrupt.
InitExtInterrupt();
// Enable Global Interrupt.
enable_interrupts(GLOBAL);
// Restart WDT.
//restart_wdt();
for(;;)
{
}
}
|
|
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Fri Nov 08, 2019 9:13 am |
|
|
You could also push this PIC to 64MHz AND write global interrupt handler. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19541
|
|
Posted: Fri Nov 08, 2019 9:39 am |
|
|
You need to understand just how much time handling an interrupt takes.
When the interrupt happens, the chip responds an instruction later. Then
calls the handler (so we are now three instructions after the 'event'), the
handler then saves every register, and then does your toggle. Then the
interrupt is cleared, the registers are restored, and the chip returns to
the main code. The total instruction count to do this will be about 65
instruction times. So at 20MHz, about 12uSec. This then sets the maximum
count rate at about 83000 edges per second. While this is happening, the
chip can do nothing else (so your main loop at this point will stop....).
Now You can speed this up as others have said by coding your own
#INT_GLOBAL, which to just toggle a pin won't actually need to save
any registers. However the real way to handle something this fast is to
use the hardware. Feed the signal into a timer input, and this can be set
to count the signal at no cost of processor performance at all. You can read
the count at any time. So counting a signal at 500KHz, using the hardware,
no problem at all (the counters normally support rates up to about the
maximum of the chip). |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19541
|
|
Posted: Fri Nov 08, 2019 9:45 am |
|
|
Just checked and timer0 and timer1 on this chip support counting at up to
16MHz when you are running at 20Mhz. |
|
|
Mrinmoy Dey
Joined: 23 Jan 2018 Posts: 44
|
|
Posted: Mon Nov 25, 2019 3:40 am |
|
|
Hi,
I am trying with PIC18F46K80 to use as a high-speed counter with timer0 and timer1. Set up the timers at an external mode when I am trying to get the count through get_timer function every time I got some other values but not the expected one. Can someone suggest me if there is any special configuration or how to configure the timers as counters to get a proper count? |
|
|
|