Test circuit for MD20A with feedback pot

Gramps

Senior Member
Lance you're trying to make me think I appreciate that and thank you Alan for your explanation. After I posted I realized the only thing that can change the direction Code moves is a variable.
 

Gramps

Senior Member
symbol bReverseForward=bit1 ' 0=reverse,=forward
This should go after the symbol statement for bit0
Lance, your fix works perfectly! Rock solid on and off in both directions. all the flutter is gone!
Can't wait to get back and connect the feedback pot on the elbow.

introduce a new variable symbol Speed = w5
Alan, this looks like a cool way to control the speed as it approaches the set point and will smooth out the shadow-bot's moments.

One thing that's really exciting is that I'm FINALLY understanding what we're doing!!!
Hoping to get the limits numbers working too, but jammed with preparations for this trip.
We are leaving tomorrow morning, so i'll be away from the hardware till next Tuesday.

Many thanks to both of you!
Gramps
 

lbenson

Senior Member
I'm FINALLY understanding what we're doing
Bravo. That's the biggest step in the process.

Sorry that my mess-up in copying the program caused confusion and delays. I'm going to go back and edit that code so that it will be right, and note that it has been edited.
 

popchops

Active member
Alan, this looks like a cool way to control the speed as it approaches the set point and will smooth out the shadow-bot's moments.
I just found this thread, which is a bit more interesting than my problem! You made a proportional controller, where you are setting the output PWM proportional to your calculated error or 'diff'. Pretty nice way of slowing down to get greater fidelity close to the setpoint.

Is there any load on the motor? Are you achieving the setpoint exactly? If not - next step would be a Proportional+Integral controller (PI). Calculate the output (motor PWM) as you are now (by scaling the diff/error by a fixed value) but then add in each iteration of the loop a tiny correction to the PWM determined by scaling the diff/error by another, different value. Set a very small scaling for this 'Integral' part, because it gets added into the PWM many times per second.

When you are far away from the setpoint, the proportional term dominates and pushes you fast to the setpoint. When you get near the setpoint, especially if there is any load on the motor, the proportional contribution will bottom out, but the integral component will add in more and more (or less and less) PWM until the setpoint is achieved exactly. Then you might be able to do away with your central dead zone, and you might be able to turn down your P scaling to approach more slowly.

small print: the P scaling and the I scaling need to be 'balanced' for stability. This is not hard - just experiment. Also, it's easily possible for the I term to ramp up very high (if the setpoint cannot be reached) so you should set a maximum limit to this part, before addition.

This is a nice project Gramps- what are you making? Pops.
 
Last edited:

Gramps

Senior Member
Pops, thanks for your suggestion!
Hope to look at it next week. I'm very slow comprehending code so bear with me.
Gramps- what are you making?
We call it a shadow-bot.
View post 43 on this thread.
Controlling a large motor with a 28X2
 

Gramps

Senior Member
symbol xb0 = b0 ' reserved for bit variables
symbol bMotorState=bit0 ' 0=off,1=on
symbol bReverseForward=bit1 0=reverse,1=forward
symbol REVERSE_=0
symbol FORWARD_=1
Why do we need
symbol bReverseForward=bit1 0=reverse,1=forward
When you have:
symbol REVERSE_=0
symbol FORWARD_=1
 

AllyCat

Senior Member
Hi,

Personally, my priority is to Symbolise the Variables (b1, b2, w1, etc.) with reasonably short but meaningful names, so that one doesn't get "confused" with what the program/calculations are actually doing. That also makes it easy to swap around the Word, Byte and Bit allocations as the program requirements develop (e.g. low numbers for the section of program presently being developed). Next, symbolise the "Magic Numbers" (constants) at the top of the program so that it's easy to adjust/optimise the hardware, etc.. I normally use Capitals for these (followed by a comment), for example symbol ENDSTOP_A = 40 ; Anticlockwise ADC Limit .

Then you can consider Symbolising the PICaxe Pins, for much the same reasons. In some cases there won't be too many to remember, but something like High RedLEDon helps anybody reading the program. The "on" might seem superfluous, but conventionally a "High" level is "true" so it might be symbolised as "RedLEDoff" if the anode of the LED was connected to the supply rail (so that an "Active Low" turns it on).

Finally, there are "Boolean" symbols, sometimes pre-defined in the Editor/Compiler such as TRUE = 1 , FALSE = 0 , etc. and perhaps for your motor: FORWARD = 1 , BACKWARDS = 0 . I'm less enthusiastic about using these; it can be a lot of typing to replace a single binary value and the name might not be correct or consistent for the whole program. For example Rev.Ed. have predefined symbols FORWARD, BACKWARDS and REVERSE etc. which do things that don't (necessarily) apply to your motor, which is why "yours" have needed to be named FORWARD_ and REVERSE_ .

The symbol bReverseForward=bit1 ; 0=reverse,1=forward (I've added a semicolon ";" to mark what I believe is a comment) is a "flag" for the program to "remember" the present (or perhaps previous) state of the motor. Naming symbols is very much a personal preference, but (at least until you begin to run out of bytes), I would probably have chosen something like symbol MotorForwardFlg = b27 and relied on the convention of 1 = True (forward) and 0 = False (reverse). Similarly there might be pins symbolised as MotorRun and MotorForward (or MotorReverse , if that's the way it's wired).

Cheers, Alan.
 

lbenson

Senior Member
Why do we need
symbol bReverseForward=bit1 ' 0=reverse,1=forward
When you have:
symbol REVERSE_=0
symbol FORWARD_=1
Yes, it is a comment after bit1. As Alan suggests, REVERSE_ and FORWARD_ are symbols for values (0 and 1 respectively). bReverseForward is a variable -- a 1-bit variable: it can hold a value of either 0 (REVERSE_) or 1 (FORWARD_).

So REVERSE_ and FORWARD_ are just convenient names for the values 0 and 1. These names give you a clue as to what those values mean in the context in which you are using them. In PICAXE BASIC, the bit values can't be used directly to set pins, with, say, "direction=REVERSE_". Instead you must use HIGH or LOW: LOW direction. But when you're talking about a variable which will save for you the current direction (so you only set the direction pin when you need to change it), you can use the symbol for the value, bReverseForward = REVERSE_.

For other contexts, you might wish to use different symbol names for the same values in the same program. For instance, if you had a phone charger (5v) wired to a PICAXE pin (running at 5V) in a battery powered system, you could use it to determine whether mains power was available like this:

symbol mainsAvailable=pinC.6
symbol YES=1
symbol NO=0
if mainsAvailable=YES then ' ... and so on

Not everyone likes to use symbols like this. Erco writes very successful code without it. But I like the self-documenting aspect of meaningful names for constants, variables, and pins. Without them, if I were to go back and look at some of the longer PICAXE programs I have written, I would be lost without a deep dive to try to recover my thought processes at the time. For smaller programs, it's not so necessary, but I still tend to use symbolic names.
 

Gramps

Senior Member
In poet #14 I wrote:
Code:
Symbol  desired_pot = 13 'B.5
Symbol  feedback_pot = 11'B.4
Symbol MOTOR = B.0' Turn on the Motor Controlor
Symbol  FORWARD_ = B.7 'Motor CW
Symbol  REVERSE_ = B.7 'Motor CCW
Symbol STOP_ = B.0 'Motor stop
In PICAXE BASIC, the bit values can't be used directly to set pins,
Instead use:
Code:
Symbol  FORWARD_ = 0 ;  B.7 'Motor CW
Symbol  REVERSE_ = 1 ;  B.7 Motor CCW

;then replace these two symbols:

Symbol MOTOR = B.0' Turn on the Motor Controlor
Symbol STOP_ = B.0 'Motor stop

;with this!;

symbol bReverseForward=bit1

;or with what ever else you want to name it?
Correct?
 

lbenson

Senior Member
Not quite. Or at least that is incomplete. "bReverseForward" gives a name to a variable (bit1)--it can't replace MOTOR and STOP_ which are the names (different names) for a single pin. "bReverseForward" is intended to preserve the direction you have set for the motor, using (from post 33) code like this:
Code:
  if  desired_pot_value > feedback_pot_value then
    if bReverseForward = REVERSE_ then
      high Direction ' go forward
      bReverseForward = FORWARD_
    endif
  elseif  desired_pot_value < feedback_pot_value then
The first IF statement asks if we want to go FORWARD. The second one asks if we are presently in REVERSE. If we are, we need to change the direction to forward with "HIGH Direction", and then record that we are going forward by setting the bReverseForward variable to reflect what the hardware is set for: with "bReverseForward = FORWARD_".

Then if the next time through the loop it's still true that "desired_pot_value > feedback_pot_value" and we want to continue to go forward, "bReverseForward" tells us that we're not presently in reverse, so we don't need to do anything--the motor will continue forward.

But if it's not true that "desired_pot_value > feedback_pot_value" (remembering that we're still in the section of code where the diff value is such that we need to run the motor to move toward the desired_pot_value), then we come to the next IF statement: are we already in reverse? If we are, we do nothing, but if we're not, then
Code:
      low Direction ' go in reverse
      bReverseForward = REVERSE_
puts the motor in reverse and bReverseForward is set to signal (to the program at a later time) the state we are currently in (motor reversed).
 

Gramps

Senior Member
Can't wait to get back and connect the feedback pot on the elbow
Tinkering this evening, Code runs the motor nice and steady and feedback pot is pretty good too. The the motor driver is a little bumpy just before or after the set point. Perhaps we can tighten that up later.
Now to code the limit points but i've sort of lost my way since we last spoke.
[/QUOTE]
Code:
if desired_pot_value > feedback_pot_value then
if bReverseForward = REVERSE_ then
high Direction ' go forward
bReverseForward = FORWARD_
endif
elseif desired_pot_value < feedback_pot_value then
Did I get it right that this code needs to be inserted to replace this pseudo-code?
Code:
'Limit of movement
#rem
    if feedback_pot_value > 200 then
      pwmout MOTOR, off' STOP
      endif
    if feedback_pot_value < 70 then
      pwmout MOTOR, off' STOP
    endif
#endrem
 

lbenson

Senior Member
Did I get it right that this code needs to be inserted to replace this pseudo-code?
No. This code is not a limit. It determines whether you need to set the direction to either forward (HIGH Direction) or in reverse (LOW Direction), and it keeps you from repeatedly issuing a new PWMOUT when there is already one in effect (which can cause jitter).

The limiting pseudo-code was replaced by the diff calculation and
Code:
if diff < 6 then
   pwmout MOTOR, 199, 0' STOP
If the absolute difference between the feedback_pot_value and the desired_pot_value is less than 6, STOP--regardless of which direction you are travelling.
 

Gramps

Senior Member
Perhaps I didn't make clear what what i'm trying to do.
When the robot's member (elbow, shoulder, etc.) is fully extended or retracted, we want the feedback pot's reading to stop the motor in that direction, in the same way a limit switch would work.
 

lbenson

Senior Member
Perhaps I didn't make clear what what i'm trying to do.
When the robot's member (elbow, shoulder, etc.) is fully extended or retracted, we want the feedback pot's reading to stop the motor in that direction, in the same way a limit switch would work.
Can your desired_pot_value be beyond the limit? If so, you could set high and low limits to that value.
 

AllyCat

Senior Member
Hi,

Those SYMBOL names have "vanished" again ! :(

IF b3 were your "desired_pot" value then NO, you should limit that value with MAX and MIN (or you can use IF statements if you prefer). For example: desired_pot = desired_pot MIN 70 MAX 200 , or better, after symbolising the limits as I explained back in #47 : desired_pot = desired_pot MIN ENDSTOP_A MAX ENDSTOP_C , etc.

BUT, if b3 is the MOTOR (or "feedback") pot value, then yes the OFF/STOP in the code is correct (or at least one way to do it), but that's not what Lance suggested in #66).

Cheers, Alan.
 

lbenson

Senior Member
Because you have a risk of overshoot of the motor with a limit on desired_pot_value, it would probably be best to implement the slowdown of the motor (by reducing the pwm value) as you approach the desired_po_value.

Fortunately, the "diff" value that you are calculating allows a fairly easy way to do that. You will need to experiment to determine the exact comparisons to make, since it will depend on how fast your motor actually moves and how quickly your main loop processes (now and with all subsequently needed code). First determine what the slowest pwm rate is that moves your motor. Then figure out what the diff value is at which you need to start to slow down. Then figure out what pwm values you need to step down to, and how many step-down (slow down) steps you want to get a smooth transition to the exact feedback_pot_value.
 

Gramps

Senior Member
it would probably be best to implement the slowdown of the motor.
That sounds like a cool way to do it but also sounds like Advanced code.
Perhaps step-by-step we can work through this and first see if we can get the limits to work, and then add motor slowdown.
I'm currently running the project on 6 volts. it normally operates on 12 volts so we're already moving at slow speed.
 

lbenson

Senior Member
sounds like Advanced code
It is somewhat advanced. I looked at throwing some code together quickly, but it seemed like you pretty much had to do the whole job.

One thing to look at: in running at your 6 volts, with whatever diff value you have determined works, do you still have overshoot? That is, if you are moving forward because feedback_pot_value is less than desired_pot_value, once you issue the STOP, does feedback_pot_value ever end up greater than
desired_pot_value (or less than when going in REVERSE)?

If you're using "if diff < 12 then", for instance, at that point, don't issue the stop, but cut the speed in half. So you'd have something like this
Code:
if diff < 3 then
  pwmout MOTOR, 199, 0 ' stop Motor
elseif diff < 6 then
  pwmout MOTOR, 199, 100 ' slow Motor down (about a quarter of 399)
elseif diff < 12 then
  pwmout MOTOR, 199, 200 ' slow Motor down (about half of 399)
endif
You'd have to see how to bring the motor back up to speed again when the desired_pot is moved, without repeatedly issuing PWMOUT commands many times a second.
 

lbenson

Senior Member
When you move the desired_pot, is the reading stable once you let go if it or does it chatter (fluctuate back and forth a value or two with each reading)?
If it is stable, you can set it to full speed only if diff => 12 and desired_pot_value <> prior_desired_pot_value (a new variable).
So before the ENDIF in the code in the above post,
Code:
else
  if desired_pot_value <> prior_desired_pot_value then
    prior_desired_pot_value=desired_pot_value
    pwmout MOTOR, 199, 399 ' full speed
  endif
As allyCat noted, you still should use MIN and MAX to set your limits on desired_pot_value when you read the pot.
 

AllyCat

Senior Member
Hi,
Yes b3 is the value of the feedback pot.
66??
Sorry, it was post #56 :
Can your desired_pot_value be beyond the limit? If so, you could set high and low limits to that value.
And I described the "proportional" control of motor speed in #31 :
...calculate the required speed immediately after each calculation of the variable diff , for example Speed = diff * LOOPGAIN max MAXPWMVALUE . Then change all the (non-OFF) PWMOUT commands to PWMOUT MOTOR , 199 , Speed .
Cheers, Alan.
 

Gramps

Senior Member
As allyCat noted, you still should use MIN and MAX to set your limits on desired_pot_value when you read the pot
Had originally planned 2 set the minimum and maximum limits on the feedback pot rather than the desired pot.
Is setting them on the desired pot better?
 

lbenson

Senior Member
Had originally planned 2 set the minimum and maximum limits on the feedback pot rather than the desired pot.
Is setting them on the desired pot better?
Functionally there may be no difference, but if there is no overshoot I would think that setting them on the desired pot would simpler--just use MAX and MIN as AllyCat suggested to assure that the desired pot never asks for anything more than the physical limits of the system require.
 

Gramps

Senior Member
I'm getting a little lost in all the posts.

just use MAX and MIN as AllyCat suggested
IF b3 were your "desired_pot" value then NO, you should limit that value with MAX and MIN (or you can use IF statements if you prefer). For example: desired_pot = desired_pot MIN 70 MAX 200 , or better, after symbolising the limits as I explained back in #47 : desired_pot = desired_pot MIN ENDSTOP_A MAX ENDSTOP_C , etc.

"after symbolising the limits" Like this?
Code:
Symbol MIN ENDSTOP_A  = desired_pot MIN
Symbol MAX ENDSTOP_C = desired_pot MAX
BELOW: Working Code before adding limits:
Code:
'Shadow-Bot feedback control code with LBenson's improvement (working correctly)
#picaxe 28x2
#no_data
#no_table

symbol xb0 = b0 ' reserved for bit variables
symbol bReverseForward=bit1 ' 0=reverse,=forward
symbol bMotorState=bit0     ' 0=off,1=on
symbol REVERSE_=0
symbol FORWARD_=1

Symbol desired_pot_value = b1
Symbol feedback_pot_value = b3
Symbol diff=b4
Symbol  desired_pot = 13 'B.5
Symbol  feedback_pot = 11'B.4
Symbol MOTOR = B.0' Energize PWM
Symbol Direction = B.7
Symbol MAXPWMVALUE = 399

'INIT: pwmout MOTOR, 199, MAXPWMVALUE  'Energize Motor controller

Main:

    Readadc Desired_pot, b1
    sertxd (#b1," ",#w2,13,10)

    Readadc feedback_pot, b3
    sertxd (#b3," ",#w3,13,10)
    'debug
 
if desired_pot_value > feedback_pot_value then
   diff=desired_pot_value - feedback_pot_value
else
   diff=feedback_pot_value - desired_pot_value
endif
if diff < 12 then ' from 5 below a match to 5 above
  if bMotorState=1 then
    pwmout MOTOR, OFF ' STOP
    bMotorState=0
  endif
else ' motor must be set for proper direction and then activated
  if  desired_pot_value > feedback_pot_value then
    if bReverseForward = REVERSE_ then
      high Direction ' go forward
      bReverseForward = FORWARD_
    endif
  elseif  desired_pot_value < feedback_pot_value then
    if bReverseForward = FORWARD_ then
      low Direction ' go in reverse
      bReverseForward = REVERSE_
    endif
  endif
  if bMotorState=0 then
    bMotorState=1
    pwmout MOTOR, 199, MAXPWMVALUE' rotate Reverse
  endif
goto main
 

AllyCat

Senior Member
Hi,
"after symbolising the limits" Like this?
Code:
Symbol MIN ENDSTOP_A = desired_pot MIN
Symbol MAX ENDSTOP_C = desired_pot MAX
No, the endstops are actual numbers, for example :
Code:
Symbol ENDSTOP_A  = 70 ; desired_pot MIN (Text after the semicolon is just a comment)
Symbol ENDSTOP_C = 200 ; desired_pot MAXimum value
and then in main:
Code:
Readadc Desired_pot, Desired_pot_value ; (Assuming that b1 had been symbolised as "Desired_pot_value")
Desired_pot_value = Desired_pot_value MIN ENDSTOP_A MAX ENDSTOP_C
Cheers, Alan.
 

lbenson

Senior Member
Again with the meaningful names--once you have defined a symbol, you should use it.

You have:
Symbol desired_pot_value = b1
Symbol feedback_pot_value = b3

Your READADC statements should be:

Readadc Desired_pot, desired_pot_value

and

Readadc feedback_pot, feedback_pot_value

Likewise for your SERTXD statements:

sertxd (#desired_pot_value," ",#w2,13,10)

and

sertxd (#feedback_pot_value," ",#w3,13,10)

(And where did w2 and w3 come from in the SERTXD statement? I can't see that they are given values anywhere. What are they intended to represent? If they are used, they should also be given meaningful names with symbol statements.)
 

Gramps

Senior Member
Shadow-Bot feedback control code updated (i think) as per posts #69 & 70
Results
We had to adjust the limit numbers and it was easy because they were Symbol-ed!
Overall operation is steady except as the motor closes in on the limits it "sputters" or turns off and on repeatedly..
However, no over shoot at all!

Code:
#picaxe 28x2
#no_data
#no_table

symbol xb0 = b0 ' reserved for bit variables
symbol bReverseForward=bit1 ' 0=reverse,=forward
symbol bMotorState=bit0     ' 0=off,1=on
symbol REVERSE_=0
symbol FORWARD_=1

Symbol desired_pot_value = b1
Symbol feedback_pot_value = b3
Symbol diff=b4
Symbol  desired_pot = 13 'B.5
Symbol  feedback_pot = 11'B.4
Symbol MOTOR = B.0' Energize PWM
Symbol Direction = B.7
Symbol MAXPWMVALUE = 399
Symbol ENDSTOP_A  = 35 ; desired_pot MINimum value
Symbol ENDSTOP_C = 210 ; desired_pot MAXimum value

'INIT: pwmout MOTOR, 199, MAXPWMVALUE  'Energize Motor controller

Main:
  Readadc Desired_pot, desired_pot_value
    sertxd (#desired_pot_value," ",#b1,13,10)
    Readadc feedback_pot, feedback_pot_value
    sertxd (#feedback_pot_value," ",#b3,13,10)
  Readadc Desired_pot, Desired_pot_value
    Desired_pot_value = Desired_pot_value MIN ENDSTOP_A MAX ENDSTOP_C

if desired_pot_value > feedback_pot_value then
   diff=desired_pot_value - feedback_pot_value
   else
   diff=feedback_pot_value - desired_pot_value
endif
if diff < 12 then ' from 5 below a match to 5 above
  if bMotorState=1 then
    pwmout MOTOR, OFF ' STOP
    bMotorState=0
  endif
else ' motor must be set for proper direction and then activated
  if  desired_pot_value > feedback_pot_value then
    if bReverseForward = REVERSE_ then
      high Direction ' go forward
      bReverseForward = FORWARD_
    endif
  elseif  desired_pot_value < feedback_pot_value then
    if bReverseForward = FORWARD_ then
      low Direction ' go in reverse
      bReverseForward = REVERSE_
  endif
  endif
  if bMotorState=0 then
    bMotorState=1
    pwmout MOTOR, 199, MAXPWMVALUE' rotate Reverse
  endif
endif

goto main
 

Gramps

Senior Member
Couple of questions,
Why is
'INIT: pwmout MOTOR, 199, MAXPWMVALUE 'Energize Motor controller
Commented out?
Why must we have two endif's after elseif?
Will not compile without both present.......
Because elseif and if both need an endif?
 

Gramps

Senior Member
After correcting the sertxd commands, the terminal window tracks the pots perfectly!

Edit; can we slow down the number of readings without slowing down the whole program?
 
Last edited:

lbenson

Senior Member
Couple of questions,
Why is
'INIT: pwmout MOTOR, 199, MAXPWMVALUE 'Energize Motor controller
Commented out?
If upon startup the "diff" value is within your stop band, you don't need to start the motor. If diff is outside the stop band, the code will set the direction properly and then turn on the motor.

Why must we have two endif's after elseif?
Will not compile without both present.......
Because elseif and if both need an endif?
There are "nested" IFs. Each must have an ENDIF. The ELSEIF doesn't need its own ENDIF, but the IF for which it is an ELSE does. The first of the two ENDIFs which are there as one line after another should have two more spaces of indentation to show that it is the end of the block which begins with "if bReverseForward = FORWARD_ then".
 

lbenson

Senior Member
After correcting the sertxd commands, the terminal window tracks the pots perfectly!
Great.

Edit; can we slow down the number of readings without slowing down the whole program?
Can be done, but could be tricky (you could put in a loop counter and only perform the READADCs and tests every nth pass through the loop). What is the problem you face with the number of times you are reading the sensors? If the program is working as you intend, you can comment out the SERTXD commands.
 

lbenson

Senior Member
I see you have this statement twice: Readadc Desired_pot, Desired_pot_value

You don't need the second one. You might (or might not) want to move the line with MIN and MAX up immediately after the Readadc Desired_pot, before the SERTXD for the value you have read.
 

lbenson

Senior Member
Any ideas to fix my Sputter??
Sorry--I misread the following as saying that it was fixed.
After correcting the sertxd commands, the terminal window tracks the pots perfectly!
The only thing that I can see offhand that would cause sputter is waffling in the READADC for feedback_pot or desired_pot which would cause diff to vary between 11 and 12 (or greater) until the motor moves far enough so that it stays in the stop range.

This is an argument for the slow-down method recommended by AllyCat. Try this replacing "if diff < 12" through "else" after first defining a new bit variable "symbol bSlowState=bit2":

Code:
if diff < 12 then ' from 11 below a match to 11 above
  if bMotorState=1 then
    if diff > 4 then ' this value may need to be set experimentally
      if bSlowState = 0 then
        bSlowState = 1 ' note that we are in the "slow speed" state
        pwmout MOTOR, 199, 200 ' slow down to half speed (change to 100 if necessary)
      endif
    else
      pwmout MOTOR, OFF ' STOP
      bMotorState=0
      bSlowState = 0
    endif
  endif
else ' motor must be set for proper direction and then activated
Untested because I don't have the gear. Note each of the comments--you may need to make adjustments based on the behavior you see.[/code]
 

AllyCat

Senior Member
Hi,
This is an argument for the slow-down method recommended by AllyCat. ......
The PWM can give a "fine" control of the motor speed and the READADCs give a good indication of the "correction" (amount of movement) required. Therefore, IMHO it makes sense to implement a "Linear" (or analogue / proportional) "Servo" feedback loop. This would make the motor slow smoothly as it approaches the "desired" (i.e. diff = 0) position.

The current "state of the art" appears to be that the motor should slow down (from a maximum PWM value of 339) when diff is less than 12 (symbolised as MAXPWMVALUE). Thus the "LOOPGAIN" that I described back in #26 and #31 would be about 339 / 11 = 30. So if we multiply the present "error signal" (diff) by the LOOPGAIN, apply a MAX of 339 and send that to the PWM modulator, then above about 11 the motor will run at "full speed", but below that value the motor slows down smoothly, potentially to zero at zero diff.

There might be minor complications at very low diff (or PWM duty cycle) values, when the motor may not drive (or more specifically may not start turning due to static friction), but that could be solved by adding a MINPWMVALUE if necessary.

Cheers, Alan.
 
Top