Assignment 5 for OCE360, timers, tickers, and interrupts.
Dependencies: 4DGL-uLCD-SE MMA8452Q SDFileSystem bouncing_ball mbed
Fork of OCE360_4 by
main.cpp@11:abfb94de3a41, 2017-11-16 (annotated)
- Committer:
- rsean10
- Date:
- Thu Nov 16 15:01:30 2017 +0000
- Revision:
- 11:abfb94de3a41
- Parent:
- 10:1fe988d4e61e
- Child:
- 12:1b20c6eceae8
writes 1 line to sd card, does not write data
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
slicht | 2:552e6feb8709 | 1 | // A solution to OCE360 Homework #4. |
slicht | 2:552e6feb8709 | 2 | // Objective: Use object oriented programming to create a system that displays |
slicht | 2:552e6feb8709 | 3 | // multiple balls bouncing around the LCD screen. |
slicht | 3:a7f02754bc99 | 4 | // Stephen Licht, 11/7/2017 |
slicht | 1:6b99ffa62cc8 | 5 | |
slicht | 0:8d3812068c6c | 6 | #include "mbed.h" |
slicht | 2:552e6feb8709 | 7 | #include "MMA8452Q.h" //acceleromater library |
slicht | 2:552e6feb8709 | 8 | #include "uLCD_4DGL.h" //LCD library |
slicht | 2:552e6feb8709 | 9 | #include "bouncing_ball.h" //new ball phyics library |
rsean10 | 8:2617100c441d | 10 | #include "SDFileSystem.h" |
slicht | 1:6b99ffa62cc8 | 11 | |
slicht | 2:552e6feb8709 | 12 | #define UPDATE_TIME_S 0.02 |
slicht | 2:552e6feb8709 | 13 | #define START_X_1 10 |
slicht | 2:552e6feb8709 | 14 | #define START_Y_1 10 |
slicht | 2:552e6feb8709 | 15 | #define START_X_2 20 |
slicht | 2:552e6feb8709 | 16 | #define START_Y_2 20 |
slicht | 2:552e6feb8709 | 17 | #define RADIUS_1 6 |
slicht | 2:552e6feb8709 | 18 | #define RADIUS_2 3 |
slicht | 0:8d3812068c6c | 19 | |
slicht | 2:552e6feb8709 | 20 | #define DEBUG_MODE 0 |
slicht | 2:552e6feb8709 | 21 | |
rsean10 | 6:050104c0dc75 | 22 | #define LCD_UPDATE .091 //11 Hz |
rsean10 | 9:7a577d790538 | 23 | |
rsean10 | 10:1fe988d4e61e | 24 | // Accelerometer - SDA, SCL, and I2C address |
rsean10 | 10:1fe988d4e61e | 25 | MMA8452Q accel(p28, p27, 0x1D); //initialize a driver object for an accelerometer connected on pins 27-28. |
rsean10 | 10:1fe988d4e61e | 26 | |
rsean10 | 9:7a577d790538 | 27 | // Analog input (pin 15) |
rsean10 | 9:7a577d790538 | 28 | AnalogIn tempin(p15); |
rsean10 | 5:93f88deda5ba | 29 | |
rsean10 | 5:93f88deda5ba | 30 | //Initialize Serial communication |
rsean10 | 5:93f88deda5ba | 31 | Serial pc(USBTX, USBRX); |
rsean10 | 5:93f88deda5ba | 32 | |
rsean10 | 8:2617100c441d | 33 | // SD card (SPI pins) |
rsean10 | 8:2617100c441d | 34 | SDFileSystem sd(p5, p6, p7, p8, "sd"); |
rsean10 | 8:2617100c441d | 35 | |
rsean10 | 9:7a577d790538 | 36 | //Drawing positions |
rsean10 | 9:7a577d790538 | 37 | int lastx1; |
rsean10 | 9:7a577d790538 | 38 | int lasty1; |
rsean10 | 9:7a577d790538 | 39 | int lastx2; |
rsean10 | 9:7a577d790538 | 40 | int lasty2; |
rsean10 | 9:7a577d790538 | 41 | |
rsean10 | 6:050104c0dc75 | 42 | //Led Initialization |
rsean10 | 6:050104c0dc75 | 43 | DigitalOut led1(LED1); //update leds |
rsean10 | 6:050104c0dc75 | 44 | DigitalOut led2(LED2); |
rsean10 | 7:614b40b85579 | 45 | DigitalOut led3(LED3); |
rsean10 | 6:050104c0dc75 | 46 | |
rsean10 | 7:614b40b85579 | 47 | //Toggle Initialization |
rsean10 | 7:614b40b85579 | 48 | InterruptIn button(p13); //Interrupt on the button on pin 13 |
rsean10 | 7:614b40b85579 | 49 | Timer debounce; //defines debounce timer for proper switching |
rsean10 | 7:614b40b85579 | 50 | |
rsean10 | 8:2617100c441d | 51 | int recorder = 0; |
rsean10 | 8:2617100c441d | 52 | |
rsean10 | 7:614b40b85579 | 53 | void toggle(){ |
rsean10 | 7:614b40b85579 | 54 | if(debounce.read_ms()>175){ |
rsean10 | 9:7a577d790538 | 55 | led3= !led3; |
rsean10 | 8:2617100c441d | 56 | recorder = !recorder; |
rsean10 | 7:614b40b85579 | 57 | debounce.reset(); //restart timer after toggle occurs |
rsean10 | 7:614b40b85579 | 58 | } |
rsean10 | 7:614b40b85579 | 59 | } |
rsean10 | 6:050104c0dc75 | 60 | |
rsean10 | 8:2617100c441d | 61 | //Position recorder |
rsean10 | 9:7a577d790538 | 62 | Timer logtimer; |
rsean10 | 9:7a577d790538 | 63 | Ticker logticker; |
rsean10 | 8:2617100c441d | 64 | |
rsean10 | 10:1fe988d4e61e | 65 | float voltage_in; |
rsean10 | 10:1fe988d4e61e | 66 | float degrees_c; |
rsean10 | 10:1fe988d4e61e | 67 | |
rsean10 | 10:1fe988d4e61e | 68 | FILE *file; |
rsean10 | 10:1fe988d4e61e | 69 | void datarecord(); |
rsean10 | 8:2617100c441d | 70 | |
slicht | 2:552e6feb8709 | 71 | //Function prototype for color selection function: |
slicht | 2:552e6feb8709 | 72 | int get_LCD_color(int color_integer); |
slicht | 1:6b99ffa62cc8 | 73 | |
slicht | 1:6b99ffa62cc8 | 74 | // Graphic LCD - TX, RX, and RES pins |
slicht | 2:552e6feb8709 | 75 | uLCD_4DGL uLCD(p9,p10,p11); //initialize a driver object for an LCD connected on pins 9-11 |
slicht | 1:6b99ffa62cc8 | 76 | |
slicht | 2:552e6feb8709 | 77 | physics_ball ball1; //initialize two balls for bouncing |
slicht | 2:552e6feb8709 | 78 | physics_ball ball2; //the default states from the library will be used initially |
slicht | 0:8d3812068c6c | 79 | |
rsean10 | 6:050104c0dc75 | 80 | //Ticker for update |
rsean10 | 6:050104c0dc75 | 81 | Ticker update1; //ball 1 ticker for update position |
rsean10 | 6:050104c0dc75 | 82 | Ticker update2; //ball 2 ticker for update position |
rsean10 | 6:050104c0dc75 | 83 | |
rsean10 | 6:050104c0dc75 | 84 | void ball1up(){ |
rsean10 | 6:050104c0dc75 | 85 | ball1.update(UPDATE_TIME_S,accel); //updates position |
rsean10 | 6:050104c0dc75 | 86 | led1 = !led1; //changes led state every update |
rsean10 | 6:050104c0dc75 | 87 | } |
rsean10 | 6:050104c0dc75 | 88 | |
rsean10 | 6:050104c0dc75 | 89 | void ball2up(){ |
rsean10 | 6:050104c0dc75 | 90 | ball2.update(UPDATE_TIME_S,accel); //updates position |
rsean10 | 6:050104c0dc75 | 91 | led2 = !led2; //changes led state every update |
rsean10 | 6:050104c0dc75 | 92 | } |
rsean10 | 6:050104c0dc75 | 93 | |
rsean10 | 6:050104c0dc75 | 94 | //Ticker for display |
rsean10 | 6:050104c0dc75 | 95 | Ticker displayup; //ticker for displaying ball on lcd |
rsean10 | 6:050104c0dc75 | 96 | |
rsean10 | 6:050104c0dc75 | 97 | void display(){ |
rsean10 | 9:7a577d790538 | 98 | |
rsean10 | 9:7a577d790538 | 99 | // Erase old circles by writing over there locations using the screen color: |
rsean10 | 9:7a577d790538 | 100 | uLCD.filled_circle(lastx1, lasty1, ball1.radius, BLACK); |
rsean10 | 9:7a577d790538 | 101 | uLCD.filled_circle(lastx2, lasty2, ball2.radius, BLACK); |
rsean10 | 9:7a577d790538 | 102 | |
rsean10 | 6:050104c0dc75 | 103 | // Draw circles in the x and y positions stored by the ball objects: |
rsean10 | 6:050104c0dc75 | 104 | uLCD.filled_circle(ball1.posx, ball1.posy, ball1.radius, get_LCD_color(ball1.color)); |
rsean10 | 6:050104c0dc75 | 105 | uLCD.filled_circle(ball2.posx, ball2.posy, ball2.radius, get_LCD_color(ball2.color)); |
rsean10 | 9:7a577d790538 | 106 | |
rsean10 | 9:7a577d790538 | 107 | //Sets previous ball position to be erased in next iteration |
rsean10 | 9:7a577d790538 | 108 | lastx1 = ball1.posx; |
rsean10 | 9:7a577d790538 | 109 | lasty1 = ball1.posy; |
rsean10 | 9:7a577d790538 | 110 | lastx2 = ball2.posx; |
rsean10 | 9:7a577d790538 | 111 | lasty2 = ball2.posy; |
rsean10 | 5:93f88deda5ba | 112 | } |
rsean10 | 5:93f88deda5ba | 113 | |
rsean10 | 5:93f88deda5ba | 114 | int main(){ |
rsean10 | 9:7a577d790538 | 115 | |
slicht | 1:6b99ffa62cc8 | 116 | // Initialize uLCD |
slicht | 1:6b99ffa62cc8 | 117 | uLCD.baudrate(115200); |
slicht | 1:6b99ffa62cc8 | 118 | uLCD.background_color(BLACK); |
slicht | 1:6b99ffa62cc8 | 119 | uLCD.cls(); |
rsean10 | 8:2617100c441d | 120 | |
slicht | 1:6b99ffa62cc8 | 121 | // Initialize accelerometer |
slicht | 1:6b99ffa62cc8 | 122 | accel.init(); |
slicht | 1:6b99ffa62cc8 | 123 | |
slicht | 2:552e6feb8709 | 124 | //Initialize balls: |
slicht | 2:552e6feb8709 | 125 | ball1.set_state(START_X_1,START_Y_1,0,0); //speeds are set to zero |
slicht | 2:552e6feb8709 | 126 | ball1.set_state(START_X_2,START_Y_2,0,0); |
slicht | 2:552e6feb8709 | 127 | |
slicht | 2:552e6feb8709 | 128 | //Set ball radius and color: |
slicht | 2:552e6feb8709 | 129 | ball1.set_param(RADIUS_1,0); //color is unimportant |
slicht | 2:552e6feb8709 | 130 | ball2.set_param(RADIUS_2,1); //just making sure the colors are different |
slicht | 2:552e6feb8709 | 131 | |
rsean10 | 6:050104c0dc75 | 132 | update1.attach(&ball1up,UPDATE_TIME_S); //ticker force position update ball 1 |
rsean10 | 6:050104c0dc75 | 133 | update2.attach(&ball2up,UPDATE_TIME_S); //ticker force position update ball 2 |
rsean10 | 6:050104c0dc75 | 134 | |
rsean10 | 6:050104c0dc75 | 135 | displayup.attach(&display,LCD_UPDATE); //ticker force lcd update |
rsean10 | 6:050104c0dc75 | 136 | |
rsean10 | 8:2617100c441d | 137 | debounce.start(); //starts debounce timer |
rsean10 | 8:2617100c441d | 138 | button.rise(&toggle); //toggles on button press |
rsean10 | 8:2617100c441d | 139 | |
rsean10 | 9:7a577d790538 | 140 | while (1) { //execute 'forever' |
rsean10 | 8:2617100c441d | 141 | |
rsean10 | 9:7a577d790538 | 142 | if (recorder == 1){ |
rsean10 | 9:7a577d790538 | 143 | //File Writing |
rsean10 | 10:1fe988d4e61e | 144 | //FILE *file; |
rsean10 | 9:7a577d790538 | 145 | file = fopen("/sd/ball_data.txt", "w"); |
rsean10 | 9:7a577d790538 | 146 | if ( file == NULL ) { |
rsean10 | 9:7a577d790538 | 147 | error("ERROR: Could not open file for writing!\n\r"); |
rsean10 | 9:7a577d790538 | 148 | return -1; |
rsean10 | 9:7a577d790538 | 149 | } |
rsean10 | 9:7a577d790538 | 150 | // Tell the user we need to wait while we collect some data |
rsean10 | 9:7a577d790538 | 151 | pc.printf("\nCollecting data (Do not remove SD Card!) ...\n\r"); |
rsean10 | 11:abfb94de3a41 | 152 | logtimer.start(); |
rsean10 | 9:7a577d790538 | 153 | fprintf(file, " Time X Position Y Position X Accleration Y Acceleration Temperature\n\r"); |
rsean10 | 11:abfb94de3a41 | 154 | //logticker.attach(&datarecord,LCD_UPDATE); |
rsean10 | 9:7a577d790538 | 155 | pc.printf("\nData Recorded Sucessfully! \n\r"); |
rsean10 | 11:abfb94de3a41 | 156 | logtimer.reset(); |
rsean10 | 9:7a577d790538 | 157 | |
rsean10 | 9:7a577d790538 | 158 | // Close file |
rsean10 | 9:7a577d790538 | 159 | fclose(file); |
rsean10 | 9:7a577d790538 | 160 | } |
rsean10 | 6:050104c0dc75 | 161 | |
slicht | 2:552e6feb8709 | 162 | if (DEBUG_MODE) { |
slicht | 3:a7f02754bc99 | 163 | //If compiled with DEBUG_MODE flag raised, print values to screen. |
slicht | 2:552e6feb8709 | 164 | uLCD.locate(0,4); |
slicht | 2:552e6feb8709 | 165 | uLCD.printf("X: %d.1\nY: %.1d",ball1.posx,ball1.posy); |
rsean10 | 9:7a577d790538 | 166 | |
slicht | 2:552e6feb8709 | 167 | uLCD.locate(0,6); |
slicht | 2:552e6feb8709 | 168 | uLCD.printf("VX: %f.1\nVY: %.1f",ball1.speedx,ball1.speedy); |
rsean10 | 9:7a577d790538 | 169 | |
slicht | 2:552e6feb8709 | 170 | uLCD.locate(0,10); |
slicht | 2:552e6feb8709 | 171 | uLCD.printf("AX: %f.1\nAY: %.1f\nAZ: %0.1f",accel.readX(),accel.readY(),accel.readZ()); |
slicht | 2:552e6feb8709 | 172 | } |
slicht | 2:552e6feb8709 | 173 | } |
slicht | 2:552e6feb8709 | 174 | } |
slicht | 1:6b99ffa62cc8 | 175 | |
slicht | 3:a7f02754bc99 | 176 | //Interpret LCD colors. |
slicht | 2:552e6feb8709 | 177 | int get_LCD_color(int color_integer) |
slicht | 2:552e6feb8709 | 178 | { |
slicht | 2:552e6feb8709 | 179 | switch (color_integer) { |
slicht | 2:552e6feb8709 | 180 | case 0: |
slicht | 2:552e6feb8709 | 181 | return(RED); |
slicht | 2:552e6feb8709 | 182 | case 1: |
slicht | 2:552e6feb8709 | 183 | return(BLUE); |
slicht | 2:552e6feb8709 | 184 | case 2: |
slicht | 2:552e6feb8709 | 185 | return(GREEN); |
slicht | 2:552e6feb8709 | 186 | default: |
slicht | 2:552e6feb8709 | 187 | return(WHITE); |
slicht | 0:8d3812068c6c | 188 | } |
rsean10 | 10:1fe988d4e61e | 189 | } |
rsean10 | 10:1fe988d4e61e | 190 | |
rsean10 | 10:1fe988d4e61e | 191 | void datarecord(){ |
rsean10 | 10:1fe988d4e61e | 192 | float time = 1*logtimer.read(); |
rsean10 | 10:1fe988d4e61e | 193 | float pos1x = 1*ball1.posx; |
rsean10 | 10:1fe988d4e61e | 194 | float pos1y = 1*ball1.posy; |
rsean10 | 10:1fe988d4e61e | 195 | float spe1x = 1*ball1.speedx; |
rsean10 | 10:1fe988d4e61e | 196 | float spe1y = 1*ball1.speedy; |
rsean10 | 10:1fe988d4e61e | 197 | float accx = 1*accel.readX(); |
rsean10 | 10:1fe988d4e61e | 198 | float accy = 1*accel.readY(); |
rsean10 | 10:1fe988d4e61e | 199 | |
rsean10 | 10:1fe988d4e61e | 200 | float pos2x = 1*ball2.posx; |
rsean10 | 10:1fe988d4e61e | 201 | float pos2y = 1*ball2.posy; |
rsean10 | 10:1fe988d4e61e | 202 | float spe2x = 1*ball2.speedx; |
rsean10 | 10:1fe988d4e61e | 203 | float spe2y = 1*ball2.speedy; |
rsean10 | 10:1fe988d4e61e | 204 | |
rsean10 | 10:1fe988d4e61e | 205 | voltage_in = tempin * 3.3; |
rsean10 | 10:1fe988d4e61e | 206 | degrees_c = (voltage_in - 0.5) * 100.0; |
rsean10 | 10:1fe988d4e61e | 207 | |
rsean10 | 10:1fe988d4e61e | 208 | fprintf(file, "Ball 1: %.3g %.3g %.3g %.3g %.3g %.3g %.3g %.3g\n\r",time,pos1x,pos1y,spe1x,spe1y,accx,accy,degrees_c); |
rsean10 | 10:1fe988d4e61e | 209 | |
rsean10 | 10:1fe988d4e61e | 210 | fprintf(file, "Ball 2: %.3g %.3g %.3g %.3g \n\r",pos2x,pos2y,spe2x,spe2y); |
rsean10 | 10:1fe988d4e61e | 211 | } |