Analog joystick library

Dependents:   GameProject_Prototype Joystick lcd205 Joystick205 ... more

Committer:
eencae
Date:
Tue Feb 07 13:01:48 2017 +0000
Revision:
0:649b59b2fb26
Updated docs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
eencae 0:649b59b2fb26 1 #include "Joystick.h"
eencae 0:649b59b2fb26 2
eencae 0:649b59b2fb26 3 Joystick::Joystick(PinName vertPin,PinName horizPin,PinName clickPin)
eencae 0:649b59b2fb26 4 {
eencae 0:649b59b2fb26 5 vert = new AnalogIn(vertPin);
eencae 0:649b59b2fb26 6 horiz = new AnalogIn(horizPin);
eencae 0:649b59b2fb26 7 click = new InterruptIn(clickPin);
eencae 0:649b59b2fb26 8 }
eencae 0:649b59b2fb26 9
eencae 0:649b59b2fb26 10 void Joystick::init()
eencae 0:649b59b2fb26 11 {
eencae 0:649b59b2fb26 12 // read centred values of joystick
eencae 0:649b59b2fb26 13 _x0 = horiz->read();
eencae 0:649b59b2fb26 14 _y0 = vert->read();
eencae 0:649b59b2fb26 15
eencae 0:649b59b2fb26 16 // this assumes that the joystick is centred when the init function is called
eencae 0:649b59b2fb26 17 // if perfectly centred, the pots should read 0.5, but this may
eencae 0:649b59b2fb26 18 // not be the case and x0 and y0 will be used to calibrate readings
eencae 0:649b59b2fb26 19
eencae 0:649b59b2fb26 20 // turn on pull-down for button -> this assumes the other side of the button
eencae 0:649b59b2fb26 21 // is connected to +3V3 so we read 1 when pressed and 0 when not pressed
eencae 0:649b59b2fb26 22 click->mode(PullDown);
eencae 0:649b59b2fb26 23 // we therefore need to fire the interrupt on a rising edge
eencae 0:649b59b2fb26 24 click->rise(callback(this,&Joystick::click_isr));
eencae 0:649b59b2fb26 25 // need to use a callback since mbed-os5 - basically tells it to look in this class for the ISR
eencae 0:649b59b2fb26 26 _click_flag = 0;
eencae 0:649b59b2fb26 27
eencae 0:649b59b2fb26 28 }
eencae 0:649b59b2fb26 29
eencae 0:649b59b2fb26 30 Direction Joystick::get_direction()
eencae 0:649b59b2fb26 31 {
eencae 0:649b59b2fb26 32 float angle = get_angle(); // 0 to 360, -1 for centred
eencae 0:649b59b2fb26 33
eencae 0:649b59b2fb26 34 Direction d;
eencae 0:649b59b2fb26 35 // partition 360 into segments and check which segment the angle is in
eencae 0:649b59b2fb26 36 if (angle < 0.0f) {
eencae 0:649b59b2fb26 37 d = CENTRE; // check for -1.0 angle
eencae 0:649b59b2fb26 38 } else if (angle < 22.5f) { // then keep going in 45 degree increments
eencae 0:649b59b2fb26 39 d = N;
eencae 0:649b59b2fb26 40 } else if (angle < 67.5f) {
eencae 0:649b59b2fb26 41 d = NE;
eencae 0:649b59b2fb26 42 } else if (angle < 112.5f) {
eencae 0:649b59b2fb26 43 d = E;
eencae 0:649b59b2fb26 44 } else if (angle < 157.5f) {
eencae 0:649b59b2fb26 45 d = SE;
eencae 0:649b59b2fb26 46 } else if (angle < 202.5f) {
eencae 0:649b59b2fb26 47 d = S;
eencae 0:649b59b2fb26 48 } else if (angle < 247.5f) {
eencae 0:649b59b2fb26 49 d = SW;
eencae 0:649b59b2fb26 50 } else if (angle < 292.5f) {
eencae 0:649b59b2fb26 51 d = W;
eencae 0:649b59b2fb26 52 } else if (angle < 337.5f) {
eencae 0:649b59b2fb26 53 d = NW;
eencae 0:649b59b2fb26 54 } else {
eencae 0:649b59b2fb26 55 d = N;
eencae 0:649b59b2fb26 56 }
eencae 0:649b59b2fb26 57
eencae 0:649b59b2fb26 58 return d;
eencae 0:649b59b2fb26 59 }
eencae 0:649b59b2fb26 60
eencae 0:649b59b2fb26 61 // this method gets the magnitude of the joystick movement
eencae 0:649b59b2fb26 62 float Joystick::get_mag()
eencae 0:649b59b2fb26 63 {
eencae 0:649b59b2fb26 64 Polar p = get_polar();
eencae 0:649b59b2fb26 65 return p.mag;
eencae 0:649b59b2fb26 66 }
eencae 0:649b59b2fb26 67
eencae 0:649b59b2fb26 68 // this method gets the angle of joystick movement (0 to 360, 0 North)
eencae 0:649b59b2fb26 69 float Joystick::get_angle()
eencae 0:649b59b2fb26 70 {
eencae 0:649b59b2fb26 71 Polar p = get_polar();
eencae 0:649b59b2fb26 72 return p.angle;
eencae 0:649b59b2fb26 73 }
eencae 0:649b59b2fb26 74
eencae 0:649b59b2fb26 75 // get raw joystick coordinate in range -1 to 1
eencae 0:649b59b2fb26 76 // Direction (x,y)
eencae 0:649b59b2fb26 77 // North (0,1)
eencae 0:649b59b2fb26 78 // East (1,0)
eencae 0:649b59b2fb26 79 // South (0,-1)
eencae 0:649b59b2fb26 80 // West (-1,0)
eencae 0:649b59b2fb26 81 Vector2D Joystick::get_coord()
eencae 0:649b59b2fb26 82 {
eencae 0:649b59b2fb26 83 // read() returns value in range 0.0 to 1.0 so is scaled and centre value
eencae 0:649b59b2fb26 84 // substracted to get values in the range -1.0 to 1.0
eencae 0:649b59b2fb26 85 float x = 2.0f*( horiz->read() - _x0 );
eencae 0:649b59b2fb26 86 float y = 2.0f*( vert->read() - _y0 );
eencae 0:649b59b2fb26 87
eencae 0:649b59b2fb26 88 // Note: the x value here is inverted to ensure the positive x is to the
eencae 0:649b59b2fb26 89 // right. This is simply due to how the potentiometer on the joystick
eencae 0:649b59b2fb26 90 // I was using was connected up. It could have been corrected in hardware
eencae 0:649b59b2fb26 91 // by swapping the power supply pins. Instead it is done in software so may
eencae 0:649b59b2fb26 92 // need to be changed depending on your wiring setup
eencae 0:649b59b2fb26 93
eencae 0:649b59b2fb26 94 Vector2D coord = {-x,y};
eencae 0:649b59b2fb26 95 return coord;
eencae 0:649b59b2fb26 96 }
eencae 0:649b59b2fb26 97
eencae 0:649b59b2fb26 98 // This maps the raw x,y coord onto a circular grid.
eencae 0:649b59b2fb26 99 // See: http://mathproofs.blogspot.co.uk/2005/07/mapping-square-to-circle.html
eencae 0:649b59b2fb26 100 Vector2D Joystick::get_mapped_coord()
eencae 0:649b59b2fb26 101 {
eencae 0:649b59b2fb26 102 Vector2D coord = get_coord();
eencae 0:649b59b2fb26 103
eencae 0:649b59b2fb26 104 // do the transformation
eencae 0:649b59b2fb26 105 float x = coord.x*sqrt(1.0f-pow(coord.y,2.0f)/2.0f);
eencae 0:649b59b2fb26 106 float y = coord.y*sqrt(1.0f-pow(coord.x,2.0f)/2.0f);
eencae 0:649b59b2fb26 107
eencae 0:649b59b2fb26 108 Vector2D mapped_coord = {x,y};
eencae 0:649b59b2fb26 109 return mapped_coord;
eencae 0:649b59b2fb26 110 }
eencae 0:649b59b2fb26 111
eencae 0:649b59b2fb26 112 // this function converts the mapped coordinates into polar form
eencae 0:649b59b2fb26 113 Polar Joystick::get_polar()
eencae 0:649b59b2fb26 114 {
eencae 0:649b59b2fb26 115 // get the mapped coordinate
eencae 0:649b59b2fb26 116 Vector2D coord = get_mapped_coord();
eencae 0:649b59b2fb26 117
eencae 0:649b59b2fb26 118 // at this point, 0 degrees (i.e. x-axis) will be defined to the East.
eencae 0:649b59b2fb26 119 // We want 0 degrees to correspond to North and increase clockwise to 359
eencae 0:649b59b2fb26 120 // like a compass heading, so we need to swap the axis and invert y
eencae 0:649b59b2fb26 121 float x = coord.y;
eencae 0:649b59b2fb26 122 float y = coord.x;
eencae 0:649b59b2fb26 123
eencae 0:649b59b2fb26 124 float mag = sqrt(x*x+y*y); // pythagoras
eencae 0:649b59b2fb26 125 float angle = RAD2DEG*atan2(y,x);
eencae 0:649b59b2fb26 126 // angle will be in range -180 to 180, so add 360 to negative angles to
eencae 0:649b59b2fb26 127 // move to 0 to 360 range
eencae 0:649b59b2fb26 128 if (angle < 0.0f) {
eencae 0:649b59b2fb26 129 angle+=360.0f;
eencae 0:649b59b2fb26 130 }
eencae 0:649b59b2fb26 131
eencae 0:649b59b2fb26 132 // the noise on the ADC causes the values of x and y to fluctuate slightly
eencae 0:649b59b2fb26 133 // around the centred values. This causes the random angle values to get
eencae 0:649b59b2fb26 134 // calculated when the joystick is centred and untouched. This is also when
eencae 0:649b59b2fb26 135 // the magnitude is very small, so we can check for a small magnitude and then
eencae 0:649b59b2fb26 136 // set the angle to -1. This will inform us when the angle is invalid and the
eencae 0:649b59b2fb26 137 // joystick is centred
eencae 0:649b59b2fb26 138
eencae 0:649b59b2fb26 139 if (mag < TOL) {
eencae 0:649b59b2fb26 140 mag = 0.0f;
eencae 0:649b59b2fb26 141 angle = -1.0f;
eencae 0:649b59b2fb26 142 }
eencae 0:649b59b2fb26 143
eencae 0:649b59b2fb26 144 Polar p = {mag,angle};
eencae 0:649b59b2fb26 145 return p;
eencae 0:649b59b2fb26 146 }
eencae 0:649b59b2fb26 147
eencae 0:649b59b2fb26 148 bool Joystick::button_pressed()
eencae 0:649b59b2fb26 149 {
eencae 0:649b59b2fb26 150 // ISR must have been triggered
eencae 0:649b59b2fb26 151 if (_click_flag) {
eencae 0:649b59b2fb26 152 _click_flag = 0; // clear flag
eencae 0:649b59b2fb26 153 return true;
eencae 0:649b59b2fb26 154 } else {
eencae 0:649b59b2fb26 155 return false;
eencae 0:649b59b2fb26 156 }
eencae 0:649b59b2fb26 157 }
eencae 0:649b59b2fb26 158
eencae 0:649b59b2fb26 159 void Joystick::click_isr()
eencae 0:649b59b2fb26 160 {
eencae 0:649b59b2fb26 161 _click_flag = 1;
eencae 0:649b59b2fb26 162 }