Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp@2:f3ae10decc2f, 2015-12-06 (annotated)
- Committer:
- alecselfridge
- Date:
- Sun Dec 06 22:42:01 2015 +0000
- Revision:
- 2:f3ae10decc2f
- Parent:
- 1:0a93e9e88ad3
- Child:
- 3:25eba54bace2
Version 1.4 with LEDs, RGB, and joystick.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| alecselfridge | 2:f3ae10decc2f | 1 | /************************************************************************ |
| alecselfridge | 2:f3ae10decc2f | 2 | * Authors: Alec Selfridge/Dylan Smith |
| alecselfridge | 2:f3ae10decc2f | 3 | * Date: 12/4/2015 |
| alecselfridge | 2:f3ae10decc2f | 4 | * Rev: 1.4 |
| alecselfridge | 2:f3ae10decc2f | 5 | * Project: RTOS Light Animations |
| alecselfridge | 2:f3ae10decc2f | 6 | * Notes: The z-axis of the accelerometer is used to calculate the |
| alecselfridge | 2:f3ae10decc2f | 7 | * "effective" angle that the board is tilted. First, the Z data |
| alecselfridge | 2:f3ae10decc2f | 8 | * (0-65) is converted to a (0-90) scale. Then the actual |
| alecselfridge | 2:f3ae10decc2f | 9 | * manipulation occurs by injecting the acc data into a response |
| alecselfridge | 2:f3ae10decc2f | 10 | * formula in the form of ax^2 - by + c. The resulting angle has |
| alecselfridge | 2:f3ae10decc2f | 11 | * no sign but it's magnitude is used to determine the rate at |
| alecselfridge | 2:f3ae10decc2f | 12 | * which LEDs will "fill", thus simulating a gravity effect. To |
| alecselfridge | 2:f3ae10decc2f | 13 | * account for both directions of tilt we check the polarity of |
| alecselfridge | 2:f3ae10decc2f | 14 | * the x-axis. A negative value indicates a tilt to the right |
| alecselfridge | 2:f3ae10decc2f | 15 | * and vice versa. |
| alecselfridge | 2:f3ae10decc2f | 16 | * A 5-axis joystick is used to mix R, G, and B values to create |
| alecselfridge | 2:f3ae10decc2f | 17 | * a custom color. The RGB LED is controled via PWM with a value |
| alecselfridge | 2:f3ae10decc2f | 18 | * of 1.0 indicating "off" and vice versa. |
| alecselfridge | 2:f3ae10decc2f | 19 | * |
| alecselfridge | 2:f3ae10decc2f | 20 | ************************************************************************/ |
| alecselfridge | 2:f3ae10decc2f | 21 | |
| alecselfridge | 0:4555c427d7a8 | 22 | #include "mbed.h" |
| alecselfridge | 1:0a93e9e88ad3 | 23 | #include "rtos.h" |
| alecselfridge | 0:4555c427d7a8 | 24 | #include "MMA7455.h" |
| alecselfridge | 0:4555c427d7a8 | 25 | |
| alecselfridge | 2:f3ae10decc2f | 26 | // response formula coefficients |
| alecselfridge | 2:f3ae10decc2f | 27 | #define X2 0.0038 |
| alecselfridge | 2:f3ae10decc2f | 28 | #define X 0.0299 |
| alecselfridge | 2:f3ae10decc2f | 29 | #define C 0.1883 |
| alecselfridge | 0:4555c427d7a8 | 30 | |
| alecselfridge | 0:4555c427d7a8 | 31 | /* |
| alecselfridge | 0:4555c427d7a8 | 32 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 33 | Display Functions |
| alecselfridge | 0:4555c427d7a8 | 34 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 35 | */ |
| alecselfridge | 0:4555c427d7a8 | 36 | void displayBanner(); |
| alecselfridge | 0:4555c427d7a8 | 37 | void newline(); |
| alecselfridge | 0:4555c427d7a8 | 38 | |
| alecselfridge | 0:4555c427d7a8 | 39 | /* |
| alecselfridge | 0:4555c427d7a8 | 40 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 41 | Utility Functions |
| alecselfridge | 0:4555c427d7a8 | 42 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 43 | */ |
| alecselfridge | 2:f3ae10decc2f | 44 | void SerialInit(void); |
| alecselfridge | 2:f3ae10decc2f | 45 | void AccInit(void); |
| alecselfridge | 2:f3ae10decc2f | 46 | void LEDsInit(void); |
| alecselfridge | 2:f3ae10decc2f | 47 | void RgbInit(void); |
| alecselfridge | 2:f3ae10decc2f | 48 | void accFeed(void); |
| alecselfridge | 0:4555c427d7a8 | 49 | void sampleAcc(int period, int32_t data[3]); |
| alecselfridge | 2:f3ae10decc2f | 50 | double getAngle(void); |
| alecselfridge | 2:f3ae10decc2f | 51 | unsigned char mapLEDS(double v); |
| alecselfridge | 2:f3ae10decc2f | 52 | void LEDPush(void const *args); |
| alecselfridge | 2:f3ae10decc2f | 53 | void RGBpicker(void const *args); |
| alecselfridge | 2:f3ae10decc2f | 54 | void testLED(void); |
| alecselfridge | 2:f3ae10decc2f | 55 | void testRGB(void); |
| alecselfridge | 0:4555c427d7a8 | 56 | |
| alecselfridge | 0:4555c427d7a8 | 57 | /* |
| alecselfridge | 0:4555c427d7a8 | 58 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 59 | Global Data |
| alecselfridge | 0:4555c427d7a8 | 60 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 61 | */ |
| alecselfridge | 0:4555c427d7a8 | 62 | const char banner[37] = "Serial Comm Established with LPC4088"; |
| alecselfridge | 0:4555c427d7a8 | 63 | // x, y, z |
| alecselfridge | 0:4555c427d7a8 | 64 | // holds current position |
| alecselfridge | 0:4555c427d7a8 | 65 | int32_t accPos[3] = {}; |
| alecselfridge | 0:4555c427d7a8 | 66 | // holds up to 20 samples of data |
| alecselfridge | 0:4555c427d7a8 | 67 | int32_t accData[20][20][20] = {}; |
| alecselfridge | 0:4555c427d7a8 | 68 | // holds calibration offsets |
| alecselfridge | 0:4555c427d7a8 | 69 | int32_t accCal[3] = {}; |
| alecselfridge | 2:f3ae10decc2f | 70 | // holds last acc value |
| alecselfridge | 2:f3ae10decc2f | 71 | int32_t acc_old = 0; |
| alecselfridge | 2:f3ae10decc2f | 72 | // holds most recent, adjusted, acc value |
| alecselfridge | 2:f3ae10decc2f | 73 | double acc_adj = 0.0; |
| alecselfridge | 2:f3ae10decc2f | 74 | // a value representing what's shown on the LEDs |
| alecselfridge | 2:f3ae10decc2f | 75 | uint8_t LEDvals = 0; |
| alecselfridge | 2:f3ae10decc2f | 76 | // tracker of how many times the joystick was used |
| alecselfridge | 2:f3ae10decc2f | 77 | uint8_t tick = 0; |
| alecselfridge | 2:f3ae10decc2f | 78 | // red value of RGB |
| alecselfridge | 2:f3ae10decc2f | 79 | float r = 0; |
| alecselfridge | 2:f3ae10decc2f | 80 | // green value of RGB |
| alecselfridge | 2:f3ae10decc2f | 81 | float g = 0; |
| alecselfridge | 2:f3ae10decc2f | 82 | // blue value of RGB |
| alecselfridge | 2:f3ae10decc2f | 83 | float b = 0; |
| alecselfridge | 0:4555c427d7a8 | 84 | |
| alecselfridge | 0:4555c427d7a8 | 85 | /* |
| alecselfridge | 0:4555c427d7a8 | 86 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 87 | Objects |
| alecselfridge | 0:4555c427d7a8 | 88 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 89 | */ |
| alecselfridge | 0:4555c427d7a8 | 90 | // UART connection to PC |
| alecselfridge | 0:4555c427d7a8 | 91 | Serial terminal(USBTX, USBRX); |
| alecselfridge | 0:4555c427d7a8 | 92 | // accelerometer on I2C bus |
| alecselfridge | 0:4555c427d7a8 | 93 | MMA7455 acc(P0_27, P0_28); |
| alecselfridge | 1:0a93e9e88ad3 | 94 | // SPI interface for 8 LEDs |
| alecselfridge | 1:0a93e9e88ad3 | 95 | SPI leds(p5, NC, p7); |
| alecselfridge | 1:0a93e9e88ad3 | 96 | // load for shift register |
| alecselfridge | 1:0a93e9e88ad3 | 97 | DigitalOut ld(p30); |
| alecselfridge | 2:f3ae10decc2f | 98 | // R of RGB LED |
| alecselfridge | 2:f3ae10decc2f | 99 | PwmOut R(p25); |
| alecselfridge | 2:f3ae10decc2f | 100 | // G of RGB LED |
| alecselfridge | 2:f3ae10decc2f | 101 | PwmOut G(p28); |
| alecselfridge | 2:f3ae10decc2f | 102 | // B of RGB LED |
| alecselfridge | 2:f3ae10decc2f | 103 | PwmOut B(p26); |
| alecselfridge | 2:f3ae10decc2f | 104 | // active-low 5-axis joystick |
| alecselfridge | 2:f3ae10decc2f | 105 | // center, left_hi, right_hi, left_lo, right_lo |
| alecselfridge | 2:f3ae10decc2f | 106 | BusIn joystick(p31, p32, p37, p39, p38); |
| alecselfridge | 0:4555c427d7a8 | 107 | |
| alecselfridge | 0:4555c427d7a8 | 108 | int main() { |
| alecselfridge | 0:4555c427d7a8 | 109 | /* |
| alecselfridge | 0:4555c427d7a8 | 110 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 111 | Initializations |
| alecselfridge | 0:4555c427d7a8 | 112 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 113 | */ |
| alecselfridge | 0:4555c427d7a8 | 114 | SerialInit(); |
| alecselfridge | 2:f3ae10decc2f | 115 | AccInit(); |
| alecselfridge | 1:0a93e9e88ad3 | 116 | LEDsInit(); |
| alecselfridge | 2:f3ae10decc2f | 117 | testLED(); |
| alecselfridge | 2:f3ae10decc2f | 118 | RgbInit(); |
| alecselfridge | 2:f3ae10decc2f | 119 | testRGB(); |
| alecselfridge | 1:0a93e9e88ad3 | 120 | |
| alecselfridge | 2:f3ae10decc2f | 121 | /*terminal.printf("Initializing tasks............"); |
| alecselfridge | 2:f3ae10decc2f | 122 | Thread js_update(test); |
| alecselfridge | 2:f3ae10decc2f | 123 | js_update.set_priority(osPriorityNormal); |
| alecselfridge | 2:f3ae10decc2f | 124 | terminal.printf("done."); |
| alecselfridge | 2:f3ae10decc2f | 125 | newline();*/ |
| alecselfridge | 2:f3ae10decc2f | 126 | terminal.printf("Initializing timers.........."); |
| alecselfridge | 2:f3ae10decc2f | 127 | // timer responsible for updating the LEDs |
| alecselfridge | 2:f3ae10decc2f | 128 | RtosTimer refresh_timer(LEDPush, osTimerPeriodic, (void *)0); |
| alecselfridge | 2:f3ae10decc2f | 129 | // 16.7Hz timer (60ms or ~1/2 of 30fps) |
| alecselfridge | 1:0a93e9e88ad3 | 130 | refresh_timer.start(60); |
| alecselfridge | 2:f3ae10decc2f | 131 | RtosTimer update_timer(RGBpicker, osTimerPeriodic, (void *)0); |
| alecselfridge | 2:f3ae10decc2f | 132 | // 10Hz timer (100ms) |
| alecselfridge | 2:f3ae10decc2f | 133 | update_timer.start(100); |
| alecselfridge | 2:f3ae10decc2f | 134 | terminal.printf("done."); |
| alecselfridge | 1:0a93e9e88ad3 | 135 | |
| alecselfridge | 2:f3ae10decc2f | 136 | newline(); newline(); |
| alecselfridge | 2:f3ae10decc2f | 137 | terminal.printf("Initialization complete."); |
| alecselfridge | 2:f3ae10decc2f | 138 | newline(); |
| alecselfridge | 0:4555c427d7a8 | 139 | /* |
| alecselfridge | 0:4555c427d7a8 | 140 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 141 | Main Execution |
| alecselfridge | 0:4555c427d7a8 | 142 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 143 | */ |
| alecselfridge | 2:f3ae10decc2f | 144 | while(true) { |
| alecselfridge | 0:4555c427d7a8 | 145 | acc.read(accPos[0], accPos[1], accPos[2]); |
| alecselfridge | 2:f3ae10decc2f | 146 | acc_adj = getAngle(); |
| alecselfridge | 2:f3ae10decc2f | 147 | LEDvals = mapLEDS(acc_adj); |
| alecselfridge | 0:4555c427d7a8 | 148 | } |
| alecselfridge | 0:4555c427d7a8 | 149 | } |
| alecselfridge | 0:4555c427d7a8 | 150 | |
| alecselfridge | 0:4555c427d7a8 | 151 | /* |
| alecselfridge | 0:4555c427d7a8 | 152 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 153 | Function Definitions |
| alecselfridge | 0:4555c427d7a8 | 154 | ************************** |
| alecselfridge | 0:4555c427d7a8 | 155 | */ |
| alecselfridge | 0:4555c427d7a8 | 156 | void SerialInit() |
| alecselfridge | 0:4555c427d7a8 | 157 | { |
| alecselfridge | 2:f3ae10decc2f | 158 | // initialize connection to PC. default: 8N1 |
| alecselfridge | 0:4555c427d7a8 | 159 | terminal.baud(19200); |
| alecselfridge | 0:4555c427d7a8 | 160 | displayBanner(); |
| alecselfridge | 0:4555c427d7a8 | 161 | newline(); |
| alecselfridge | 0:4555c427d7a8 | 162 | } |
| alecselfridge | 0:4555c427d7a8 | 163 | |
| alecselfridge | 0:4555c427d7a8 | 164 | void AccInit() |
| alecselfridge | 0:4555c427d7a8 | 165 | { |
| alecselfridge | 0:4555c427d7a8 | 166 | // configure accelerometer for 2G range |
| alecselfridge | 0:4555c427d7a8 | 167 | acc.setMode(MMA7455::ModeMeasurement); |
| alecselfridge | 0:4555c427d7a8 | 168 | acc.setRange(MMA7455::Range_2g); |
| alecselfridge | 0:4555c427d7a8 | 169 | terminal.printf("Calibrating accelerometer..."); |
| alecselfridge | 0:4555c427d7a8 | 170 | |
| alecselfridge | 0:4555c427d7a8 | 171 | // if we can successfully calibrate the accelerometer... |
| alecselfridge | 0:4555c427d7a8 | 172 | if(acc.calibrate()) { |
| alecselfridge | 0:4555c427d7a8 | 173 | newline(); |
| alecselfridge | 0:4555c427d7a8 | 174 | acc.getCalibrationOffsets(accCal[0], accCal[1], accCal[2]); |
| alecselfridge | 2:f3ae10decc2f | 175 | terminal.printf(" Offsets are (x,y,z): (%d, %d, %d)", accCal[0], accCal[1], accCal[2]); |
| alecselfridge | 0:4555c427d7a8 | 176 | newline(); newline(); |
| alecselfridge | 0:4555c427d7a8 | 177 | } |
| alecselfridge | 0:4555c427d7a8 | 178 | else { |
| alecselfridge | 0:4555c427d7a8 | 179 | terminal.printf("failed."); |
| alecselfridge | 0:4555c427d7a8 | 180 | newline(); newline(); |
| alecselfridge | 0:4555c427d7a8 | 181 | } |
| alecselfridge | 0:4555c427d7a8 | 182 | } |
| alecselfridge | 0:4555c427d7a8 | 183 | |
| alecselfridge | 2:f3ae10decc2f | 184 | void LEDsInit() |
| alecselfridge | 2:f3ae10decc2f | 185 | { |
| alecselfridge | 2:f3ae10decc2f | 186 | terminal.printf("Initializing LED array......."); |
| alecselfridge | 2:f3ae10decc2f | 187 | leds.format(8, 3); // 8-bit packet, polarity & phase mode 3 |
| alecselfridge | 2:f3ae10decc2f | 188 | leds.frequency(100000); // 1MHz SPI |
| alecselfridge | 2:f3ae10decc2f | 189 | ld = 1; |
| alecselfridge | 2:f3ae10decc2f | 190 | LEDvals = 0x00; |
| alecselfridge | 2:f3ae10decc2f | 191 | terminal.printf("done."); |
| alecselfridge | 2:f3ae10decc2f | 192 | newline(); |
| alecselfridge | 2:f3ae10decc2f | 193 | } |
| alecselfridge | 2:f3ae10decc2f | 194 | |
| alecselfridge | 2:f3ae10decc2f | 195 | void RgbInit() |
| alecselfridge | 2:f3ae10decc2f | 196 | { |
| alecselfridge | 2:f3ae10decc2f | 197 | terminal.printf("Initializing RGB LED........."); |
| alecselfridge | 2:f3ae10decc2f | 198 | // 1KHz |
| alecselfridge | 2:f3ae10decc2f | 199 | R.period(.001); |
| alecselfridge | 2:f3ae10decc2f | 200 | R = 1.0; |
| alecselfridge | 2:f3ae10decc2f | 201 | G.period(.001); |
| alecselfridge | 2:f3ae10decc2f | 202 | G = 1.0; |
| alecselfridge | 2:f3ae10decc2f | 203 | B.period(.001); |
| alecselfridge | 2:f3ae10decc2f | 204 | B = 1.0; |
| alecselfridge | 2:f3ae10decc2f | 205 | terminal.printf("done."); |
| alecselfridge | 2:f3ae10decc2f | 206 | newline(); |
| alecselfridge | 2:f3ae10decc2f | 207 | } |
| alecselfridge | 2:f3ae10decc2f | 208 | |
| alecselfridge | 0:4555c427d7a8 | 209 | void newline() |
| alecselfridge | 0:4555c427d7a8 | 210 | { |
| alecselfridge | 0:4555c427d7a8 | 211 | // newline = carriage return + line feed |
| alecselfridge | 0:4555c427d7a8 | 212 | terminal.putc('\n'); |
| alecselfridge | 0:4555c427d7a8 | 213 | terminal.putc('\r'); |
| alecselfridge | 0:4555c427d7a8 | 214 | } |
| alecselfridge | 0:4555c427d7a8 | 215 | |
| alecselfridge | 0:4555c427d7a8 | 216 | /* |
| alecselfridge | 0:4555c427d7a8 | 217 | Displays the following header: |
| alecselfridge | 0:4555c427d7a8 | 218 | ************************************************ |
| alecselfridge | 0:4555c427d7a8 | 219 | Serial Comm Established with LPC4088 |
| alecselfridge | 0:4555c427d7a8 | 220 | ************************************************ |
| alecselfridge | 0:4555c427d7a8 | 221 | */ |
| alecselfridge | 0:4555c427d7a8 | 222 | void displayBanner() |
| alecselfridge | 0:4555c427d7a8 | 223 | { |
| alecselfridge | 0:4555c427d7a8 | 224 | int i = 0; |
| alecselfridge | 0:4555c427d7a8 | 225 | for(int j = 0; j < 48; j++) |
| alecselfridge | 0:4555c427d7a8 | 226 | terminal.putc('*'); |
| alecselfridge | 0:4555c427d7a8 | 227 | newline(); |
| alecselfridge | 0:4555c427d7a8 | 228 | |
| alecselfridge | 0:4555c427d7a8 | 229 | while(i != 36) { |
| alecselfridge | 0:4555c427d7a8 | 230 | char c = banner[i]; |
| alecselfridge | 0:4555c427d7a8 | 231 | terminal.putc(c); |
| alecselfridge | 0:4555c427d7a8 | 232 | i++; |
| alecselfridge | 0:4555c427d7a8 | 233 | } |
| alecselfridge | 0:4555c427d7a8 | 234 | newline(); |
| alecselfridge | 0:4555c427d7a8 | 235 | |
| alecselfridge | 0:4555c427d7a8 | 236 | for(int j = 0; j < 48; j++) |
| alecselfridge | 0:4555c427d7a8 | 237 | terminal.putc('*'); |
| alecselfridge | 0:4555c427d7a8 | 238 | } |
| alecselfridge | 0:4555c427d7a8 | 239 | |
| alecselfridge | 0:4555c427d7a8 | 240 | // prints the current positional data from the accelerometer |
| alecselfridge | 0:4555c427d7a8 | 241 | void accFeed() |
| alecselfridge | 0:4555c427d7a8 | 242 | { |
| alecselfridge | 0:4555c427d7a8 | 243 | // returns false if the mode is set to standby or unable to convert |
| alecselfridge | 0:4555c427d7a8 | 244 | if(acc.read(accPos[0], accPos[1], accPos[2])) { |
| alecselfridge | 0:4555c427d7a8 | 245 | terminal.printf("x: %d y: %d z: %d", accPos[0], accPos[1], accPos[2]); |
| alecselfridge | 0:4555c427d7a8 | 246 | newline(); |
| alecselfridge | 0:4555c427d7a8 | 247 | } |
| alecselfridge | 0:4555c427d7a8 | 248 | else { |
| alecselfridge | 2:f3ae10decc2f | 249 | terminal.printf("Unable to access MMA7455."); |
| alecselfridge | 0:4555c427d7a8 | 250 | newline(); |
| alecselfridge | 0:4555c427d7a8 | 251 | } |
| alecselfridge | 0:4555c427d7a8 | 252 | } |
| alecselfridge | 0:4555c427d7a8 | 253 | |
| alecselfridge | 0:4555c427d7a8 | 254 | /* |
| alecselfridge | 0:4555c427d7a8 | 255 | Samples the accelerometer in 1/4s intervals for the length of "period" (max 5). |
| alecselfridge | 0:4555c427d7a8 | 256 | The results are placed in the 3D array. Additionally, the array passed in |
| alecselfridge | 0:4555c427d7a8 | 257 | will hold the last reading. |
| alecselfridge | 0:4555c427d7a8 | 258 | */ |
| alecselfridge | 0:4555c427d7a8 | 259 | void sampleAcc(int period, int32_t data[3]) |
| alecselfridge | 0:4555c427d7a8 | 260 | { |
| alecselfridge | 0:4555c427d7a8 | 261 | for(int i = 0; i < period*4; i++) { |
| alecselfridge | 0:4555c427d7a8 | 262 | //load temps |
| alecselfridge | 0:4555c427d7a8 | 263 | acc.read(data[0], data[1], data[2]); |
| alecselfridge | 0:4555c427d7a8 | 264 | accData[i][0][0] = data[0]; // x |
| alecselfridge | 0:4555c427d7a8 | 265 | accData[0][i][0] = data[1]; // y |
| alecselfridge | 0:4555c427d7a8 | 266 | accData[0][0][i] = data[2]; // z |
| alecselfridge | 0:4555c427d7a8 | 267 | wait(.25); |
| alecselfridge | 0:4555c427d7a8 | 268 | } |
| alecselfridge | 0:4555c427d7a8 | 269 | // if we didn't fill the whole array, we'll clear it to avoid confusion later |
| alecselfridge | 0:4555c427d7a8 | 270 | if(period < 5) { |
| alecselfridge | 0:4555c427d7a8 | 271 | for(int i = period*4; i < 20; i++) |
| alecselfridge | 0:4555c427d7a8 | 272 | accData[i][i][i] = 0; |
| alecselfridge | 0:4555c427d7a8 | 273 | } |
| alecselfridge | 1:0a93e9e88ad3 | 274 | } |
| alecselfridge | 1:0a93e9e88ad3 | 275 | |
| alecselfridge | 2:f3ae10decc2f | 276 | // called by the refresh timer every 60ms |
| alecselfridge | 2:f3ae10decc2f | 277 | void LEDPush(void const *args) |
| alecselfridge | 2:f3ae10decc2f | 278 | { |
| alecselfridge | 2:f3ae10decc2f | 279 | ld = 0; // active-low load |
| alecselfridge | 2:f3ae10decc2f | 280 | leds.write(LEDvals); |
| alecselfridge | 2:f3ae10decc2f | 281 | ld = 1; // "lock" lights |
| alecselfridge | 2:f3ae10decc2f | 282 | } |
| alecselfridge | 2:f3ae10decc2f | 283 | |
| alecselfridge | 2:f3ae10decc2f | 284 | void RGBPush(void) |
| alecselfridge | 2:f3ae10decc2f | 285 | { |
| alecselfridge | 2:f3ae10decc2f | 286 | R = r; |
| alecselfridge | 2:f3ae10decc2f | 287 | G = g; |
| alecselfridge | 2:f3ae10decc2f | 288 | B = b; |
| alecselfridge | 2:f3ae10decc2f | 289 | } |
| alecselfridge | 2:f3ae10decc2f | 290 | |
| alecselfridge | 2:f3ae10decc2f | 291 | /* |
| alecselfridge | 2:f3ae10decc2f | 292 | -0-90 degrees = 0-65 units (deg/unit ratio) |
| alecselfridge | 2:f3ae10decc2f | 293 | -90 - conversion = actual angle (a value of 65 means the device is flat) |
| alecselfridge | 2:f3ae10decc2f | 294 | thus, Theta = 90 - (90/65 * x) (90/65 = 1.38) |
| alecselfridge | 2:f3ae10decc2f | 295 | -Using ax^2 - by + c allows the data to fit into a custom model of about 1/3 scale |
| alecselfridge | 2:f3ae10decc2f | 296 | Therefore, the final equation is: Theta = 90 - 3(ax^2 - by + c) |
| alecselfridge | 2:f3ae10decc2f | 297 | */ |
| alecselfridge | 2:f3ae10decc2f | 298 | double getAngle(void) |
| alecselfridge | 2:f3ae10decc2f | 299 | { |
| alecselfridge | 2:f3ae10decc2f | 300 | double deg = 1.38 * accPos[2]; |
| alecselfridge | 2:f3ae10decc2f | 301 | double cal = 1.38 * accCal[2]; |
| alecselfridge | 2:f3ae10decc2f | 302 | return ( 90 - (3.0 * ((X2*deg*deg) - (X*cal) + C)) ); |
| alecselfridge | 2:f3ae10decc2f | 303 | } |
| alecselfridge | 2:f3ae10decc2f | 304 | |
| alecselfridge | 2:f3ae10decc2f | 305 | // look-up table based on ranges |
| alecselfridge | 2:f3ae10decc2f | 306 | // this setup gives a nonlinear response from 0-90 degrees |
| alecselfridge | 2:f3ae10decc2f | 307 | unsigned char mapLEDS(double v) |
| alecselfridge | 1:0a93e9e88ad3 | 308 | { |
| alecselfridge | 2:f3ae10decc2f | 309 | int angle = int(v); |
| alecselfridge | 2:f3ae10decc2f | 310 | if(accPos[0] < 0) { |
| alecselfridge | 2:f3ae10decc2f | 311 | if(angle < 8) |
| alecselfridge | 2:f3ae10decc2f | 312 | return 0xFF; |
| alecselfridge | 2:f3ae10decc2f | 313 | else if(angle >= 8 && angle < 15) |
| alecselfridge | 2:f3ae10decc2f | 314 | return 0x7F; |
| alecselfridge | 2:f3ae10decc2f | 315 | else if(angle >= 15 && angle < 25) |
| alecselfridge | 2:f3ae10decc2f | 316 | return 0x3F; |
| alecselfridge | 2:f3ae10decc2f | 317 | else if(angle >= 25 && angle < 35) |
| alecselfridge | 2:f3ae10decc2f | 318 | return 0x1F; |
| alecselfridge | 2:f3ae10decc2f | 319 | else if(angle >= 35 && angle < 40) |
| alecselfridge | 2:f3ae10decc2f | 320 | return 0x0F; |
| alecselfridge | 2:f3ae10decc2f | 321 | else if(angle >= 40 && angle < 50) |
| alecselfridge | 2:f3ae10decc2f | 322 | return 0x07; |
| alecselfridge | 2:f3ae10decc2f | 323 | else if(angle >= 50 && angle < 60) |
| alecselfridge | 2:f3ae10decc2f | 324 | return 0x03; |
| alecselfridge | 2:f3ae10decc2f | 325 | else if(angle >= 60 && angle < 70) |
| alecselfridge | 2:f3ae10decc2f | 326 | return 0x01; |
| alecselfridge | 2:f3ae10decc2f | 327 | else if(angle >= 70) |
| alecselfridge | 2:f3ae10decc2f | 328 | return 0x00; |
| alecselfridge | 2:f3ae10decc2f | 329 | else |
| alecselfridge | 2:f3ae10decc2f | 330 | return 0xFF; |
| alecselfridge | 2:f3ae10decc2f | 331 | } |
| alecselfridge | 2:f3ae10decc2f | 332 | else { |
| alecselfridge | 2:f3ae10decc2f | 333 | if(angle < 8) |
| alecselfridge | 2:f3ae10decc2f | 334 | return 0xFF; |
| alecselfridge | 2:f3ae10decc2f | 335 | else if(angle >= 8 && angle < 15) |
| alecselfridge | 2:f3ae10decc2f | 336 | return 0xFE; |
| alecselfridge | 2:f3ae10decc2f | 337 | else if(angle >= 15 && angle < 25) |
| alecselfridge | 2:f3ae10decc2f | 338 | return 0xFC; |
| alecselfridge | 2:f3ae10decc2f | 339 | else if(angle >= 25 && angle < 35) |
| alecselfridge | 2:f3ae10decc2f | 340 | return 0xF8; |
| alecselfridge | 2:f3ae10decc2f | 341 | else if(angle >= 35 && angle < 40) |
| alecselfridge | 2:f3ae10decc2f | 342 | return 0xF0; |
| alecselfridge | 2:f3ae10decc2f | 343 | else if(angle >= 40 && angle < 50) |
| alecselfridge | 2:f3ae10decc2f | 344 | return 0xE0; |
| alecselfridge | 2:f3ae10decc2f | 345 | else if(angle >= 50 && angle < 60) |
| alecselfridge | 2:f3ae10decc2f | 346 | return 0xC0; |
| alecselfridge | 2:f3ae10decc2f | 347 | else if(angle >= 60 && angle < 70) |
| alecselfridge | 2:f3ae10decc2f | 348 | return 0x80; |
| alecselfridge | 2:f3ae10decc2f | 349 | else if(angle >= 70) |
| alecselfridge | 2:f3ae10decc2f | 350 | return 0x00; |
| alecselfridge | 2:f3ae10decc2f | 351 | else |
| alecselfridge | 2:f3ae10decc2f | 352 | return 0xFF; |
| alecselfridge | 2:f3ae10decc2f | 353 | } |
| alecselfridge | 1:0a93e9e88ad3 | 354 | } |
| alecselfridge | 1:0a93e9e88ad3 | 355 | |
| alecselfridge | 2:f3ae10decc2f | 356 | /* |
| alecselfridge | 2:f3ae10decc2f | 357 | joystick: 0 1 2 3 4 |
| alecselfridge | 2:f3ae10decc2f | 358 | center left_hi right_hi left_lo right_lo |
| alecselfridge | 2:f3ae10decc2f | 359 | */ |
| alecselfridge | 2:f3ae10decc2f | 360 | void RGBpicker(void const *args) |
| alecselfridge | 1:0a93e9e88ad3 | 361 | { |
| alecselfridge | 2:f3ae10decc2f | 362 | tick++; |
| alecselfridge | 2:f3ae10decc2f | 363 | if(tick > 1) { |
| alecselfridge | 2:f3ae10decc2f | 364 | tick = 0; |
| alecselfridge | 2:f3ae10decc2f | 365 | return; |
| alecselfridge | 2:f3ae10decc2f | 366 | } |
| alecselfridge | 2:f3ae10decc2f | 367 | // left : R |
| alecselfridge | 2:f3ae10decc2f | 368 | if(!(joystick[1] & !joystick[3])) { |
| alecselfridge | 2:f3ae10decc2f | 369 | if(R.read() == 0.0) |
| alecselfridge | 2:f3ae10decc2f | 370 | r = 1.0; |
| alecselfridge | 2:f3ae10decc2f | 371 | r = r - .02; |
| alecselfridge | 2:f3ae10decc2f | 372 | } |
| alecselfridge | 2:f3ae10decc2f | 373 | // right : B |
| alecselfridge | 2:f3ae10decc2f | 374 | else if(!(joystick[2] & !joystick[4])) { |
| alecselfridge | 2:f3ae10decc2f | 375 | if(B.read() == 0.0) |
| alecselfridge | 2:f3ae10decc2f | 376 | b = 1.0; |
| alecselfridge | 2:f3ae10decc2f | 377 | b = b - .02; |
| alecselfridge | 2:f3ae10decc2f | 378 | } |
| alecselfridge | 2:f3ae10decc2f | 379 | // up : G |
| alecselfridge | 2:f3ae10decc2f | 380 | else if(!(joystick[1] & joystick[2])) { |
| alecselfridge | 2:f3ae10decc2f | 381 | if(G.read() == 0.0) |
| alecselfridge | 2:f3ae10decc2f | 382 | g = 1.0; |
| alecselfridge | 2:f3ae10decc2f | 383 | g = g - .02; |
| alecselfridge | 2:f3ae10decc2f | 384 | } |
| alecselfridge | 2:f3ae10decc2f | 385 | // center : confirm changes |
| alecselfridge | 2:f3ae10decc2f | 386 | else if(!joystick[0]) { |
| alecselfridge | 2:f3ae10decc2f | 387 | RGBPush(); |
| alecselfridge | 2:f3ae10decc2f | 388 | terminal.printf("RGB updated: (%f, %f, %f)", R.read(), G.read(), B.read()); |
| alecselfridge | 2:f3ae10decc2f | 389 | newline(); |
| alecselfridge | 2:f3ae10decc2f | 390 | } |
| alecselfridge | 1:0a93e9e88ad3 | 391 | } |
| alecselfridge | 1:0a93e9e88ad3 | 392 | |
| alecselfridge | 2:f3ae10decc2f | 393 | // "chase" pattern to verify LED array |
| alecselfridge | 2:f3ae10decc2f | 394 | void testLED(void) |
| alecselfridge | 2:f3ae10decc2f | 395 | { |
| alecselfridge | 2:f3ae10decc2f | 396 | LEDvals = 0x80; |
| alecselfridge | 2:f3ae10decc2f | 397 | LEDPush(0); |
| alecselfridge | 2:f3ae10decc2f | 398 | wait_ms(75); |
| alecselfridge | 2:f3ae10decc2f | 399 | for(int i = 0; i < 8; i++) { |
| alecselfridge | 2:f3ae10decc2f | 400 | LEDvals = LEDvals >> 1;; |
| alecselfridge | 2:f3ae10decc2f | 401 | LEDPush(0); |
| alecselfridge | 2:f3ae10decc2f | 402 | wait_ms(75); |
| alecselfridge | 2:f3ae10decc2f | 403 | } |
| alecselfridge | 2:f3ae10decc2f | 404 | LEDvals = 0x01; |
| alecselfridge | 2:f3ae10decc2f | 405 | LEDPush(0); |
| alecselfridge | 2:f3ae10decc2f | 406 | wait_ms(75); |
| alecselfridge | 2:f3ae10decc2f | 407 | for(int i = 0; i < 8; i++) { |
| alecselfridge | 2:f3ae10decc2f | 408 | LEDvals = LEDvals << 1;; |
| alecselfridge | 2:f3ae10decc2f | 409 | LEDPush(0); |
| alecselfridge | 2:f3ae10decc2f | 410 | wait_ms(75); |
| alecselfridge | 2:f3ae10decc2f | 411 | } |
| alecselfridge | 2:f3ae10decc2f | 412 | } |
| alecselfridge | 2:f3ae10decc2f | 413 | |
| alecselfridge | 2:f3ae10decc2f | 414 | // cycles thru various colors to show functionality of an RGB LED |
| alecselfridge | 2:f3ae10decc2f | 415 | void testRGB(void) |
| alecselfridge | 1:0a93e9e88ad3 | 416 | { |
| alecselfridge | 2:f3ae10decc2f | 417 | r = 1.0; g = 1.0; b = 1.0; |
| alecselfridge | 2:f3ae10decc2f | 418 | RGBPush(); |
| alecselfridge | 2:f3ae10decc2f | 419 | wait_ms(150); |
| alecselfridge | 2:f3ae10decc2f | 420 | r = 0.0; g = 1.0; b = 1.0; |
| alecselfridge | 2:f3ae10decc2f | 421 | RGBPush(); |
| alecselfridge | 2:f3ae10decc2f | 422 | wait_ms(150); |
| alecselfridge | 2:f3ae10decc2f | 423 | r = .6; g = 0.0; b = 0.0; |
| alecselfridge | 2:f3ae10decc2f | 424 | RGBPush(); |
| alecselfridge | 2:f3ae10decc2f | 425 | wait_ms(150); |
| alecselfridge | 2:f3ae10decc2f | 426 | r = 1.0; g = 1.0; b = 0.0; |
| alecselfridge | 2:f3ae10decc2f | 427 | RGBPush(); |
| alecselfridge | 2:f3ae10decc2f | 428 | wait_ms(150); |
| alecselfridge | 2:f3ae10decc2f | 429 | r = 1.0; g = 0.0; b = 0.0; |
| alecselfridge | 2:f3ae10decc2f | 430 | RGBPush(); |
| alecselfridge | 2:f3ae10decc2f | 431 | wait_ms(150); |
| alecselfridge | 2:f3ae10decc2f | 432 | r = 1.0; g = 0.0; b = 1.0; |
| alecselfridge | 2:f3ae10decc2f | 433 | RGBPush(); |
| alecselfridge | 2:f3ae10decc2f | 434 | wait_ms(150); |
| alecselfridge | 2:f3ae10decc2f | 435 | r = 1.0; g = 1.0; b = 0.0; |
| alecselfridge | 2:f3ae10decc2f | 436 | RGBPush(); |
| alecselfridge | 2:f3ae10decc2f | 437 | wait_ms(150); |
| alecselfridge | 2:f3ae10decc2f | 438 | r = 0.0; g = 0.0; b = 1.0; |
| alecselfridge | 2:f3ae10decc2f | 439 | RGBPush(); |
| alecselfridge | 2:f3ae10decc2f | 440 | wait_ms(150); |
| alecselfridge | 2:f3ae10decc2f | 441 | r = 0.0; g = 1.0; b = 1.0; |
| alecselfridge | 2:f3ae10decc2f | 442 | RGBPush(); |
| alecselfridge | 2:f3ae10decc2f | 443 | wait_ms(150); |
| alecselfridge | 2:f3ae10decc2f | 444 | r = 1.0; g = 1.0; b = 1.0; |
| alecselfridge | 2:f3ae10decc2f | 445 | RGBPush(); |
| alecselfridge | 2:f3ae10decc2f | 446 | wait_ms(150); |
| alecselfridge | 0:4555c427d7a8 | 447 | } |