|
|
View previous topic :: View next topic |
Author |
Message |
sseidman
Joined: 14 Mar 2005 Posts: 159
|
Seeking device suggestion--controller w/ 2 asynch counters |
Posted: Thu Mar 24, 2005 8:06 am |
|
|
I'm doing a motor control project, w/ a dc brush motor that goes 10000 rpm, and a 512 count (that's x1) magnetic quad encoder.
I'm taking the quad encoder, and running it into an LS7183, which provides a count up pulse and a count down pulse. I'm running each of those outputs to timer clock inputs on an 18f252. I'd like to use two asynch counters, but because timer 1 and timer 3 share a clock input, I'm not sure how to do this, so I'm currently forced to use Timer0 and Timer1. They just don't count the same-- timer 0 seems to be the culprit, missing ticks because its a synchronous counter--This is the case, even though I'm 4x clocking at 40MHz.
Any suggestions for a device that has separate clock inputs for two asynch counter/timers? The obvious answer, of course, is dsPIC motor control chips, but I don't want to have to switch development platforms. BTW, any word on the release date of CCS dspic support??
Thanks in advance,
Scott |
|
|
bluetooth
Joined: 08 Jan 2005 Posts: 74
|
|
Posted: Thu Mar 24, 2005 8:42 am |
|
|
I am doing exactly this with a 900 line encoder at about half the speed using a 18F1320 at 32 MHz. Works fine.
I don't think the synchronization of Timer0 is the problem - unless I figured this wrong, your signals come in at about 85 KHz at full speed, which has a period of about 12 uS. Two Tcy's at 40 MHz/4 is 200 nS.
With the info given, I would suspect the input signal or your code that's computing the actual net encoder counts.
Can you:
1. Switch the two (Timer0/Timer1) to see if the problem stays with Timer 0?
2. Put an external event counter on Timer0 input and compare the results from your external measurement and the contents of Timer0?
3. Connect your "up" signal to both inputs and compare, then your "down" signal to both inputs and compare.
It would also be useful to know by how much the count is off.... and a look at your code to see how you're handling the counts might help as well.
Just some thoughts.... |
|
|
sseidman
Joined: 14 Mar 2005 Posts: 159
|
|
Posted: Thu Mar 24, 2005 12:12 pm |
|
|
Thanks for the suggestions. A couple of clarifications: I'm using the 7183 in 4x mode, so signals come in 4x faster than the 85K. I've X1 mode, also without success.I use a 5K resistor to tune the ouptut pulse size to about 100 ns by their spec sheet, but I haven't confirmed the pulse size on a scope yet-- I should have plenty of headroom though. The 7183 provides a negative pulse, but I have the same problem even if I run off an inverter.
When driving T0 ant T1 off the same waveform, it's actually T1(that was surprising) that comes up 1 or 2 counts short on just about every displayed count (and I'm displaying every 300 polls, polling at about 1K.
I haven't tried an external counter. I might take that route if I can't fix this problem, but once I have external asynchronous counters, I can jsut take the data right off of them, bypassing this problem.
Here's the code snippets. I'm driving the samples off of Timer 3 ISR. I use AN0 (device set to 10 bits) as a command, polling every time the position count is updated. B0 and B1 are direction controls. The motor is driven off of a L293 bridge. I have a PWM deadband in the code for dealing with motor sticktion.
Thanks again.
#int_TIMER3
TIMER3_isr()
{
t0value=get_timer0();
t1value=get_timer1(); //get counter values
set_timer1(0); //rezero counters
set_timer0(0);
set_timer3(10082);
readflag=1; // set flag stating got new position
}
void main()
{
int direction;
signed int32 position=0;
unsigned int8 P=100; //proportional control
unsigned int16 adtarget=0, tmp=0, command;
signed int32 target;
signed int32 poserror;
int16 deadband=130; // deadband for PWM width
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_1);
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
setup_timer_3(T3_INTERNAL | T3_DIV_BY_1);
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1,255,1); //PWM on C2
enable_interrupts(INT_TIMER3);
enable_interrupts(GLOBAL);
set_ADC_channel(0);
set_timer1(0);
set_timer0(0);
delay_ms(10);
set_timer3(64535);
while (1)
{
if (readflag==1){
readflag=0; // reset read flag
icount++; // increment counter for printf display
//get command position
adtarget=read_adc();
target=((signed int32)adtarget*50);
position=position+(signed int32)t0value-(signed int32)t1value; // update position
poserror=(signed int32)(target)-(signed int32)position;
// brake if error small
if (abs(poserror) < 5){
output_bit(PIN_B0,0);
output_bit(PIN_B1,0);
}
else{
(poserror < 0) ? (direction=0) : (direction=1);
output_bit(PIN_B0,direction);
output_bit(PIN_B1,!direction);
}
command=p*abs(poserror)/100;
command=command+deadband;
(command<1023) ? (delay_us(1)) : (command=1023);
set_PWM1_duty(command);
if (icount==300){
printf(" timer: %ld %ld %ld %lu \n\r", poserror, position, target, command);
//printf(" timer: %ld %lu %lu \n\r", position, t0value, t1value );
icount=0;
}
}
}
} |
|
|
bluetooth
Joined: 08 Jan 2005 Posts: 74
|
|
Posted: Thu Mar 24, 2005 3:32 pm |
|
|
A couple of things:
1. I still don't think the synch thing is a problem, even @ 4x. 3 uS vs. 200 nS.
2. When I computed my 32 bit position, I did it by establishing a signed difference between the counters, with the counter values specified as unsigned - as in:
Code: |
(signed long) delta = (unsigned long) get_timer0() - (unsigned long) get_timer1();
|
I then do this:
Code: |
if (delta != last_delta)
{
actpos += (signed int32) ((signed long)delta - (signed long)(last_delta));
last_delta = delta;
}
|
This seems to work very well.
3. For no specific reason, I would lengthen the pulses past 100 nS, maybe to 500 nS. Just seems safer.
4. By external counter, I meant a bench instrument - not more parts! The method you are using should work!
Maybe some of this will help.... |
|
|
Hans Wedemeyer
Joined: 15 Sep 2003 Posts: 226
|
Re: Seeking device suggestion--controller w/ 2 asynch counte |
Posted: Sat Mar 26, 2005 11:55 pm |
|
|
sseidman wrote: | Timer0 and Timer1. They just don't count the same-- timer 0 seems to be the culprit, missing ticks because its a synchronous counter-- |
You should have received a compiler error. RTCC_DIV_1 is not valid !
Timer0 prescaler can only be set to Divide by 2 or more so the minimum is
RTCC_DIV_2 i.e. divide by 2
Timer1 can count every pulse !
So yes it's correct to say "They just don't count the same" ! |
|
|
bluetooth
Joined: 08 Jan 2005 Posts: 74
|
Re: Seeking device suggestion--controller w/ 2 asynch counte |
Posted: Sun Mar 27, 2005 12:20 am |
|
|
Quote: |
Timer0 prescaler can only be set to Divide by 2 or more so the minimum is
RTCC_DIV_2 i.e. divide by 2
|
So true about the prescaler.... but RTCC_DIV_1 *is* valid.
But if PSA (T0CON:3) = 1, then the prescaler isn't used.
They should count the same if PSA = 1 and all other things are equal!
BTW - the diagram in most 18F data sheets has the PSA function depicted backwards from the register description.... the register description is the correct one. |
|
|
Hans Wedemeyer
Joined: 15 Sep 2003 Posts: 226
|
Re: Seeking device suggestion--controller w/ 2 asynch counte |
Posted: Mon Mar 28, 2005 6:01 pm |
|
|
bluetooth wrote: | Quote: |
Timer0 prescaler can only be set to Divide by 2 or more so the minimum is
RTCC_DIV_2 i.e. divide by 2
|
So true about the prescaler.... but RTCC_DIV_1 *is* valid.
But if PSA (T0CON:3) = 1, then the prescaler isn't used.
They should count the same if PSA = 1 and all other things are equal!
BTW - the diagram in most 18F data sheets has the PSA function depicted backwards from the register description.... the register description is the correct one. |
Your are correct: I got burned again by CCS help
mode may be one or two of the constants defined in the devices .h file.
RTCC_INTERNAL, RTCC_EXT_L_TO_H or RTCC_EXT_H_TO_L
RTCC_DIV_2, RTCC_DIV_4, RTCC_DIV_8, RTCC_DIV_16, RTCC_DIV_32, RTCC_DIV_64, RTCC_DIV_128, RTCC_DIV_256
PIC18XXX only: RTCC_OFF, RTCC_8_BIT
One constant may be used from each group or'ed together with the | operator. |
|
|
TSchultz
Joined: 08 Sep 2003 Posts: 66 Location: Toronto, Canada
|
|
Posted: Tue Mar 29, 2005 7:28 am |
|
|
As a deviation you may want to look at the Renesas M16C families. Some of the devices actually have on-chip peripherals arranged to directly handle the motor control with the quadrature encoder with very little software required. The starter development tools, with C compiler and ICD, are very low cost (US$49) and is worth taking a look at for motor control.
Don't get me wrong, I like the PIC, but I find some of the other device families better suited to certain applications. If you carefully design the software much of it can be easily ported between the micro families with only the low level stuff having to change. I have yet to find a micro family that fits all applications well, I do keep hoping though. |
|
|
sseidman
Joined: 14 Mar 2005 Posts: 159
|
|
Posted: Sat Apr 09, 2005 11:03 am |
|
|
Thanks for all the suggestions. I think the original problem was probably noise in my prototyping environment. I decided to not address it, and went with the HCTL2020 to deal with the quadrature, and parallel shifting in the 16 bit word for position in two steps. The 2020 has a great noise filter on the quadrature decoding. To deal with the extra DIO, I jumped up to the 18f452. I'm going with the parallel read to avoid using an extra chip to figure out whether to increment a count up or count down timer.
So I don't have to deal with cascading, I'm resetting the counter on the 2020 after each read--- I might lose a tick now and again, but its still much better than what I had going.
Also, lo and behold, the 18f2331 has encoder inputs, with noise filters similar to the hctl2020!! I didn't notice this in the microchip selection guide. I have a sample arriving soon. It would save me on DIO, and it might make the carryover easier to deal with.
BTW, this whole thing started because all the servo controllers I could find offer only 10-bit resolution on the analog command in, and I need 12. I guess if you want something done right ....
In any case, so far the hctl2020 gets my vote over the ls7183. The 18f2331 might be the best solution, but I haven't tried it yet. It would be great if the Quad inputs for this chip showed up in the selection table. |
|
|
|
|
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
|