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.
Diff: main.cpp
- 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