Joystick Input - Reversing a variables value to be opposite of ADC reading

Blazemaguire

Senior Member
Hi,

I'm using an Xbox, sprung joystick potentiometer as an input. These obviously spring back to the center neutral position, and thus give an 'at rest' reading of about 127 to 128 (as you'd expect, being half way between 0 and 255) when reading the pot via ADC.

I want to use the joystick to act as a speed controlling forward and reverse input to drive a motor, i.e, push up, the motor goes forward, faster depending how much you push up, and when pushing down, the motor goes backwards, again, faster the harder down you press.

I'm more than happy with the output end and circuity (done this loads before) (Ill use the PWM pins to drive the inputs to a H bridge... got that bit working already)

For some stupid reason (and because I'm rubbish at Maths, especially 8 bit, non floating point Maths!) I can't figure out how to scale the joystick potentiometer reading to be opposite to it's read value, and also scaled from 0 to 255 (to give the full PWM duty cycle range)

What I want is below:

At joystick home position, the motor is off (I'll set a deadband area of ADC reading from around 125 to 130 with an IF statement) - This bit I'm happy with.

When I push DOWN past the programmed deadband on the joystick, values start at 125, then drop down incrementally to 0, but I want to get numbers into a variable that vary from 0 to 255 (from home, to fully down)

When I push UP on the joystick, the ADC records readings from 130 up to 255, but I want these to scale from 0 to 255.

I hope that makes sense?

I don't need help with the code, just the suggestion/hints of how to do the Maths. It might be because It's Sunday and I've been marking all day, but my brain can't seem to grasp it.!

Thanks in advance.

Rob
 

Buzby

Senior Member
Isn't it just 'NewVal = 255 - PotVal' ?

As PotVal gets bigger, NewVal gets smaller.

I don't think it's more complicated than that.

Cheers,

Buzby

Edit : I re-read your post, and now see what you're after.

127 to 255 gives 0 to 127

127 to 0 also gives 0 to 127

So all you need is :

If PotVal > 127 then
NewVal = PotVal - 127
else
NewVal = 127 - PotVal
endif
 

Blazemaguire

Senior Member
Thanks Buzby,

that gives me a new value of 125 to 255 for an input reading of 125 to 0. Part way there.

I can't believe I couldn't see the wood for the trees on that one! (V tired)

I just need to scale that now to be 0 to 255. Any pointers on the scaling?

Sorry, I feel like a lech on other peoples brain capacity, but I can't seem to focus on this, and I've got 2 screaming ankle biters running around which probably isn't helping matters!

(Trying to figure it out for a student I need to help tomorrow AM)

Thanks again
 

StefanST

New Member
I just need to scale that now to be 0 to 255.
Try:
Code:
SYMBOL cLIMIT1 = 125
SYMBOL cLIMIT2 = 130
SYMBOL PotVal = b0
SYMBOL direction = b1
SYMBOL OutVal = b2
SYMBOL tmp = b3

readAdc <channel>, PotVal
if PotVal <= cLIMIT1 then

   direction = 2        ; backward
   OutVal = cLIMIT1 - PotVal * 255 / cLIMIT1

elseif PotVal >= cLIMIT2 then

   direction = 1        ; forward
   tmp = 255 - cLIMIT2
   OutVal = PotVal - cLIMIT2 * 255 / tmp

else

   direction = 0        ; stop
   OutVal = 0

endif
 
Last edited:

Blazemaguire

Senior Member
Thanks Stefan, that works exactly as I needed.

Many thanks. The Maths makes sense now I can see it, but you know when you hit a wall and just can't see the obvious.

Rob
 

hippy

Technical Support
Staff member
This is a generic extension of StefanST's Post #4 which handles a dead band plus the ADC not going fully down to zero or up to 255 -

Code:
#Picaxe 08M2
#Terminal 4800

Symbol MAX_FWD = 245
Symbol MIN_FWD = 130

Symbol MAX_REV = 125
Symbol MIN_REV = 10

Symbol FWD_GAP = MAX_FWD - MIN_FWD
Symbol REV_GAP = MAX_REV - MIN_REV

Symbol POT_ADC = C.4

Symbol pos  = b0
Symbol dir  = b1
Symbol duty = b2

Do
  ReadAdc POT_ADC, pos
  Select Case pos
    Case >= MIN_FWD
      dir  = "+"
      duty = pos Max MAX_FWD - MIN_FWD * 255 / FWD_GAP
    Case <= MAX_REV
      dir  = "-"
      duty = pos Min MIN_REV
      duty = MAX_REV - duty * 255 / REV_GAP
    Else
      dir  = " "
      duty = 0
  End Select
  SerTxd( #pos, " = ", dir, #duty, CR, LF )
  Pause 1000
Loop
 

StefanST

New Member
Thanks hippy, for the generalization.
I did not remember defining the derived constant instead of the variable tmp. Still learning something.
 
Top