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

Help with motor feedback/delay

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



Joined: 08 Feb 2012
Posts: 3

View user's profile Send private message

Help with motor feedback/delay
PostPosted: Wed Feb 08, 2012 4:43 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Feb 09, 2012 4:23 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Feb 09, 2012 10:59 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Feb 13, 2012 9:43 pm     Reply with quote

Problem solved. It was a noise problem. thanks again Ttelmah.
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