LE KICKASS TEAM / Mbed 2 deprecated RTOS_Lights_Master

Dependencies:   mbed-rtos mbed

Revision:
2:f3ae10decc2f
Parent:
1:0a93e9e88ad3
Child:
3:25eba54bace2
diff -r 0a93e9e88ad3 -r f3ae10decc2f main.cpp
--- a/main.cpp	Wed Dec 02 23:11:31 2015 +0000
+++ b/main.cpp	Sun Dec 06 22:42:01 2015 +0000
@@ -1,11 +1,32 @@
+/************************************************************************
+* Authors: Alec Selfridge/Dylan Smith
+* Date:    12/4/2015
+* Rev:     1.4
+* Project: RTOS Light Animations
+* Notes:   The z-axis of the accelerometer is used to calculate the 
+*          "effective" angle that the board is tilted. First, the Z data
+*          (0-65) is converted to a (0-90) scale. Then the actual
+*          manipulation occurs by injecting the acc data into a response
+*          formula in the form of ax^2 - by + c. The resulting angle has
+*          no sign but it's magnitude is used to determine the rate at 
+*          which LEDs will "fill", thus simulating a gravity effect. To
+*          account for both directions of tilt we check the polarity of 
+*          the x-axis. A negative value indicates a tilt to the right
+*          and vice versa.
+*          A 5-axis joystick is used to mix R, G, and B values to create 
+*          a custom color. The RGB LED is controled via PWM with a value
+*          of 1.0 indicating "off" and vice versa.  
+*
+************************************************************************/
+
 #include "mbed.h"
 #include "rtos.h"
 #include "MMA7455.h"
 
-// thresholds for detecting a rotation of 90 deg or more
-#define X_TH 60
-#define Y_TH 60
-#define Z_TH 0
+// response formula coefficients
+#define X2 0.0038
+#define X  0.0299
+#define C  0.1883
 
 /*
 **************************
@@ -20,13 +41,18 @@
     Utility Functions
 **************************
 */
-void SerialInit();
-void AccInit();
-void LEDsInit();
-void accFeed();
+void SerialInit(void);
+void AccInit(void);
+void LEDsInit(void);
+void RgbInit(void);
+void accFeed(void);
 void sampleAcc(int period, int32_t data[3]);
-void LEDPush(void);
-void LEDS(void const *args);
+double getAngle(void);
+unsigned char mapLEDS(double v);
+void LEDPush(void const *args);
+void RGBpicker(void const *args);
+void testLED(void);
+void testRGB(void);
 
 /*
 **************************
@@ -34,7 +60,6 @@
 **************************
 */
 const char banner[37] = "Serial Comm Established with LPC4088";
-
 // x, y, z
 // holds current position
 int32_t accPos[3]           = {};
@@ -42,8 +67,20 @@
 int32_t accData[20][20][20] = {};
 // holds calibration offsets
 int32_t accCal[3]           = {};
-// a counter for LED animations
-uint8_t LEDvals = 0;
+// holds last acc value
+int32_t acc_old             = 0;
+// holds most recent, adjusted, acc value
+double acc_adj              = 0.0;
+// a value representing what's shown on the LEDs
+uint8_t LEDvals             = 0;
+// tracker of how many times the joystick was used
+uint8_t tick                = 0;
+// red value of RGB
+float r                     = 0;
+// green value of RGB
+float g                     = 0;
+// blue value of RGB
+float b                     = 0;
 
 /*
 **************************
@@ -58,6 +95,15 @@
 SPI leds(p5, NC, p7);
 // load for shift register
 DigitalOut ld(p30);
+// R of RGB LED
+PwmOut R(p25);
+// G of RGB LED
+PwmOut G(p28);
+// B of RGB LED
+PwmOut B(p26);
+// active-low 5-axis joystick
+// center, left_hi, right_hi, left_lo, right_lo
+BusIn joystick(p31, p32, p37, p39, p38);
 
 int main() {
     /*
@@ -66,22 +112,39 @@
     **************************
     */
     SerialInit();
-    AccInit();
-    
+    AccInit(); 
     LEDsInit();
+    testLED();
+    RgbInit();
+    testRGB();
     
-    RtosTimer refresh_timer(LEDS, osTimerPeriodic, (void *)0);
+    /*terminal.printf("Initializing tasks............");
+    Thread js_update(test);
+    js_update.set_priority(osPriorityNormal);
+    terminal.printf("done.");
+    newline();*/
+    terminal.printf("Initializing timers..........");
+    // timer responsible for updating the LEDs
+    RtosTimer refresh_timer(LEDPush, osTimerPeriodic, (void *)0);
+    // 16.7Hz timer (60ms or ~1/2 of 30fps)
     refresh_timer.start(60);
+    RtosTimer update_timer(RGBpicker, osTimerPeriodic, (void *)0);
+    // 10Hz timer (100ms)
+    update_timer.start(100);
+    terminal.printf("done.");
     
-    terminal.printf("Timer started.");    
+    newline(); newline();
+    terminal.printf("Initialization complete.");
+    newline(); 
     /*
     **************************
           Main Execution
     **************************
     */
-    while(1) {
+    while(true) {
         acc.read(accPos[0], accPos[1], accPos[2]);
-        LEDvals = (accPos[2]%4);   
+        acc_adj = getAngle();
+        LEDvals = mapLEDS(acc_adj);
     }
 }
 
@@ -92,7 +155,7 @@
 */
 void SerialInit()
 {
-    // initialize connection to PC
+    // initialize connection to PC. default: 8N1
     terminal.baud(19200);
     displayBanner();
     newline();
@@ -109,7 +172,7 @@
     if(acc.calibrate()) {
         newline();
         acc.getCalibrationOffsets(accCal[0], accCal[1], accCal[2]);
-        terminal.printf("  Offsets are (xyz): (%d) (%d) (%d)", accCal[0], accCal[1], accCal[2]);
+        terminal.printf("  Offsets are (x,y,z): (%d, %d, %d)", accCal[0], accCal[1], accCal[2]);
         newline(); newline();
     }
     else {
@@ -118,6 +181,31 @@
     }
 }
 
+void LEDsInit()
+{
+    terminal.printf("Initializing LED array.......");
+    leds.format(8, 3);      // 8-bit packet, polarity & phase mode 3
+    leds.frequency(100000); // 1MHz SPI
+    ld = 1;
+    LEDvals = 0x00;
+    terminal.printf("done.");
+    newline();
+}
+
+void RgbInit()
+{
+    terminal.printf("Initializing RGB LED.........");
+    // 1KHz
+    R.period(.001);
+    R = 1.0;
+    G.period(.001);
+    G = 1.0;
+    B.period(.001);
+    B = 1.0;
+    terminal.printf("done.");
+    newline();
+}
+
 void newline()
 {
     // newline = carriage return + line feed
@@ -158,7 +246,7 @@
         newline();
     }
     else {
-        terminal.printf("Unable to access MMA7455");
+        terminal.printf("Unable to access MMA7455.");
         newline();
     }
 }
@@ -185,40 +273,175 @@
     }
 }
 
-void LEDS(void const *args) 
+// called by the refresh timer every 60ms
+void LEDPush(void const *args)
+{
+    ld = 0; // active-low load
+    leds.write(LEDvals);
+    ld = 1; // "lock" lights
+}
+
+void RGBPush(void)
+{
+    R = r; 
+    G = g; 
+    B = b;
+}
+
+/* 
+    -0-90 degrees = 0-65 units (deg/unit ratio)
+    -90 - conversion = actual angle (a value of 65 means the device is flat)
+     thus, Theta = 90 - (90/65 * x) (90/65 = 1.38)
+    -Using ax^2 - by + c allows the data to fit into a custom model of about 1/3 scale
+     Therefore, the final equation is: Theta = 90 - 3(ax^2 - by + c) 
+*/ 
+double getAngle(void)
+{
+    double deg = 1.38 * accPos[2];
+    double cal = 1.38 * accCal[2];
+    return ( 90 - (3.0 * ((X2*deg*deg) - (X*cal) + C)) );
+}
+
+// look-up table based on ranges
+// this setup gives a nonlinear response from 0-90 degrees
+unsigned char mapLEDS(double v)
 {
-    LEDPush();
+    int angle = int(v);
+    if(accPos[0] < 0) {
+        if(angle < 8)
+            return 0xFF;
+        else if(angle >= 8 && angle < 15)
+            return 0x7F;
+        else if(angle >= 15 && angle < 25)
+            return 0x3F;
+        else if(angle >= 25 && angle < 35)
+            return 0x1F;
+        else if(angle >= 35 && angle < 40)
+            return 0x0F;           
+        else if(angle >= 40 && angle < 50)
+            return 0x07; 
+        else if(angle >= 50 && angle < 60)
+            return 0x03;
+        else if(angle >= 60 && angle < 70)
+            return 0x01;
+        else if(angle >= 70)
+            return 0x00;
+        else
+            return 0xFF;
+    }
+    else {
+        if(angle < 8)
+            return 0xFF;
+        else if(angle >= 8 && angle < 15)
+            return 0xFE;
+        else if(angle >= 15 && angle < 25)
+            return 0xFC;
+        else if(angle >= 25 && angle < 35)
+            return 0xF8;
+        else if(angle >= 35 && angle < 40)
+            return 0xF0;           
+        else if(angle >= 40 && angle < 50)
+            return 0xE0; 
+        else if(angle >= 50 && angle < 60)
+            return 0xC0;
+        else if(angle >= 60 && angle < 70)
+            return 0x80;
+        else if(angle >= 70)
+            return 0x00;
+        else
+            return 0xFF;
+    }
 }
 
-void LEDsInit()
+/*
+    joystick:   0       1         2         3        4
+             center  left_hi  right_hi  left_lo  right_lo  
+*/
+void RGBpicker(void const *args) 
 {
-    terminal.printf("Setting format...");
-    newline();
-    leds.format(8, 3);
-    leds.frequency(100000);
-    terminal.printf("Creating timer...");
-    newline();
-    ld = 1;
-    LEDvals = 0x00;
-    LEDPush();
-    LEDvals = 0xFF;
-    terminal.printf("LEDvals = %d", LEDvals);
-    newline();
-    /*LEDvals = 0xAA;
-    LEDPush();
-    wait(1);
-    LEDvals = 0x55;
-    LEDPush();*/
-    terminal.printf("Starting timer...");
-    newline();
-    terminal.printf("Timer started.");
+    tick++;
+    if(tick > 1) {
+        tick = 0;
+        return;
+    }
+    // left : R
+    if(!(joystick[1] & !joystick[3])) {
+        if(R.read() == 0.0)
+            r = 1.0;
+        r = r - .02;
+    }
+    // right : B
+    else if(!(joystick[2] & !joystick[4])) {
+        if(B.read() == 0.0)
+            b = 1.0;
+        b = b - .02;
+    }
+    // up : G
+    else if(!(joystick[1] & joystick[2])) {
+        if(G.read() == 0.0)
+            g = 1.0;
+        g = g - .02;
+    }
+    // center : confirm changes
+    else if(!joystick[0]) {
+        RGBPush();
+        terminal.printf("RGB updated: (%f, %f, %f)", R.read(), G.read(), B.read());
+        newline();
+    }
 }
 
-void LEDPush(void)
+// "chase" pattern to verify LED array
+void testLED(void)
+{
+    LEDvals = 0x80;
+    LEDPush(0);
+    wait_ms(75);
+    for(int i = 0; i < 8; i++) {
+        LEDvals = LEDvals >> 1;;
+        LEDPush(0);
+        wait_ms(75);
+    }
+    LEDvals = 0x01;
+    LEDPush(0);
+    wait_ms(75);
+    for(int i = 0; i < 8; i++) {
+        LEDvals = LEDvals << 1;;
+        LEDPush(0);
+        wait_ms(75);
+    }
+}
+
+// cycles thru various colors to show functionality of an RGB LED
+void testRGB(void)
 {
-    ld = 0;
-    leds.write(LEDvals);
-    ld = 1;
-    terminal.printf("LEDvals = %d", LEDvals);
-    newline();
+    r = 1.0; g = 1.0; b = 1.0;
+    RGBPush();
+    wait_ms(150);
+    r = 0.0; g = 1.0; b = 1.0;
+    RGBPush();
+    wait_ms(150);
+    r = .6; g = 0.0; b = 0.0;
+    RGBPush();
+    wait_ms(150);
+    r = 1.0; g = 1.0; b = 0.0;
+    RGBPush();
+    wait_ms(150);
+    r = 1.0; g = 0.0; b = 0.0;
+    RGBPush();
+    wait_ms(150);
+    r = 1.0; g = 0.0; b = 1.0;
+    RGBPush();
+    wait_ms(150);
+    r = 1.0; g = 1.0; b = 0.0;
+    RGBPush();
+    wait_ms(150);
+    r = 0.0; g = 0.0; b = 1.0;
+    RGBPush();
+    wait_ms(150);
+    r = 0.0; g = 1.0; b = 1.0;
+    RGBPush();
+    wait_ms(150);
+    r = 1.0; g = 1.0; b = 1.0;
+    RGBPush();
+    wait_ms(150);
 }
\ No newline at end of file