Forked from gwygonik/L3DCubeAccelerometerDemo.ino
Last active
August 29, 2015 14:12
-
-
Save mgrider/e1c983d280dbcae62bd6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This #include statement was automatically added by the Spark IDE. | |
#include "neopixel/neopixel.h" | |
#include <math.h> | |
//set up the pin that controls the LEDs, the type of LEDs (WS2812B) and the number of LEDs in the cube (8*8*8=512) | |
#define PIXEL_PIN D0 | |
#define PIXEL_COUNT 512 | |
#define PIXEL_TYPE WS2812B | |
#define SIDE 8 | |
//accelerometer pinout | |
#define X 13 | |
#define Y 14 | |
#define Z 15 | |
SYSTEM_MODE(SEMI_AUTOMATIC); //don't connect to the internet on boot | |
#define BUTTON D2 //press this button to connect to the internet | |
#define MODE D3 | |
bool onlinePressed=false; | |
bool lastOnline=true; | |
int accelerometer[3]; | |
int MIDVAL_X = 0; // to store the initial resting accelerometer value to compare against | |
int MIDVAL_Z = 0; | |
Adafruit_NeoPixel strip=Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE); | |
bool colorAsGround = true; // set to false to use "water tank" colors | |
// standard non-blocking millisecond update vars | |
long prevM = 0; | |
int interval = 25; // fast update, but allowing time for LED refresh | |
void setup() { | |
pinMode(7,OUTPUT); | |
digitalWrite(7, HIGH); | |
initCloudButton(); | |
strip.setBrightness(64); // dim all the LEDs. Set to 255, or comment out, for normal brightness | |
clearStrip(); | |
strip.show(); | |
// we're going to let the accelerometer settle | |
delay(500); | |
// grab 10 readings from the accelerometer | |
for (int i=0;i<10;i++) { | |
updateAccelerometer(); | |
MIDVAL_X += accelerometer[1]; | |
MIDVAL_Z += accelerometer[2]; | |
delay(50); // delay slightly | |
} | |
// get the average to use as a base for rotation later | |
MIDVAL_X /= 10; | |
MIDVAL_Z /= 10; | |
// pause for effect | |
delay(500); | |
} | |
void loop() | |
{ | |
checkCloudButton(); | |
updateAccelerometer(); | |
// check if we're needing to do an update | |
unsigned long curM = millis(); | |
if (curM - prevM > interval) { | |
prevM = curM; | |
clearStrip(); // clear all colors from cube | |
// subtract base rotation value from current value to get a negative to positive rotation value | |
// then divide by 100 to get a small number (the accelerometer values are in the thousands range) | |
int xVal = floor((accelerometer[1] - MIDVAL_X) / 100); | |
// clamp the rotation to -3 to +3. Change to -4 to +4 for more extreme rotation | |
if (xVal < -2) xVal = -2; | |
else if (xVal > 2) xVal = 2; | |
int zVal = floor((accelerometer[2] - MIDVAL_Z) / 100); | |
// clamp the rotation to -3 to +3. Change to -4 to +4 for more extreme rotation | |
if (zVal < -2) zVal = -2; | |
else if (zVal > 2) zVal = 2; | |
// update all the LEDs in the cube | |
for (int x=0;x<8;x++) { | |
int lXval = intlerp(-xVal,xVal,x/8.0f); // lerp between negative of value to positive of value to keep level across | |
for (int z=0;z<8;z++) { | |
int lZval = intlerp(-zVal,zVal,z/8.0f); // lerp between negative of value to positive of value to keep level across | |
int lval = lZval + lXval; | |
for (int y=0;y<4+lval;y++) { | |
if (colorAsGround) { | |
// brownish base, green grass | |
strip.setPixelColor(y + (x * 8) + (z*64),y < 3+lval ? strip.Color(24, 7, 0) : strip.Color(0, 70, 0)); | |
} else { | |
// dark blue base, light blue top level | |
strip.setPixelColor(y + (x * 8) + (z*64),y < 3+lval ? strip.Color(0, 0, (y+1)*3) : strip.Color(0, (y+1)*5, (y+1)*10)); | |
} | |
} | |
// draw the background plane | |
// (water tank doesn't have a background) | |
if (colorAsGround && z == 0) { | |
for (int y=4+lval;y<8;y++) { | |
// light blue sky background | |
strip.setPixelColor(y + (x * 8) + (z*64), strip.Color(0,100,105)); | |
} | |
} | |
} | |
} | |
strip.show(); | |
} | |
} | |
// function to return an integer between start and end values | |
int intlerp(int start, int end, float perc) { | |
return floor(start + perc*(end - start)); | |
} | |
// set all LEDs to black | |
void clearStrip() { | |
for (int p=0;p<PIXEL_COUNT;p++) { | |
strip.setPixelColor(p,0); | |
} | |
} | |
void updateAccelerometer() | |
{ | |
for(int i=0;i<3;i++) | |
accelerometer[i]=analogRead(X+i); | |
} | |
//sets up the online/offline switch | |
void initCloudButton() | |
{ | |
//set the input mode for the 'connect to cloud' button | |
pinMode(BUTTON, INPUT_PULLUP); | |
pinMode(MODE, INPUT_PULLUP); | |
if(!digitalRead(MODE)) | |
WiFi.listen(); | |
//a.k.a. onlinePressed is HIGH when the switch is set to 'online' and LOW when the switch is set to 'offline' | |
onlinePressed=digitalRead(BUTTON); | |
if(onlinePressed) | |
Spark.connect(); | |
} | |
//checks to see if the 'online/offline' switch is switched | |
void checkCloudButton() | |
{ | |
//if the 'connect to cloud' button is pressed, try to connect to wifi. | |
//otherwise, run the program | |
//note -- how does this behave when there are no wifi credentials loaded on the spark? | |
//onlinePressed is HIGH when the switch is _not_ connected and LOW when the switch is connected | |
//a.k.a. onlinePressed is HIGH when the switch is set to 'online' and LOW when the switch is set to 'offline' | |
onlinePressed=digitalRead(BUTTON); | |
if((!onlinePressed)&&(lastOnline)) //marked as 'online' | |
{ | |
lastOnline=onlinePressed; | |
Spark.connect(); | |
} | |
else if((onlinePressed)&&(!lastOnline)) //marked as 'offline' | |
{ | |
lastOnline=onlinePressed; | |
Spark.disconnect(); | |
} | |
lastOnline=onlinePressed; | |
if(!digitalRead(MODE)) | |
WiFi.listen(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment