Tripling A Picaxe Code

AllyCat

Senior Member
Hi,

You seem to have gone back to much lower values for CREEP and MAXPWMVALUE so the Creep might not keep driving properly. IIRC you were using a creep of 299 and a DEADZONE of 6 is far too large! But to go back to one of my previous comments:
That's one reason we include "comments" in the code, but unfortunately can only mark them with a ' or ; character (it's not possible to use fancy fonts inside the code window)... :
It might not be possible to change the Fonts, but it is possible to add Colour by using the "Copy for Forum" link. But I rarely use it because all the color codes can very rapidly take you to the forum's 10,000 character limit. :( However, it does help to draw attention to comments (which the PE will ignore). There are quite a lot of lines that have either been "commented out" (i.e. do nothing) or are unnecessary. I've commented out the unnecessary lines from an earlier post (I can't keep up with all of your posts at the moment). I've also added/changed two lines to lower the PWM frequency, but it seems the 28X2 probably cannot go low enough to really "jog" the motor out of "stiction" (static friction).

Rich (BB code):
'Shadow-Bot feedback control code with limits updated 11-13-20
#picaxe 28x2
#no_data
#no_table
; The next line can reduce the PWM frequency   ** NEW ** (Cannot put comments in #define lines)
#define pwmfreq PWMDIV16,
;#define pwmfreq
symbol DEADZONE = 2        ; Switch motor off (Make as small as practical)
;symbol SLOWZONE = 12      ; Slow motor down (NB: May depend on motor speed ! )
symbol MotorSpeed  = w4    ; (To replace the "300" in the present PWMOUT code)
symbol LOOPGAIN = 33       ;  i.e.  MAXPWMVALUE / SLOWZONE (= 399 / 12)
symbol PWMPERIOD = 199     ; Equivalent Max Duty Cycle is 799
;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   ; ** ONLY HALF OF THE AVAILABLE DRIVE VOLTAGE !
;Symbol bSlowState=bit2
Symbol old_feedback_value= b5
Symbol old_desired_value= b6
Symbol ENDSTOP_A = 60      ; desired_pot MINimum value
Symbol ENDSTOP_C = 210     ; desired_pot MAXimum value
Symbol CREEP = 160         ; PWM value to run slowly * HIGH ENOUGH TO START MOTOR TURNING !

Main:
  Readadc Desired_pot, desired_pot_value
    Desired_pot_value = Desired_pot_value MIN ENDSTOP_A MAX ENDSTOP_C
'    sertxd (#desired_pot_value," ",#b1,13,10)
    pause 100
    Readadc feedback_pot, feedback_pot_value
'    sertxd (#feedback_pot_value," ",#b3,13,10)
    pause 100
'  sertxd("Desired/Feedback: ",#desired_pot_value," ",#feedback_pot_value,13,10)
  If old_feedback_value<>feedback_pot_value or old_desired_value<> desired_pot_value then
    old_feedback_value=feedback_pot_value
    old_desired_value=desired_pot_value
    sertxd("Desired/Feedback: ",#desired_pot_value," ",#feedback_pot_value,13,10) 
  endif
  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 > DEADZONE then
    MotorSpeed = diff * LOOPGAIN max MAXPWMVALUE min CREEP     ; Limit range of motor speed
    if  desired_pot_value > feedback_pot_value then
      high Direction                         ; Set forward direction
    else
      low Direction                          ; Set reverse direction
    endif
;    pwmout MOTOR , PWMPERIOD , MotorSpeed   ; Slows motor within SLOWZONE
    pwmout pwmfreq MOTOR , PWMPERIOD , MotorSpeed     ; Slows motor within SLOWZONE  ** NEW **
  else
    pwmout MOTOR , OFF                       ; STOP
;   bMotorState=0      ; Not sure what these do (now)
;   bSlowState = 0     ;
  endif
goto main
Cheers, Alan.
 

lbenson

Senior Member
Why does a deadzone of 6 cause the motor to not be energized when other values don't?

I can understand if dithering of the pot readings meant movement would start and stop, but the readings shown seem to be pretty stable. Before you move on to additional motors, you might do well to follow Alan's advice and get Desired and Feedback to match exactly. Then reset the deadzone a little wider so that dithering (say desired dithers low by one while feedback dithers high by one) doesn't restart the motor.

(Alan posted while I was typing.)
 

Gramps

Senior Member
I've also added/changed two lines to lower the PWM frequency
The code was not working earlier because "goto main" was lost when cutting and pasting.
Code is up and running!:)
Observations:
The motor now has a high pitched whine. (which is kind of cool)
Motor is peppier.
Creep is working correctly!
ENDSTOPs are working well!
 
Last edited:

lbenson

Senior Member
Looking good there. Congratulations.

Now you probably need to implement some greater rigor in making backups (on and off the PC being used), for instance with date and time in, say, YYMMDDhhmm format along with notes to say what that version achieved and what still needed work:
Shadow-Bot_2011140854

Housekeeping, but it helps in the long run with a big project.
 

Gramps

Senior Member
Now you probably need to implement some greater rigor in making backups
Yes, good idea!
you might do well to follow Alan's advice and get Desired and Feedback to match exactly. Then reset the deadzone a little wider so that dithering (say desired dithers low by one while feedback dithers high by one) doesn't restart the motor
Okay. Here is Alan's beautiful cleaned up code.
Edit: We tried pasting to get the colors to paste by using "copy for forum" but the names of the colors pasted instead of the actual colors.
Looking for Alan's instructions in the thread how to "get Desired and Feedback to match exactly"
Edit: Believe it's post #30,

Code:
'Alan's cleaned up Shadow-Bot feedback control code / limits updated 11-14-20
'Note; working nice!
#picaxe 28x2
#no_data
#no_table
; The next line can reduce the PWM frequency   ** NEW ** (Cannot put comments in #define lines)
#define pwmfreq PWMDIV16,
Symbol DEADZONE = 2        ; Switch motor off (Make as small as practical)
Symbol MotorSpeed  = w4    ; (To replace the "300" in the present PWMOUT code)
Symbol LOOPGAIN = 33       ;  i.e.  MAXPWMVALUE / SLOWZONE (= 399 / 12)
Symbol PWMPERIOD = 199     ; Equivalent Max Duty Cycle is 799
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   ; ** ONLY HALF OF THE AVAILABLE DRIVE VOLTAGE !
Symbol old_feedback_value= b5
Symbol old_desired_value= b6
Symbol ENDSTOP_A = 60      ; desired_pot MINimum value
Symbol ENDSTOP_C = 210     ; desired_pot MAXimum value
Symbol CREEP = 160         ; PWM value to run slowly * HIGH ENOUGH TO START

Main:
' do
   ' gosub controlMotor1
   ' gosub controlMotor2
  '  gosub controlMotor3
' loop

controlMotor1:
  Readadc Desired_pot, desired_pot_value
    Desired_pot_value = Desired_pot_value MIN ENDSTOP_A MAX ENDSTOP_C
    pause 100
    Readadc feedback_pot, feedback_pot_value
    pause 100
  If old_feedback_value<>feedback_pot_value or old_desired_value<> desired_pot_value then
    old_feedback_value=feedback_pot_value
    old_desired_value=desired_pot_value
    sertxd("Desired/Feedback: ",#desired_pot_value," ",#feedback_pot_value,13,10)
  endif
  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 > DEADZONE then
    MotorSpeed = diff * LOOPGAIN max MAXPWMVALUE min CREEP; Limit range of motor speed
    if  desired_pot_value > feedback_pot_value then
      high Direction                ; Set forward direction
    else
      low Direction                ; Set reverse direction
    endif
    pwmout pwmfreq MOTOR , PWMPERIOD , MotorSpeed; Slows motor within SLOWZONE  ** NEW **
  else
    pwmout MOTOR , OFF                       ; STOP
  endif
goto main
 
Last edited:

Gramps

Senior Member
We increased the MAXPWMVALUE by 100 to= 499 then divided 499 by 12= 41, so we changed loopgain to 41.
Now the desied/feedback pot stops equal or one number different.
Then reset the deadzone a little wider
Raised the deadzone from 2 to 5 by increments of 1. Now the arm is stopping on the correct numbers without dithering.
However we lost our creep!
 

AllyCat

Senior Member
Hi,

To get the colours to display you may need to change the [tag] at the top of the code window to [CODE = RICH] .

IMHO the only DEADZONE values you should be considering are 0 - 2. 1 is probably the optimum, but in principle even 0 could be possible because the motor should be able to creep until the "desired" and "feedback" values are identical (i.e the same number). The only problem with that is if the ADC(s) themselves dither by one digit, so the motor may have to keep "re-adjusting" itself. Anything more than one digit of ADC dither needs to be fixed (e.g. by averaging) !

The CREEP value needs to be set high enough that the motor is always able to get to the desired position (eventually). Again, if that doesn't happen then something needs to be "fixed". Similarly, I don't see why the MAXPWMVALUE isn't 800, if not, you are just "wasting" the available drive voltage.

You might (not) have noticed that the Symbol SLOWZONE has "vanished" from the active code. That's intentional because the LOOPGAIN should be the fundamental control of how "lively" is the motor. With a very low value (probably less than 10) the arm should move mainly at the CREEP speed (a good way to check that the motor really is able to creep correctly). With large LOOPGAIN figures (certainly above about 100) the motor should move very briskly, probably overshooting the desired position initially. A small amount of overshoot is not necessarily a bad thing (it should creep back to the exact position afterwards), it's only necessary to keep the LOOPGAIN low enough to avoid instability, i.e. the motor "hunting" or continuously overshooting.

Next, it might be necessary to pay attention to the purpose of the ENDSTOPS. If it is not acceptable for the motor to slightly overshoot their positions, then you will either need to set them with some safety margin, or to introduce a similar DEADSPACE / SLOWZONE control as for the desired position (i.e. using more "diff" values to slow the approach).

Finally, why have those PAUSES crept back in? A DEBUG command would be more useful! But you nearly always want the control loop to operate as quickly as possible. If that causes too much data being sent to the diagnostics terminal, then change the code so that data is not sent on every pass around the loop, even once per second may be sufficient.

Cheers, Alan.
 

Gramps

Senior Member
change the [tag] at the top of the code window to [CODE = RICH]
OK Thanks
the only DEADZONE values you should be considering are 0 - 2.
Yup! 2 is prefect.
The CREEP value needs to be set high enough that the motor is always able to get to the desired position (eventually)
We are running CREEP at 160 and it's working nicely.
With a very low value (probably less than 10) the arm should move mainly at the CREEP speed (a good way to check that the motor really is able to creep correctly). With large LOOPGAIN figures (certainly above about 100) the motor should move very briskly,
Thanks for these numbers! Using 16 is working ok. We will experiment with them later.
(a good way to check that the motor really is able to creep correctly)
Another good tip. Thanks!
set them with some safety margin,
Yes that's what we did. Working great.
Finally, why have those PAUSES crept back in
The "novice" way of slowing down the serial terminal. (embarrassed grin)
Edit: removed pauses, now running better!

BTW This evening we successfully converted the code to control motor 2!
 
Last edited:

Gramps

Senior Member
We combined code for motor #1 and motor #2!!
The model is working in two axis now but desired pots 1 & 2 are interfering with each other.
UGH BUGS!
Code below:
Note; Rich=code, i mean code=rich! was more then 10k!
Good nite!!:sleep:
Code:
'Shadow-Bot feedback control code with two Motors

'Note: Motor #1( Symbol MOTOR)  "Shoulder left-right"

'Note; Motor #2 ( Symbol MOTOR2) "Shoulder up-down" updated 11-15-20

#picaxe 28x2
#no_data
#no_table
; The next line can reduce the PWM frequency   ** NEW ** (Cannot put comments in #define lines)
#define pwmfreq PWMDIV16,
Symbol DEADZONE = 2        ; Switch motor off (Make as small as practical)
Symbol MotorSpeed  = w4    ; (To replace the "300" in the present PWMOUT code)
Symbol LOOPGAIN = 33       ;  i.e.  MAXPWMVALUE / SLOWZONE (= 399 / 12)
Symbol PWMPERIOD = 199     ; Equivalent Max Duty Cycle is 799
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   ; ** ONLY HALF OF THE AVAILABLE DRIVE VOLTAGE !
Symbol old_feedback_value= b5
Symbol old_desired_value= b6
Symbol ENDSTOP_A = 60      ; desired_pot MINimum value
Symbol ENDSTOP_C = 210     ; desired_pot MAXimum value
Symbol CREEP = 160         ; PWM value to run slowly * HIGH ENOUGH TO START

Main:
  do
   ' gosub controlMotor1
   ' gosub controlMotor2
  '  gosub controlMotor3
  loop

controlMotor1:
  Readadc Desired_pot, desired_pot_value
    Desired_pot_value = Desired_pot_value MIN ENDSTOP_A MAX ENDSTOP_C
    'pause 100
    Readadc feedback_pot, feedback_pot_value
   ' pause 100
  If old_feedback_value<>feedback_pot_value or old_desired_value<> desired_pot_value then
    old_feedback_value=feedback_pot_value
    old_desired_value=desired_pot_value
    sertxd("Desired/Feedback: ",#desired_pot_value," ",#feedback_pot_value,13,10)
  endif
  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 > DEADZONE then
    MotorSpeed = diff * LOOPGAIN max MAXPWMVALUE min CREEP; Limit range of motor speed
    if  desired_pot_value > feedback_pot_value then
      high Direction                ; Set forward direction
    else
      low Direction                ; Set reverse direction
    endif
    pwmout pwmfreq MOTOR , PWMPERIOD , MotorSpeed; Slows motor within SLOWZONE  ** NEW **
  else
    pwmout MOTOR , OFF                       ; STOP
  endif

; The next line can reduce the PWM frequency
'#define pwmfreq PWMDIV16,
Symbol DEADZONE2 = 2        ; Switch motor off (Make as small as practical)
Symbol MotorSpeed2  = w9         'was w4 
Symbol LOOPGAIN2 = 33       ;  i.e.  MAXPWMVALUE2 / SLOWZONE2 (= 399 / 12)
Symbol PWMPERIOD2 = 199     ; Equivalent Max Duty Cycle is 799
Symbol desired_pot_value2 = b11     'was b1
Symbol feedback_pot_value2 = b13    'was b3
Symbol diff2 = b14             'was b4
Symbol desired_pot2 = 9    'B.3
Symbol feedback_pot2 = 8   'B.2
Symbol MOTOR2 =  C.2         ' Energize PWM2
Symbol Direction2 =  B.6
Symbol MAXPWMVALUE2 = 800   ; ** ONLY HALF OF THE AVAILABLE DRIVE VOLTAGE !
Symbol old_feedback_value2= b15     'was b5
Symbol old_desired_value2= b16     'was b6
Symbol ENDSTOP_A2 = 105      ; desired_pot2 MINimum value
Symbol ENDSTOP_C2 = 160     ; desired_pot2 MAXimum value
Symbol CREEP2 = 160         ; PWM value to run slowly * HIGH ENOUGH TO START


controlMotor2:
  Readadc Desired_pot2, desired_pot_value2
    Desired_pot_value2 = Desired_pot_value2 MIN ENDSTOP_A2 MAX ENDSTOP_C2
   ' pause 100
    Readadc feedback_pot2, feedback_pot_value2
   ' pause 100
  If old_feedback_value2<>feedback_pot_value2 or old_desired_value2<> desired_pot_value2 then
    old_feedback_value2=feedback_pot_value2
    old_desired_value2=desired_pot_value2
    sertxd("Desired2/Feedback2: ",#desired_pot_value2," ",#feedback_pot_value2,13,10)
  endif
  if desired_pot_value2 > feedback_pot_value2 then
    diff2=desired_pot_value2 - feedback_pot_value2
  else
    diff2=feedback_pot_value2 - desired_pot_value2
  endif
  if diff2 > DEADZONE2 then
    MotorSpeed2 = diff * LOOPGAIN2 max MAXPWMVALUE2 min CREEP2; Limit range of motor speed
    if  desired_pot_value2 > feedback_pot_value2 then
      high Direction2                ; Set forward direction
    else
      low Direction2                ; Set reverse direction
    endif
    pwmout pwmfreq MOTOR2 , PWMPERIOD2 , MotorSpeed2; Slows motor within SLOWZONE  ** NEW **
  else
    pwmout MOTOR2 , OFF                       ; STOP
  endif
goto main
 
Last edited:

AllyCat

Senior Member
Hi,
How to determine which are the "unique variables"??
Some variables such as the Potentiometer positions, the "diff" and the Motor Speed (PWM) must be duplicated for each motor. Also very probably the ENDSTOP constants, but NOT the DEADZONE or PWM Frequency/Period. But then it will depend on how "similar" are the motors and their load and speed requirements. It might not be necessary to have different Variable/Constants for the LOOPGAIN, MAXPWM and CREEP, etc. but it's probably best to keep them separate at least during development. The problem with "Global" variables is that if you change one, then you may discover later that you have "broken" another part of the system that was using it.

It looks as if the hardware and software are beginning to function quite well, so it's probably time to rationalise the structure of the program. I've modified parts of the program to give a few ideas. One thing is to make the Comments (and the symbol names themselves) meaningful and UP TO DATE. If a comment says that a change needs to be (or was) made then after a reasonable time it can be removed and/or replaced with something more informative. It doesn't seem that the PWM can run slow enough in an X2 to "Jog" the motor in movement (M2s have a PWMDIV64 and lower clock frequency) but it's probably worth using a PWMDIV4. Unfortunately that can't be set by a Symbol command, which is why I had to use the #define to set it up (optionally) at the "top" of the program.

To control 3 motors at the same time you need to keep the subroutines quite "Lean", so I have commented out the SERTXD sections. Now, a single DEBUG in the complete loop might be the most efficient, but in the longer-term one might write a custom SERTXD routine that just sends a modest amount of data, perhaps just a few (different) characters for each pass around the main loop.

Personally I prefer reasonably short variable/constant names, ideally about 6 characters (but obviously that's not always possible). One of the advantages of PICaxe is that the program usually fits in a single file (not with descriptions "hidden" away in some Library, Header or Include files). So the names can be a little cryptic with comments to explain what they do, at the top of the program. IMHO "feedback_pot_value_2" etc. is getting rather long and "feedback" is not particularly meaningful. I would use ACT which can stand for Actual or Active and REQ for a Required or Requested value. Also I might use POT to indicate the pin and/or the ADC channel on which a Potentiometer is connected, and POS to represent its Position (i.e. value). So my Program statements might look more like:
READADC ReqPot1 , ReqPos1 ; Shoulder L - R
IF ReqPos1 > ActPos1 THEN
; Move Rightwards
MotorRL = 1 etc.. ; Move shoulder Right
You might even change the Motor names to "ShoulderLR" and "ShoulderUD" etc, perhaps with a digit attached to ensure that they're controlled by the correct Pot(s) and maybe MAXPWMVALUE to TOPSPEED or FULLSPEED.

Rich (BB code):
'Shadow-Bot feedback control code with two Motors
'Note: Motor #1( Symbol MOTOR)  "Shoulder left-right"
'Note; Motor #2 ( Symbol MOTOR2) "Shoulder up-down" updated 11-15-20
#picaxe 28x2
#no_data
#no_table
; The next line can reduce the PWM frequency   ** NEW ** (Cannot put comments in #define lines)
Symbol DEADZONE = 2        ; Cut power to motor (Make as small as practical)
Symbol MotorSpeed  = w4    ; SHOULDER_LR PWM value    ONE FOR EACH MOTOR
Symbol LOOPGAIN = 33       ; Rate of change between MAXPWMVALUE and CREEP SPEED
Symbol PWMPERIOD = 199     ; Equivalent Max Duty Cycle is 799
Symbol desired_pot_value = b1    ; REQuested POSition for Shoulder Left-Right
Symbol feedback_pot_value = b3   ; ACTual POSition of Shoulder Left-Right
Symbol diff = b4           ; ONE FOR EACH MOTOR
Symbol desired_pot = 13    ' ADC channel for REQuested Shoulder POT LR pin B.5
Symbol feedback_pot = 11   ' ADC channel for ACTual Shoulder POT LR pin B.4
Symbol MOTOR = B.0         ' PWM Shoulder LR Motor Drive
Symbol Direction = B.7      ; Shoulder Motor Direction 0 = Left, 1 = Right
Symbol MAXPWMVALUE = 800   ; ** ONLY HALF OF THE AVAILABLE DRIVE VOLTAGE ! NOT NOW IT ISN'T ! 
;Symbol old_feedback_value= b5
;Symbol old_desired_value= b6
Symbol ENDSTOP_L = 60      ; Shoulder POT MINimum position (Left)
Symbol ENDSTOP_R = 210     ; Shoulder POT MAXimum position (Right)
Symbol ENDSTOP_D = 60      ; Shoulder POT MINimum position (Down)
Symbol ENDSTOP_U = 210     ; Shoulder POT MAXimum position (Up)
Symbol CREEP = 160         ; PWM value to run slowly BUT HIGH ENOUGH TO ALWAYS START

Main:
  do
    gosub controlMotor1
    gosub controlMotor2
    gosub controlMotor3
    DEBUG                  ; Replace later with a custom SERTXD routine
  loop
;==============
controlMotor2:
  Readadc Desired_pot2, desired_pot_value2      ; REQuired POSition of Shoulder Down-Up
    Desired_pot_value2 = Desired_pot_value2 MIN ENDSTOP_D MAX ENDSTOP_U
    Readadc feedback_pot2, feedback_pot_value2
;  If old_feedback_value2<>feedback_pot_value2 or old_desired_value2<> desired_pot_value2 then
;    old_feedback_value2=feedback_pot_value2
;    old_desired_value2=desired_pot_value2
;    sertxd("Desired2/Feedback2: ",#desired_pot_value2," ",#feedback_pot_value2,13,10)
;  endif
  if desired_pot_value2 > feedback_pot_value2 then
    diff2=desired_pot_value2 - feedback_pot_value2
  else
    diff2=feedback_pot_value2 - desired_pot_value2
  endif
  if diff2 > DEADZONE then
    MotorSpeed2 = diff * LOOPGAIN2 max MAXPWMVALUE2 min CREEP  ; Limit range of motor speed
    if  desired_pot_value2 > feedback_pot_value2 then
      high Direction2                  ; Select UP direction
    else
      low Direction2                   ; Select DOWN direction
    endif
    pwmout PWMDIV4 MOTOR2 , PWMPERIOD , MotorSpeed2 ; 
  else
    pwmout MOTOR2 , OFF                       ; STOP
  endif
return


Cheers, Alan.
 

AllyCat

Senior Member
Hi,

There are a few typos in the above post (fortunately it was never intended to be "complete" code), for example the "diff" in the Subroutine should be diff2 . Unfortunately, when I tried to edit the text, the forum software refused to re-post the text because it was "over 10000 characters". Even after deleting a significant amount of text it still refused, so it looks as if there might be a bug. Perhaps like in the last century when the size of a MS Word.DOC would go up and down like a YoYo each time it was saved. ;)

The 10k character limit really is an annoyance now, when you can attach images of many 10s of kbytes, and the count isn't even very accurate. On several occasions I've checked a character count in Notepad++ as less than 10k, but the forum has refused it. At least the "old" forum software would tell you how many characters had to be removed, but AFAIK the "new" software doesn't give any indication, if it needs to be a few words, sentences, paragraphs, or half the document. Or possibly ALL of the bloated embedded [ code ] window, if you're foolish enough to try to post the "Rich Text" (colour) format "for the forum". :(

EDIT: I've just looked at the "image details" in post #48 and it's over half a Megabyte (540k), or the equivalent of over 50 "barred" text posts. :eek:
Actually, that information would be better posted as "text" (in a code window) anyway, because, for example we could convert tabular data like that into a graph (e.g via a Spreadsheet such as Excel). A picture might be "worth 1,000 words", but not 100k words !

Cheers, Alan.
 
Last edited:

Gramps

Senior Member
Alan thanks so much for the trim and hair cut.
Please take the beard off to!
; If old_feedback_value2<>feedback_pot_value2 or old_desired_value2<> desired_pot_value2 then ; old_feedback_value2=feedback_pot_value2 ; old_desired_value2=desired_pot_value2 ; sertxd("Desired2/Feedback2: ",#desired_pot_value2," ",#feedback_pot_value2,13,10) ; endif
Foggy brain today. Will be back later.
Gramps.
 

lbenson

Senior Member
When one desired pot is changed, both axis move!
At the least, from post 54, "diff" should be diff2.
Code:
  if diff2 > DEADZONE2 then
    MotorSpeed2 = diff * LOOPGAIN2 max MAXPWMVALUE2 min CREEP2; Limit range of motor speed
Carefully check all the code to make sure you are using the right variables for the right motor.
 

Gramps

Senior Member
"diff" should be diff2.
YES!!! FIXED IT!! Both pots can be adjusted individually or simultaneously. Tracking NICE!
Also removed the old_feedback_values and the sertxd command.
We will need code later to calibrate Motor 3 ENDSTOPS.
Now ready to incorporate Alan's short Symbols.
Code:
'Shadow-Bot feedback control code with two Motors 11-16-20
'Note: Motor #1 "Shoulder left-right"
'Note; Motor #2 "Shoulder up-down"
#picaxe 28x2
#no_data
#no_table
; The next line can reduce the PWM frequency   ** NEW ** (Cannot put comments in #define lines)
#define pwmfreq PWMDIV16,
Symbol DEADZONE = 2        ; Switch motor off (Make as small as practical)
Symbol MotorSpeed  = w4    ; (To replace the "300" in the present PWMOUT code)
Symbol LOOPGAIN = 33       ;  i.e.  MAXPWMVALUE / SLOWZONE (= 399 / 12)
Symbol PWMPERIOD = 199     ; Equivalent Max Duty Cycle is 799
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   ; ** ONLY HALF OF THE AVAILABLE DRIVE VOLTAGE !
Symbol ENDSTOP_A = 60      ; desired_pot MINimum value
Symbol ENDSTOP_C = 210     ; desired_pot MAXimum value
Symbol CREEP = 100         ; PWM value to run slowly * HIGH ENOUGH TO START

Main:
  do
    gosub controlMotor1
    gosub controlMotor2
  '  gosub controlMotor3
  loop

controlMotor1:
  Readadc Desired_pot, desired_pot_value
    Desired_pot_value = Desired_pot_value MIN ENDSTOP_A MAX ENDSTOP_C
    Readadc feedback_pot, feedback_pot_value
  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 > DEADZONE then
    MotorSpeed = diff * LOOPGAIN max MAXPWMVALUE min CREEP; Limit range of motor speed
    if  desired_pot_value > feedback_pot_value then
      high Direction                ; Set forward direction
    else
      low Direction                ; Set reverse direction
    endif
    pwmout pwmfreq MOTOR , PWMPERIOD , MotorSpeed; Slows motor within SLOWZONE  ** NEW **
  else
    pwmout MOTOR , OFF                       ; STOP
  endif
Symbol DEADZONE2 = 2        ; Switch motor off (Make as small as practical)
Symbol MotorSpeed2  = w9         'was w4    
Symbol LOOPGAIN2 = 33       ;  i.e.  MAXPWMVALUE2 / SLOWZONE2 (= 399 / 12)
Symbol PWMPERIOD2 = 199     ; Equivalent Max Duty Cycle is 799
Symbol desired_pot_value2 = b11    
Symbol feedback_pot_value2 = b13   
Symbol diff2 = b14            
Symbol desired_pot2 = 9    'B.3
Symbol feedback_pot2 = 8   'B.2
Symbol MOTOR2 =  C.2         ' Energize PWM2
Symbol Direction2 =  B.6
Symbol MAXPWMVALUE2 = 399   ; ** ONLY HALF OF THE AVAILABLE DRIVE VOLTAGE !
Symbol ENDSTOP_A2 = 105      ; desired_pot2 MINimum value
Symbol ENDSTOP_C2 = 160     ; desired_pot2 MAXimum value
Symbol CREEP2 = 100         ; PWM value to run slowly * HIGH ENOUGH TO START


controlMotor2:
  Readadc Desired_pot2, desired_pot_value2
    Desired_pot_value2 = Desired_pot_value2 MIN ENDSTOP_A2 MAX ENDSTOP_C2
    Readadc feedback_pot2, feedback_pot_value2
  if desired_pot_value2 > feedback_pot_value2 then
    diff2=desired_pot_value2 - feedback_pot_value2
  else
    diff2=feedback_pot_value2 - desired_pot_value2
  endif
  if diff2 > DEADZONE2 then
    MotorSpeed2 = diff2 * LOOPGAIN2 max MAXPWMVALUE2 min CREEP2; Limit range of motor speed
    if  desired_pot_value2 > feedback_pot_value2 then
      high Direction2                ; Set forward direction
    else
      low Direction2                ; Set reverse direction
    endif
    pwmout pwmfreq MOTOR2 , PWMPERIOD2 , MotorSpeed2; Slows motor within SLOWZONE  ** NEW **
  else
    pwmout MOTOR2 , OFF                       ; STOP
  endif
goto main
 
Last edited:

Gramps

Senior Member
it will depend on how "similar" are the motors and their load and speed requirements
The two shoulder motors are a matched pair of power window regulators, but the Elbow is powered by a Hitachi 12 volt drill motor.
The feedback pot on the Elbow only moves 90 degrees between it's endstops having values between 60 and 110. A suggestion in another thread was to use READAC10.
 
Last edited:

Gramps

Senior Member
Today Shadow Bot went back in storage.
The ministry here at the Ft. Myers Rescue Mission is demanding my full attention so we must lay aside some things.
Thank you to erco! You were one of my first mentors back in the basic stamp days, along with my son, oldbitcollector, for all your encouragement and help when I didn't even know what a BIT was.
Thank you lbenson, AllyCat, and Hippy for holding my hand until I FINALLY begun to understand this language!
Thank you to all the folks on this forum who made comments and offered encouragements and advice to my threads.
The journey was enlightening, sometimes exciting and very satisfying.
Perhaps some day we can dust off the hardware again. Until then, take care my friends.
We are praying for each of you! Gramps
 
Top