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 CCS Technical Support

Motor encoder problem

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



Joined: 10 Jan 2014
Posts: 10

View user's profile Send private message

Motor encoder problem
PostPosted: Sun Mar 15, 2015 7:56 am     Reply with quote

Hello,

I try to count the encoder signals of a high speed motor,
if i turn the motor by hand everything runs fine and the program counts right but if i let the motor run - it doesn't work properly...the motor seem to be too fast for my program.

Is the pic too slow for this work or is it a software problem?

I use a PIC18F27J53
the Motor is a sanyo denki super r with 3000 rpm max.

here is my code:

it would be very nice if someone could help me a little bit with this problem.

Code:

// --------------------------------------------------------------------------
#include <18F27J53.h>
#device ADC=12                                                 
#fuses  HSPLL,PLLEN,PLL5, NOCPUDIV, NOWDT,NOPROTECT                     
#fuses  ADC12, RTCOSC_INT, DSWDTOSC_T1                               
#use    delay(clock=48000000)                                     

//Bootloader ------------------------------------------------
#build (reset=0x1000, interrupt=0x1008)               
#org 0x0,0xfff {}                               
// -------------------------------------------------------------------------------------------


#include <usb_cdc.h>
#include <stdlib.h>
#include <stdio.h>


//Encoderposition
#define EncMotor1CHA PIN_B7
#define EncMotor1CHB PIN_B6

   unsigned short kanalA1,kanalB1;
   unsigned short B_signal=0;
   unsigned short A_signal=0;
   signed int16 encoder_pulsA1=0;
   signed int16 pulsE1=0;


// USB ------------------------------------------------------------------------------------------

void usb_putc(char cc)                     // printf(usb_putc,...)
{
   while(!usb_cdc_putready());
   delay_ms(1);
   usb_cdc_putc(cc);
}
// USB -------------------------------------------------------------------------------------------

void HW_Init()
{

delay_us(50);   

enable_interrupts(global);
enable_interrupts(int_rb);
}
// Initialize Encoder
void encoder_init() {
pulsE1 = 0; // Clear Positions
A_signal = 0; // Clear state
B_signal = 0;
encoder_pulsA1=0;
}


//read Encoderposition
void encoder(){
        kanalA1 = input_state(EncMotor1CHA);
        kanalB1 = input_state(EncMotor1CHB);
     
   //Encoder 1
   if(kanalA1 == 1)
   {
      if(A_signal == 0)
      {
         A_signal = 1;
         
         if(B_signal == 0)
         {
            if(kanalB1 == 1)
            {
               encoder_pulsA1 = encoder_pulsA1 + 1;
           
               B_signal = 1;
            }
   
            if(kanalB1 == 0)
            {
               encoder_pulsA1 = encoder_pulsA1 - 1;
           
               B_signal = 1;
            }
         }
      }
   }

   if(kanalA1 == 0)
   {
      if(A_signal == 1)
      {
         A_signal = 0;
         
         if(B_signal == 1)
         {
            if(kanalB1 == 1)
            {
             
               B_signal = 0;
            }   

            if(kanalB1 == 0)

            {
               
               B_signal = 0;
            }
         }
      }
   }

   pulsE1 = encoder_pulsA1;

}


//Interrupt Port B
#int_rb
void button_isr(){
encoder();
}

//---------------------------------------------------------------------------------------

void main()
{
//encoder_init();
HW_Init();
usb_init();
while(!usb_cdc_connected());                  // Warte auf PC-USB-Verbindung

    while (true)
    {

  //initialize encoder
   if(input_state(PIN_A3)){
   //init
   encoder_init();
   }
   printf ( usb_putc, "%Ld \r\n ",pulsE1);
   } 
}
temtronic



Joined: 01 Jul 2010
Posts: 9241
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Mar 15, 2015 8:18 am     Reply with quote

quick answer...
Would need to know how many 'slots' are on the encoder wheel, as this relates to the number of 'PPR' ( Pulses Per Revolution ).
If it has 1024 slots, at 3000 RPM this will generate 51,200 interrupts per second. Now a quadrature encoder is 4X that number....

This does explain the 'works at slow speed- not at high speed' observation you have.

Normally, I use a US Digital encoder counter chip to 'offload' the PIC from doing the raw counting/direction details. This method, while costing a bit more, allows the PIC to do 'other things'. There are PICs with a QEI but I'm 'old school' and keep building on known reliable parts and PICs.

Jay
daalex



Joined: 10 Jan 2014
Posts: 10

View user's profile Send private message

PostPosted: Sun Mar 15, 2015 8:23 am     Reply with quote

Hello and thanks for answering,

it should be 1000 pulses/revolution... tells me the sticker on the motor and this is what my program counts in "slow motion".

I have read about the QEI PIC but i only have the pic 18f27j53, and if possible i would use the pic18F.
temtronic



Joined: 01 Jul 2010
Posts: 9241
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Mar 15, 2015 8:47 am     Reply with quote

at 1000 PPR X 3000RPM that's 3,000,000 counts per minute or 50,000 counts per second .

You can 'do the math'... 48MHz clock= 12M inst/ sec...an ISR might take 50 for overhead PLUS whatever code is inside the ISR ( your 'state decoder' ) maybe another 200 ? You can dump the listing out to actually see what is 'in there'.

My gut feeling is the PIC can't keep up....can't process the counts without losing a lot of them.

You could spin the motor at a know speed and see where the PIC loses.

You also have to decide what else the PIC has to do and factor that code in as well.Maybe the PIC could keep up with say 1200RPM BUT it'd be the ONLY code it could do.

Also any printing should be in an ISR as well to maximize the PICs speed.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Sun Mar 15, 2015 9:00 am     Reply with quote

Have a look at this thread:
<http://www.ccsinfo.com/forum/viewtopic.php?t=44491&highlight=quadrature>

This contains a quadrature routine I originally posted many years ago. Written to be efficient (uses the global interrupt, and code designed to minimise the time taken to actually deal with the encoder). It could fractionally be improved on the PIC18 (since this has hardware to save three of the registers). As written, this is capable of handling well in excess of 200000 edges per second on a chip as fast as yours.

How fast is your motor?. As Temtronic points out, a 1000ppr encoder, gives 4000 edges per rev. This should be able to handle up to perhaps 3000RPM+, but if you need faster than this, then 'think again'....

However there is another possibility. Are you sure the pulse train from your encoders is working properly at higher speeds?. If these are using resistive pull-ups, it's very possible that the pulses are no longer actually cycling high properly as the rotational speed increases. Look at this first. This may well be the core problem.

Other possibilities:
1) Use an external encoder chip.
2) Use a PIC with QEI.
3) Add external gate logic, and use the CCP's.

Both the first and last options are very easy. However there are also PIC18's with a QEI decoder. Look for chips that have the 'motion feedback module'. The PIC 18F4431 for example.
Jerry I



Joined: 14 Sep 2003
Posts: 96
Location: Toronto, Ontario, Canada

View user's profile Send private message

PostPosted: Sun Mar 15, 2015 9:18 am     Reply with quote

Hi

You can try what as per Microchip Servo AN696.pdf.
http://ww1.microchip.com/downloads/en/AppNotes/00696a.pdf

It uses the Pics internal timers with some external hardware.

Check it out.

Jerry
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Sun Mar 15, 2015 10:11 am     Reply with quote

I just have to disagree totally, with Temtronic's last line:

"Also any printing should be in an ISR as well to maximize the PICs speed."

Definitely not.

You need though to copy the 'position' value to be printed to a local variable, like:

Code:

   int16 local;


   while (local!=position)
        local=position;

   //then print the 'local' value.


Otherwise if the position changes during the print, you _will_ get garbage results.....
temtronic



Joined: 01 Jul 2010
Posts: 9241
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Mar 15, 2015 10:32 am     Reply with quote

guess I didn't word it right...but I meant that by using an ISR for printing, it should be faster as it uses a buffer and transmits data when required NOT tieing up the PIC like delay_ms() does.

Perhaps the USB driver does this ???

Jay
daalex



Joined: 10 Jan 2014
Posts: 10

View user's profile Send private message

PostPosted: Sun Mar 15, 2015 10:54 am     Reply with quote

Hello again ,

so i tried different things and now it seems to be ok and the programm is counting right. :-)

one part was the signal "cleaning" , i did that and now i have perfect quad signals.

the other part was my fault...

for explanation:
i can run the motor in different modes with a pcb...one mode runs the motor continiously in one direction with ~ 2000 rpm -> now the programm works and the counting is right.

but i used another mode and the motor runs in step mode...in this mode the motor turns a quarter step->stops-> and so on... would be nice - but this is not neccessary to count.

Thanks to all who helped me and giving tipps, thats why i like this forum...a beginner like me is getting answer's and tipps - so i can learn and get better :-)

greetz Alex
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