Analog joystick library

Committer:
eencae
Date:
Mon Jan 27 15:28:02 2020 +0000
Revision:
1:8e384c3393dd
Parent:
0:649b59b2fb26
Gamepad2

Who changed what in which revision?

UserRevisionLine numberNew contents of line
eencae 0:649b59b2fb26 1 #include "Joystick.h"
eencae 0:649b59b2fb26 2
eencae 1:8e384c3393dd 3 Joystick::Joystick(PinName vertPin,PinName horizPin)
eencae 0:649b59b2fb26 4 {
eencae 0:649b59b2fb26 5 vert = new AnalogIn(vertPin);
eencae 0:649b59b2fb26 6 horiz = new AnalogIn(horizPin);
eencae 0:649b59b2fb26 7 }
eencae 0:649b59b2fb26 8
eencae 0:649b59b2fb26 9 void Joystick::init()
eencae 0:649b59b2fb26 10 {
eencae 0:649b59b2fb26 11 // read centred values of joystick
eencae 0:649b59b2fb26 12 _x0 = horiz->read();
eencae 0:649b59b2fb26 13 _y0 = vert->read();
eencae 0:649b59b2fb26 14
eencae 0:649b59b2fb26 15 // this assumes that the joystick is centred when the init function is called
eencae 0:649b59b2fb26 16 // if perfectly centred, the pots should read 0.5, but this may
eencae 0:649b59b2fb26 17 // not be the case and x0 and y0 will be used to calibrate readings
eencae 0:649b59b2fb26 18 }
eencae 0:649b59b2fb26 19
eencae 0:649b59b2fb26 20 Direction Joystick::get_direction()
eencae 0:649b59b2fb26 21 {
eencae 0:649b59b2fb26 22 float angle = get_angle(); // 0 to 360, -1 for centred
eencae 0:649b59b2fb26 23
eencae 0:649b59b2fb26 24 Direction d;
eencae 0:649b59b2fb26 25 // partition 360 into segments and check which segment the angle is in
eencae 0:649b59b2fb26 26 if (angle < 0.0f) {
eencae 0:649b59b2fb26 27 d = CENTRE; // check for -1.0 angle
eencae 0:649b59b2fb26 28 } else if (angle < 22.5f) { // then keep going in 45 degree increments
eencae 0:649b59b2fb26 29 d = N;
eencae 0:649b59b2fb26 30 } else if (angle < 67.5f) {
eencae 0:649b59b2fb26 31 d = NE;
eencae 0:649b59b2fb26 32 } else if (angle < 112.5f) {
eencae 0:649b59b2fb26 33 d = E;
eencae 0:649b59b2fb26 34 } else if (angle < 157.5f) {
eencae 0:649b59b2fb26 35 d = SE;
eencae 0:649b59b2fb26 36 } else if (angle < 202.5f) {
eencae 0:649b59b2fb26 37 d = S;
eencae 0:649b59b2fb26 38 } else if (angle < 247.5f) {
eencae 0:649b59b2fb26 39 d = SW;
eencae 0:649b59b2fb26 40 } else if (angle < 292.5f) {
eencae 0:649b59b2fb26 41 d = W;
eencae 0:649b59b2fb26 42 } else if (angle < 337.5f) {
eencae 0:649b59b2fb26 43 d = NW;
eencae 0:649b59b2fb26 44 } else {
eencae 0:649b59b2fb26 45 d = N;
eencae 0:649b59b2fb26 46 }
eencae 0:649b59b2fb26 47
eencae 0:649b59b2fb26 48 return d;
eencae 0:649b59b2fb26 49 }
eencae 0:649b59b2fb26 50
eencae 0:649b59b2fb26 51 // this method gets the magnitude of the joystick movement
eencae 0:649b59b2fb26 52 float Joystick::get_mag()
eencae 0:649b59b2fb26 53 {
eencae 0:649b59b2fb26 54 Polar p = get_polar();
eencae 0:649b59b2fb26 55 return p.mag;
eencae 0:649b59b2fb26 56 }
eencae 0:649b59b2fb26 57
eencae 0:649b59b2fb26 58 // this method gets the angle of joystick movement (0 to 360, 0 North)
eencae 0:649b59b2fb26 59 float Joystick::get_angle()
eencae 0:649b59b2fb26 60 {
eencae 0:649b59b2fb26 61 Polar p = get_polar();
eencae 0:649b59b2fb26 62 return p.angle;
eencae 0:649b59b2fb26 63 }
eencae 0:649b59b2fb26 64
eencae 0:649b59b2fb26 65 // get raw joystick coordinate in range -1 to 1
eencae 0:649b59b2fb26 66 // Direction (x,y)
eencae 0:649b59b2fb26 67 // North (0,1)
eencae 0:649b59b2fb26 68 // East (1,0)
eencae 0:649b59b2fb26 69 // South (0,-1)
eencae 0:649b59b2fb26 70 // West (-1,0)
eencae 0:649b59b2fb26 71 Vector2D Joystick::get_coord()
eencae 0:649b59b2fb26 72 {
eencae 0:649b59b2fb26 73 // read() returns value in range 0.0 to 1.0 so is scaled and centre value
eencae 0:649b59b2fb26 74 // substracted to get values in the range -1.0 to 1.0
eencae 0:649b59b2fb26 75 float x = 2.0f*( horiz->read() - _x0 );
eencae 0:649b59b2fb26 76 float y = 2.0f*( vert->read() - _y0 );
eencae 0:649b59b2fb26 77
eencae 1:8e384c3393dd 78 // Note: the values are negated so postive is up (y).
eencae 1:8e384c3393dd 79 Vector2D coord = {x,-y};
eencae 0:649b59b2fb26 80 return coord;
eencae 0:649b59b2fb26 81 }
eencae 0:649b59b2fb26 82
eencae 0:649b59b2fb26 83 // This maps the raw x,y coord onto a circular grid.
eencae 0:649b59b2fb26 84 // See: http://mathproofs.blogspot.co.uk/2005/07/mapping-square-to-circle.html
eencae 0:649b59b2fb26 85 Vector2D Joystick::get_mapped_coord()
eencae 0:649b59b2fb26 86 {
eencae 0:649b59b2fb26 87 Vector2D coord = get_coord();
eencae 0:649b59b2fb26 88
eencae 0:649b59b2fb26 89 // do the transformation
eencae 0:649b59b2fb26 90 float x = coord.x*sqrt(1.0f-pow(coord.y,2.0f)/2.0f);
eencae 0:649b59b2fb26 91 float y = coord.y*sqrt(1.0f-pow(coord.x,2.0f)/2.0f);
eencae 0:649b59b2fb26 92
eencae 0:649b59b2fb26 93 Vector2D mapped_coord = {x,y};
eencae 0:649b59b2fb26 94 return mapped_coord;
eencae 0:649b59b2fb26 95 }
eencae 0:649b59b2fb26 96
eencae 0:649b59b2fb26 97 // this function converts the mapped coordinates into polar form
eencae 0:649b59b2fb26 98 Polar Joystick::get_polar()
eencae 0:649b59b2fb26 99 {
eencae 0:649b59b2fb26 100 // get the mapped coordinate
eencae 0:649b59b2fb26 101 Vector2D coord = get_mapped_coord();
eencae 0:649b59b2fb26 102
eencae 0:649b59b2fb26 103 // at this point, 0 degrees (i.e. x-axis) will be defined to the East.
eencae 0:649b59b2fb26 104 // We want 0 degrees to correspond to North and increase clockwise to 359
eencae 0:649b59b2fb26 105 // like a compass heading, so we need to swap the axis and invert y
eencae 0:649b59b2fb26 106 float x = coord.y;
eencae 0:649b59b2fb26 107 float y = coord.x;
eencae 0:649b59b2fb26 108
eencae 0:649b59b2fb26 109 float mag = sqrt(x*x+y*y); // pythagoras
eencae 0:649b59b2fb26 110 float angle = RAD2DEG*atan2(y,x);
eencae 0:649b59b2fb26 111 // angle will be in range -180 to 180, so add 360 to negative angles to
eencae 0:649b59b2fb26 112 // move to 0 to 360 range
eencae 0:649b59b2fb26 113 if (angle < 0.0f) {
eencae 0:649b59b2fb26 114 angle+=360.0f;
eencae 0:649b59b2fb26 115 }
eencae 0:649b59b2fb26 116
eencae 0:649b59b2fb26 117 // the noise on the ADC causes the values of x and y to fluctuate slightly
eencae 0:649b59b2fb26 118 // around the centred values. This causes the random angle values to get
eencae 0:649b59b2fb26 119 // calculated when the joystick is centred and untouched. This is also when
eencae 0:649b59b2fb26 120 // the magnitude is very small, so we can check for a small magnitude and then
eencae 0:649b59b2fb26 121 // set the angle to -1. This will inform us when the angle is invalid and the
eencae 0:649b59b2fb26 122 // joystick is centred
eencae 0:649b59b2fb26 123
eencae 0:649b59b2fb26 124 if (mag < TOL) {
eencae 0:649b59b2fb26 125 mag = 0.0f;
eencae 0:649b59b2fb26 126 angle = -1.0f;
eencae 0:649b59b2fb26 127 }
eencae 0:649b59b2fb26 128
eencae 0:649b59b2fb26 129 Polar p = {mag,angle};
eencae 0:649b59b2fb26 130 return p;
eencae 1:8e384c3393dd 131 }