|
|
View previous topic :: View next topic |
Author |
Message |
cheezy1963
Joined: 08 Feb 2012 Posts: 3
|
Help with motor feedback/delay |
Posted: Wed Feb 08, 2012 4:43 pm |
|
|
I have a DC motor that provides location feedback via a 10K pot. What I'm trying to do is determine/learn how often to check the motor for movement without using an arbitrary amount for delay. My assumption was that I could track the initial movement and store/use the highest delay but that doesn't work. I tried tracking time over movement and that doesn't work either. Both methods yield a delay less than 80ms which is too low. When I tested using fixed amounts of delay, I found that 130ms seems to be the sweet spot. I can't understand why my code below produces 80ms while the real value is closer to 130ms. Device is a PIC16LF88.
Here is the circuit below:
Code: |
----------> to AN3 pin 2
|
|
|
| 10K
4.7K | pot
+5v ---x----/\/\/\------x----/\/\/\---x---> to AN4 pin 3
| | |
| | |
| GND --- |
| - |
| 4.7K |
--------/\/\/\------------------
|
Here is the simplified code used for testing:
Code: |
#include <16F88.h>
#device adc=10
#FUSES NOWDT
#FUSES INTRC_IO
#FUSES PUT
#FUSES BROWNOUT
#FUSES NOLVP
#FUSES NOWRT
#FUSES NOPROTECT
#FUSES CCPB3
#use delay(clock=8000000)
int16 number = 0;
int1 movement_set = 1;
int16 last_movement = 0;
int16 old_movement = 0;
int16 movement_count = 0;
int16 movement_delay = 0;
int1 delay_error = 0;
int16 check_input(int8 channel)
{
int16 value = 0;
set_adc_channel(channel);
delay_us(20);
value = read_adc();
return(value);
}
void stop_motor(void)
{
set_pwm1_duty(0);
delay_ms(250);
}
void start_motor(int1 direction)
{
int8 i = ((199 + 1) / 10) - 1;
if(direction)
{
output_low(50);
}
else
{
output_high(50);
}
delay_ms(50);
while(i < 199 + 1)
{
set_pwm1_duty(i);
delay_ms(100);
i = i + ((199 + 1) / 10);
}
}
void main(void)
{
setup_adc_ports(sAN3|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_16);
setup_spi(SPI_SS_DISABLED);
setup_timer_2(T2_DIV_BY_1,199,1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(0);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(OSC_8MHZ|OSC_INTRC);
output_low(46);
output_low(50);
while(1)
{
if(!input(53) && !delay_error)
{
number = 0;
start_motor(1);
while(!input(53))
{
//hold the switch for a 5-10 seconds
if(!movement_set)
{
old_movement = check_input(3);
//**this is the amount of delay I'm trying to find**
delay_ms(movement_delay);
last_movement = check_input(3);
if(last_movement == old_movement)
{
delay_error = 1;
output_high(46);
break;
}
}
else
{
//find the amount of delay to use
movement_count = 0;
old_movement = check_input(3);
last_movement = old_movement;
while(last_movement == old_movement)
{
delay_ms(10);
last_movement = check_input(3);
movement_count += 10;
}
if(movement_count > movement_delay)
{
movement_delay = movement_count;
}
}
}
stop_motor();
if(movement_delay > 0 && movement_set)
{
number = movement_delay;
movement_set = 0;
}
}
if(!input(52))
{
//hold switch to return motor to starting position
number = 0;
delay_error = 0;
output_low(46);
start_motor(0);
while(!input(52))
{
delay_ms(1);
}
stop_motor();
}
if(number)
{
//function to blink led showing value for movement_delay
show_number(number);
}
}
}
|
Any help would be appreciated. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Thu Feb 09, 2012 4:23 am |
|
|
The first thing is 'why' the complex resistor circuit round the pot?.
As it stands all this does is lose you resolution on your position. The output to AN3, can vary from 0v, if the wiper is right at the left edge of the pot, to 3.4v, when the wiper is at the other end. Effectively giving just 2/3rd of the range of the ADC being used, and wasting half a bit of potential resolution.
Then, the output impedance if this circuit when in the middle of the swing, is above the recommended value for the source impedance to feed the ADC (2.5KR on your chip). This slows the ADC response time.
So simplify. Just have something like a 2.2K pot, connected between 5v, and ground, and feed the wiper to the ADC input you want to use.
You'll then get more ADC resolution, and the potential to 'see' movements over smaller angles.
Second comment. You are basic movement on simply looking at the last position versus the current. Hence you need significant time between the samples to 'see' movement. Two things come to mind. This risks 'hunting', with the ADC input seeing noise as a movement, and responses not happening immediately. Consider summing samples at a much faster interval, and looking at the sum of (say) the last eight samples as the basis of your position. This has the advantage of potentially smoothing purely random noise, but also seeing a small trend much quicker.
Best Wishes |
|
|
cheezy1963
Joined: 08 Feb 2012 Posts: 3
|
|
Posted: Thu Feb 09, 2012 10:59 am |
|
|
Thanks for your help.
The complex resistor circuit is part of the legacy design. The original motor did not provide resistive feedback. Instead, it had limit switches
which closed (switched to ground) to indicate full travel. The resistors are pull-up resistors for that design. The new design is to include support for both the older motor with limit switches and the newer motor that has resistive feedback. I will have to look at the chip docs again, I understood the max impedance to be 10K.
So you think when I'm sampling at a high rate, it sees the noise as movement? Seems very possible. Something I overlooked because I considered the motor movement to be slow since it takes approx 15 seconds for full extension of the motor. I will try your 'summing' idea and see if I can get that to work.
Here is the old circuit for reference:
Code: |
----------> to RA3 pin 2
|
|
|
| limit
4.7K | switch
+5v ---x----/\/\/\------x----> x <--x---> to RA4 pin 3
| | |
| | |
| GND --- |
| - |
| 4.7K |
--------/\/\/\------------------
|
|
|
|
cheezy1963
Joined: 08 Feb 2012 Posts: 3
|
|
Posted: Mon Feb 13, 2012 9:43 pm |
|
|
Problem solved. It was a noise problem. thanks again Ttelmah. |
|
|
|
|
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
|