CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

PIC18F46K80 as high Speed Counter

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
amit78



Joined: 17 Jul 2009
Posts: 21
Location: Kolkata, India

View user's profile Send private message

PIC18F46K80 as high Speed Counter
PostPosted: Fri Nov 08, 2019 6:38 am     Reply with quote

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: 9093
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Nov 08, 2019 7:15 am     Reply with quote

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: 288

View user's profile Send private message

PostPosted: Fri Nov 08, 2019 7:19 am     Reply with quote

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: 21
Location: Kolkata, India

View user's profile Send private message

PostPosted: Fri Nov 08, 2019 7:30 am     Reply with quote

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: 452
Location: Montenegro

View user's profile Send private message

PostPosted: Fri Nov 08, 2019 9:13 am     Reply with quote

You could also push this PIC to 64MHz AND write global interrupt handler.
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Fri Nov 08, 2019 9:39 am     Reply with quote

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: 19215

View user's profile Send private message

PostPosted: Fri Nov 08, 2019 9:45 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Nov 25, 2019 3:40 am     Reply with quote

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?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group