Lance, your fix works perfectly! Rock solid on and off in both directions. all the flutter is gone!symbol bReverseForward=bit1 ' 0=reverse,=forward
This should go after the symbol statement for bit0
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.introduce a new variable symbol Speed = w5
Bravo. That's the biggest step in the process.I'm FINALLY understanding what we're doing
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.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.
We call it a shadow-bot.Gramps- what are you making?
Why do we needsymbol 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
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_).Why do we need
symbol bReverseForward=bit1 ' 0=reverse,1=forward
When you have:
symbol REVERSE_=0
symbol FORWARD_=1
Symbolise the Variables (b1, b2, w1, etc.)
Next, symbolise the "Magic Numbers" Constants
Symbolising the PICaxe Pins
For the guy with the inch long memory (me) this system is a must!Finally, there are "Boolean" symbols, sometimes pre-defined in the Editor/Compiler
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
Instead use:In PICAXE BASIC, the bit values can't be used directly to set pins,
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?
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:Correct?
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
low Direction ' go in reverse
bReverseForward = REVERSE_
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.Can't wait to get back and connect the feedback pot on the elbow
Did I get it right that this code needs to be inserted to replace this pseudo-code?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
'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
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).Did I get it right that this code needs to be inserted to replace this pseudo-code?
if diff < 6 then
pwmout MOTOR, 199, 0' STOP
Is this it?was replaced by the diff calculation
Code:
if diff < 6 then
pwmout MOTOR, 199, 0' STOP
Can your desired_pot_value be beyond the limit? If so, you could set high and low limits to that value.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.
Yes, only about 2/3's of the pot range is used.Can your desired_pot_value be beyond the limit?
Yes, exactly. Like this?If so, you could set high and low limits to that value.
Sorry bout' that. They are still there but I didn't copy and paste them. Yes b3 is the value of the feedback pot.Those SYMBOL names have "vanished" again !
66??Lance suggested in #66).
That sounds like a cool way to do it but also sounds like Advanced code.it would probably be best to implement the slowdown of the motor.
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.sounds like Advanced 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
else
if desired_pot_value <> prior_desired_pot_value then
prior_desired_pot_value=desired_pot_value
pwmout MOTOR, 199, 399 ' full speed
endif
Sorry, it was post #56 :Yes b3 is the value of the feedback pot.
66??
And I described the "proportional" control of motor speed in #31 :Can your desired_pot_value be beyond the limit? If so, you could set high and low limits to that value.
Cheers, Alan....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 .
No, it does not overshoot in actual operation., do you still have overshoot?
Had originally planned 2 set the minimum and maximum limits on the feedback pot rather than the desired pot.As allyCat noted, you still should use MIN and MAX to set your limits on desired_pot_value when you read the pot
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.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?
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?
BELOW: Working Code before adding limits:Code:Symbol MIN ENDSTOP_A = desired_pot MIN Symbol MAX ENDSTOP_C = desired_pot MAX
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
No, the endstops are actual numbers, for example :"after symbolising the limits" Like this?
Code:Symbol MIN ENDSTOP_A = desired_pot MIN Symbol MAX ENDSTOP_C = desired_pot MAX
Symbol ENDSTOP_A = 70 ; desired_pot MIN (Text after the semicolon is just a comment)
Symbol ENDSTOP_C = 200 ; desired_pot MAXimum value
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
#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
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.Couple of questions,
Why is
'INIT: pwmout MOTOR, 199, MAXPWMVALUE 'Energize Motor controller
Commented out?
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".Why must we have two endif's after elseif?
Will not compile without both present.......
Because elseif and if both need an endif?
Great.After correcting the sertxd commands, the terminal window tracks the pots perfectly!
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.Edit; can we slow down the number of readings without slowing down the whole program?
Right.you can comment out the SERTXD commands.
FixedYou don't need the second one.
MovedYou might (or might not) want to move the line with MIN and MAX up immediately
Any ideas to fix my Sputter??Overall operation is steady except as the motor closes in on the limits it "sputters" or turns off and on repeatedly..
Sorry--I misread the following as saying that it was fixed.Any ideas to fix my Sputter??
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.After correcting the sertxd commands, the terminal window tracks the pots perfectly!
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
Yes the same problem we had on reaching the set point,is waffling in the READADC
Thanks that looks like what we need.Untested
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.This is an argument for the slow-down method recommended by AllyCat. ......