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

problem to read position from encoder

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







problem to read position from encoder
PostPosted: Mon Nov 21, 2005 6:30 am     Reply with quote

Hi every body,
I have problem to read the postion from encoder when the motor is turn more than 1000RPM.(pic is not work)

Any body can help me to make this program to read the position more than 3500RPM.

Thank you very much for your help.

#include <18f2431.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, parity=N, Bits=8, xmit=PIN_C6, rcv=PIN_C7,stream=COM_1)
#use fast_io(B)
/*
RB4,RB5=quadrature inputs
*/
signed int32 position=0;
//Note using int32, otherwise routine will run off the end very quickly.
//Also 'signed', so the unit can handle the shaft rotating backwards at
//the start...
#byte portb=0xF81
#bit bchanged=0xFF2.0
#int_global
void myint(void) {
static int old;
static int new;
static int value;
//Here I have an edge on one of the quadrature inputs
new=portb;
/*Now I have to decode the quadrature changes. There are four
possibilities:
I can have a rising or falling edge, on each of the two inputs. I have to
look at the state of the other bit, and increment/decrement according to
this. */
value=new^old;
//'value', now has the bit set, which has changed
if (value & 0x10) {
//Here the low bit has changed
if (new & 0x10) {
//Here a rising edge on A
if (new & 0x20) --position;
else ++position;
}
else {
//Here a falling edge on A
if (new & 0x20) ++position;
else --position;
}
}
else {
//Here the high bit (B) must have changed
if (new & 0x20) {
//Here a rising edge on B
if (new & 0x10) ++position;
else --position;
}
else {
//Here a falling edge on B
if (new & 0x10) --position;
else ++position;
}
}
old=new;
bchanged=0;
#asm
//Here the 'fast' exit.
RETFIE 1
#ENDASM
}
//Main code loop
void main(void) {
signed int32 lastpos=0;
position=0;
port_b_pullups(true);
//Note that many of the quadrature encoders _require_ pull-ups on
//their lines, having open collector outputs.
setup_adc_ports(NO_ANALOGS);
setup_spi(FALSE);
set_tris_B(0x30); //Input on bit 4,5 for quad
enable_interrupts(INT_RB);
enable_interrupts(global);
lastpos=position;
while (true) {
if(lastpos!=position){
lastpos=position;
printf("%ld \n\r",lastpos*360/4/1024/23);
//I would recommend a delay here. The interrupt will still keep
//counting edges, but without a delay, the string will be 'non stop'
//for any reasonable movement rate.
}
}
}
sseidman



Joined: 14 Mar 2005
Posts: 159

View user's profile Send private message

PostPosted: Mon Nov 21, 2005 7:37 am     Reply with quote

Using the 2431, you shouldn't have to do any edge detection by yourself-- use the QE inputs, and take advantage of the hardware quadrature handling. It will be much faster.
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Mon Nov 21, 2005 8:50 am     Reply with quote

What filtering capacitors do you have? If you look on a scope and find that the rise time doesn't even get a chance to get up all the way, then you'll have to change your hardware.

This would be the first step in troubleshooting your problem, because if the hardware is the problem, then no software changes will fix it.
Mi
Guest







PostPosted: Mon Nov 21, 2005 9:40 pm     Reply with quote

Hi sseidman and MikeValencia
I use 2 encoders input, one encoder i use QE input with no problem but an other one i use interrupt port b to capture position from encoder and i have problem when motor turn fast.


I don't have filtering capacitor, my encoder is HEDS5500. i connected my encoder directly to the pic in port B4 and B5.

how to speed up the program?
where i can i put the filtering capacitor?

thank you very much.
sseidman



Joined: 14 Mar 2005
Posts: 159

View user's profile Send private message

PostPosted: Tue Nov 22, 2005 7:31 am     Reply with quote

Personally, I'd throw one uC at each.
Ttelmah
Guest







PostPosted: Tue Nov 22, 2005 8:02 am     Reply with quote

First comment. Which HEDS5500?. For the -A version, 3500RPM, is faster than the encoder itself is rated.
Even with the -A version, you need to be checking that the signals are switching to the levels needed by the port inputs at full speed. Remember the RB4:7 pins, have schmitt trigger inputs, and must therefore go from 0.2Vdd to 0.8Vdd, for an edge to be seen. Many TTL outputs, will not guarantee this, only going up to perhaps 0.6Vdd, when switching quickly. The output timings for the decoder you are using, are for it reaching 2.4v, not the 4v needed by the PIC's inputs. I'd suspect this is actually the core of your problem, and adding a buffer with better input sensitivity might make it all work.
For full quadrature decoding, you have to count four 'edges' for every line on the encoder. At 3500RPM, on the -C version (100 lines), you would have edges at (3500*100*4)/60 times per second. This corresponds to about every 85 instruction cycles. The code you have posted is a version I developed some time ago, and should handle this rate (though I'd run the chip at 40MHz, to give more margin).

Best Wishes
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Tue Nov 22, 2005 8:04 am     Reply with quote

I only have one pair of encoders connected to rb0 and another pin. I have a tmr1, rb0, and tmr3 isr running. What i do before leaving the tmr1 and tmr3 isr is:

Code:

#int_timer1
void tmr_isr(void)
{
   ...
   if (rb0 interrupt flag is set)
   {
      rb0_isr_routine();
   }
}

#int_ext
{
    rb0_isr_routine();
}


No fast interrupt routines are used, and i seem to get away with it. Remember, with a rb0 interrupt, all you have to do is to do a 'dummy read' of rb0, and it automatically clears the flag.

If 20Mhz isn't enough, have you considered using 40MHz? or even 10MHz with PLLx4 speedup enabled to give you 40MHz?

If i had to start from the beginning, I would do as sseidman says and use two 18f4431 chips.

As an alternative, isn't it possible to feed one pair of encoders into your QEI, and another pair to go thru some flipflop logic and go to either tmr1 or tmr3 as external timer inputs?
Mi
Guest







PostPosted: Tue Nov 22, 2005 9:24 pm     Reply with quote

hi Ttelmah,
Thank you very much for your reply and your answer.
Sorry my encoder is HEDM5500J.
if I use crystal 10Mhz and PLL x 4 i can capture position with the speed increase two time.
I try to see the signal output with full speed from encoder is 0 - 4.8V and frequancy 100khz , i think is not problem with hardware.
do you have an other method to capture the position with int_Rb?

Thank you.
Ttelmah
Guest







PostPosted: Wed Nov 23, 2005 5:19 am     Reply with quote

So you have switched to using the HEDM, rather than the HEDS you originally referred to?.
Frequency, should not be 100KHz. At 3500RPM, the frequency should be (3500*1024)/60 = 59733Hz. If you are reading 100KHz, then it implies you are either well over 3500RPM, or have a lot of innacuracy somewhere in your test setup...
Now if the signal is at 100KHz, this implies quadrature decoding at 400000 times per second (remember the quadrature signals are both the rising, and falling edges of _both_clocks). Even at 40Mhz, this gives only 25 instruction times between the edges. This is beyond the capabilty of a PIC to manage. In fact if you are getting to even half this rate (50 instruction times), you are pretty much flat out, and would not have time to do anything much else.
Other posters have mentioned the possibility of using a PIC, with hardware quadrature decoders built in, another possibility is the LS7166, which is designed for this sort of job.
Do you really need this level of resolution?. Potentially you are reading the position in 0.088 degree steps. Unless you shaft is held very rigidly, with high quality bearings, you are unlikely to get repeatable operation at this sort of accuracy level, and the whole problem becomes a lot easier if you reduce the encoder accuracy. With a 100 line encoder, you still get better than 1 degree step size, and the data rate is only 1/10th of what you are using. Alternatively, switching to using single edge detection (a rising or falling interrupt on just one of the signals), reduces the data rae to just 1/4 the current level.
Realistically, you are trying to do something, that is beyond the abilities of the hardware you are using, and need to 'think again'.

Best Wishes
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