Skip to content

Instantly share code, notes, and snippets.

@gwygonik
Last active August 29, 2015 14:12
Show Gist options
  • Save gwygonik/dee80233dffe22bc5227 to your computer and use it in GitHub Desktop.
Save gwygonik/dee80233dffe22bc5227 to your computer and use it in GitHub Desktop.
A demo of using the accelerometer in the L3D Cube to keep a "ground plane" level while rotating side to side. Two color modes - ground and water. You'll need to add the Adafruit Neopixel library to your code in Spark.
// 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
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];
delay(50); // delay slightly
}
// get the average to use as a base for rotation later
MIDVAL_X /= 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 val = floor((accelerometer[1] - MIDVAL_X) / 100);
// clamp the rotation to -3 to +3. Change to -4 to +4 for more extreme rotation
if (val < -3) val = -3;
if (val > 3) val = 3;
// update all the LEDs in the cube
for (int x=0;x<8;x++) {
for (int z=0;z<8;z++) {
int lval = intlerp(-val,val,x/8.0f); // lerp between negative of value to positive of value to keep level across
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
if (z == 0) {
for (int y=4+lval;y<8;y++) {
if (colorAsGround) {
// light blue sky background
strip.setPixelColor(y + (x * 8) + (z*64), strip.Color(0,100,105));
}
// water tank doesn't have a background
}
}
}
}
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