Can I make this servo control code run faster?

Blazemaguire

Senior Member
Hi guys,

I'm starting to get more confident with the BASIC programming (if you've seen any of my previous posts, you'll know i'm a bit of a noob with the code - used to flowcharts) - anyhow, for my latest experiment i'm making a simple 'touch sensor' operated turrent - actuated by a normal micro hobby servo.

The code below works in practice, and it senses my 'touch' sensors fine (I just use a coil of solid core copper glue gunned to the back of a piece of plastic for the touch sensors). - It moves the 'turret' clockwise and anticlockwise as intended and stops when it reaches the programmed limits.

However, my bug bear is it's too slow for my needs - i'd like more rapid traverse. - I've removed all time delays from the coding, even tried running in 16mhz mode. - Basically it takes about 20 seconds of holding the touch pad down to move from one end of rotation to the other, which is too long for what I've got planned.

Am I on a hiding to nothing trying to get this operating faster? - is it a function of the touch sensing command taking up too much time in the program execution? - If it is, does anyone have any suggestions of other avenues I could explore? - I don't want a full answer, just a suggestion of another direction to follow.

thanks in advance

Code below:



'Touch sensing Servo Control MK1'

'connect touch pads to b.0 and b.1 on a PICAXE20M2

'connect servo to pin b.7


init:
symbol moveamount=1'this symbol is the 'amount' of each step back or forth (basically how much it moves per 'touch'
symbol clockwisebuttoncalib = 4700 'callibration value for my touch pads (clockwise button)
symbol anticlockbuttoncalib = 4100 'callibration value for my touch pads (anticlockwise button)
b9=150 'set variable to 150 so servo moves to midpoint
servo b.7,b9 ; initialise servo to midpoint

main:

turnclock: 'routine for rotating clockwise

touch16 b.0,w0 ; read value into w0 from touch sensor UP
if w0 > clockwisebuttoncalib and b9<=225 then 'check value has exceeded 4700 which is threshold for a 'touch', and not exceeded clockwise limits
b9=b9+moveamount 'increase servo variable so it moves clockwise
servopos b.7,b9 ; move servo to one end
else
goto turnanticlock

endif


turnanticlock:

touch16 b.1,w1 ' read value of DOWN sensor into W1
if w1 > anticlockbuttoncalib and b9>=53 then 'check the value is more than 4100 (threshold for a touch) and that it's not exceeded anticlock limits
b9=b9-moveamount 'reduce the variable by the moveamount (moves servo anticlock)
servopos b.7,b9 ; move servo to one end

goto main
else goto turnclock

endif
 

JimPerry

Senior Member
20 seconds is waay too long - try not using complicated touch16 tests and - for a test - use simple switches for left and right - if left servopos x,175 if right servopos x,225 for example.

Then simplify the touch routine. :rolleyes:
 

vttom

Senior Member
Have you tried larger values for moveamount?

Also, your code seem unnecessarily complicated with gotos and elses. I think the following is equivalent:

Code:
symbol moveamount=1'this symbol is the 'amount' of each step back or forth (basically how much it moves per 'touch'
symbol clockwisebuttoncalib = 4700 'callibration value for my touch pads (clockwise button)
symbol anticlockbuttoncalib = 4100 'callibration value for my touch pads (anticlockwise button)

init:
  b9=150 'set variable to 150 so servo moves to midpoint
  servo b.7,b9 ; initialise servo to midpoint

do

  'routine for rotating clockwise

  touch16 b.0,w0 ; read value into w0 from touch sensor UP
  if w0 > clockwisebuttoncalib and b9<=225 then 'check value has exceeded 4700 which is threshold for a 'touch', and not exceeded clockwise limits
    b9=b9+moveamount 'increase servo variable so it moves clockwise
    servopos b.7,b9 ; move servo to one end
  endif

  'routine for rotating anticlockwise

  touch16 b.1,w1 ' read value of DOWN sensor into W1
  if w1 > anticlockbuttoncalib and b9>=53 then 'check the value is more than 4100 (threshold for a touch) and that it's not exceeded anticlock limits 
    b9=b9-moveamount 'reduce the variable by the moveamount (moves servo anticlock)
    servopos b.7,b9 ; move servo to one end
  endif

loop
 

Blazemaguire

Senior Member
20 seconds is waay too long - try not using complicated touch16 tests and - for a test - use simple switches for left and right - if left servopos x,175 if right servopos x,225 for example.

Then simplify the touch routine. :rolleyes:
Hi, If I do that, then surely i'll only get the ability to move left to right, relying on balancing the buttons - I want the ability to move to any position and stay there... imagine pressing and holding the button until you get to the desired angle, then releasing and it will stay in that position.

Haven't tried it yet, but I'd have thought that would just allow me to traverse left to right and even if I let go, it will just continue rotating until it finds either 225, or 75 position?
 

Blazemaguire

Senior Member
Thanks for simplifying - though that hasn't made a great deal of difference. - I did try adjust the number of steps, which obviously speeds up the movement - but then it has the side effect of reducing the accuracy with which you can move (as in your moving 'several' degrees in one go, rather than one)

Is it just the touch sensors slowing things down? - I really wanted to use flashy 'touch sensing' buttons, but if the processing is too time intensive whatever I do I guess it will have to be PTM's.
 

boriz

Senior Member
You want speed, but also want accuracy. Usually it's a compromise. The big boys will use acceleration techniques. EG: Press and hold for short time, servo moves slowly, hold for longer, servo moves quicker etc.. The code would be a little complicated though.

Also, the servo needs at least 20mS between updates, otherwise you can interfere with the servos internal circuit. This delay can come from your code (I don't know how long a TOUCH16 command takes), but usually its a PAUSE command. Start with PAUSE 50 just before the end of your loop and then decrease the PAUSE maybe down as far as PAUSE 10 and see if it still works ok. And increase the value of 'moveamount' to 2 or 4 just for the time being. An iterative suck-it-and-see approach.

Work on the speed first, then the accuracy.

Does anyone know if the TOUCH commands can interfere with SERVO commands? And how long TOUCH commands take to execute?
 

vttom

Senior Member
Have you experimented to see if the value returned by touch16 correlates to how hard you press the touchpad?

Maybe instead of testing for a fixed threshold, use the value to set moveamount such that a light touch moves a small amount; a heavy touch moves a larger amount.
 

erco

Senior Member
Have you experimented to see if the value returned by touch16 correlates to how hard you press the touchpad?
Yes, pressing harder may yield a different touchpad values. And the values may change significantly when you unplug the programming cable (in which case, you won't be able to see the values displayed onscreen). And also, temperature, humidity, and sweaty hands will cause different readings. Definitely requires experimentation to get proper operation. AKA "empirical determination of the coefficients of the dynamic performance envelope"...

And the touchpad modifier 11101000 (used in my code) made a big difference, found here in the forum:

touch16 [%11101000],c.1,w1
 

vttom

Senior Member
This version employs some acceleration...

Code:
symbol moveamount=1'this symbol is the 'amount' of each step back or forth (basically how much it moves per 'touch'
symbol clockwisebuttoncalib = 4700 'callibration value for my touch pads (clockwise button)
symbol anticlockbuttoncalib = 4100 'callibration value for my touch pads (anticlockwise button)

init:
  b9=150 'set variable to 150 so servo moves to midpoint
  servo b.7,b9 ; initialise servo to midpoint

do

  'routine for rotating clockwise

  moveamount = 1
  touch16 b.0,w0
  do while w0 > clockwisebuttoncalib and b9<=225
    b9=b9+moveamount
    servopos b.7,b9
    inc moveamount
    touch16 b.0,w0
  loop

  'routine for rotating anticlockwise

  moveamount = 1
  touch16 b.1,w1
  do while w1 > anticlockbuttoncalib and b9>=53
    b9=b9-moveamount
    servopos b.7,b9 ; move servo to one end
    inc moveamount
    touch16 b.1,w1
  loop

loop
 

Blazemaguire

Senior Member
This version employs some acceleration...

Code:
symbol moveamount=1'this symbol is the 'amount' of each step back or forth (basically how much it moves per 'touch'
symbol clockwisebuttoncalib = 4700 'callibration value for my touch pads (clockwise button)
symbol anticlockbuttoncalib = 4100 'callibration value for my touch pads (anticlockwise button)

init:
  b9=150 'set variable to 150 so servo moves to midpoint
  servo b.7,b9 ; initialise servo to midpoint

do

  'routine for rotating clockwise

  moveamount = 1
  touch16 b.0,w0
  do while w0 > clockwisebuttoncalib and b9<=225
    b9=b9+moveamount
    servopos b.7,b9
    inc moveamount
    touch16 b.0,w0
  loop

  'routine for rotating anticlockwise

  moveamount = 1
  touch16 b.1,w1
  do while w1 > anticlockbuttoncalib and b9>=53
    b9=b9-moveamount
    servopos b.7,b9 ; move servo to one end
    inc moveamount
    touch16 b.1,w1
  loop

loop
Thanks! - The acceleration function in this code makes it work exactly as I would like! Many thanks for that insight. - I guess it is the touch16 command that slows down the loop speed. - However the accelerations gives the perfect balance between low end resolution of accuracy, and quick traverse if it is held down.

Thanks for all involved, - Hope the code will help someone else in a similar situation in future.
 

vttom

Senior Member
Glad to hear it worked out for you! Just a thought.... You might want to put and if .. then ... endif clause around the "b9=b9+/-moveamount" statements to make sure they don't over- or under-flow. Alternatively, put an if ... then ... endif around "inc moveamount", or use a max function, to keep it from getting big enough to result in an over-/under-flow when added to/subtracted from b9.
 
Top