- pin 9: LED strip data in
- pin A4: SDA of adxl345
- pin A5: SDL of adxl345
- 5V connected to adxl345 and LED strip
- GND connected to adxl and LED strip
Here's some close ups. The four wires you see are for the adxl345. On finished boards, there would be 5 more coming into the board: LED ground/power/data and battery pack positive and ground. The back is just some jumpers to read the encoder button get power/ground.
On that note, I was originally going to use an LM8705 to scoot down a 4 x AA battery pack to 5V for the LED strips (I'd read you can damage them at more than 5V). Then, I stumbled on the mention of powering a standalone Arduino through the LM8705 with 7 - 16V. I was only giving it 6V. I'm not really sure what happens at less than 7V, but after reading around more, I opted to just solder a jumper in my 4 x AA pack between the first slot negative and the second slot negative so that I'd get 4.5V from three instead.
Other than that, I used a prototype solder board (5 x 7cm cut in half) for everything and other than the above components, I just had to re-create the fairly straightforward Arduino on a breadboard.
Here's the parts I ended up using:
component | source | price | qty | total |
---|---|---|---|---|
atmega328p | eBay | 2.00 | 1 | 3.31 |
16 MHz crystal | mouser | 0.30 | 1 | 0.30 |
22pF cap | amazon | 0.091 | 2 | 0.18 |
28 pin socket | mouser | 0.77 | 1 | 0.77 |
adxl345 | ebay | 3.26 | 1 | 3.26 |
pcb | ebay | 1.09 | 1 | 1.09 |
battery holder | ax-man | 1.50 | 1 | 1.50 |
rotary encoder | mouser | 1.44 | 1 | 1.07 |
encoder knob | mouser | 0.46 | 1 | 0.46 |
22ga solid wire | amazon | 22.00 | - | 0 |
26ga stranded wire | amazon | 22.00 | 0.05 | 1.10 |
WS2112b 60 LED/m RGB strips | eBay | 39.99 | 0.2 | 8.00 |
belt clip | ax-man | 0.50 | 1 | 0.5 |
total | 21.54 |
I have to give a plug for tubelight, the eBay vendor I used for the LED strips. I found them to have the lowest cost ws2812b strips, period. So much so, that I contacted them after making my purchase (and about triple checking the specs) to make sure I was getting what I thought. I even included a link to the same item (but for much more) to verify the products were identical. They were, indeed.
I placed my order about 2mos in advance since the shipping window was huge. The day before the last day of the shipping estimate, tracking still said "origin is preparing shipment." Eeks. I took this to mean that they were still in China. I contacted tubelight and they DHL'd me a second set (I ordered 4 x 5m reels!) free. They asked if I was willing to resend on my second set (if and when it came) to other US buyers to save them having to re-send them. I was, but ultimately just bought the second set as well since my wife loves the idea of making some neat Christmas lights with them this year.
In any case, I simply insert the story as I was blown away that they'd go through that trouble and cost to make sure I hit the project deadline. Check them out!
The code is still a bit of a work in progress, but if you'd like to take a look, go for it!
#include "FastLED.h" #include "Wire.h"#include "Encoder.h" // adxl device for wire.h #define DEVICE (0x53) // must use fastLED 3.1: https://github.com/FastLED/FastLED/tree/FastLED3.1 // fast led constants and initialize #define DATA_PIN 9 #define LED_TYPE WS2812B #define COLOR_ORDER GRB #define NUM_LEDS 56 CRGB leds[NUM_LEDS]; // adxl setup byte _buff[6]; char POWER_CTL = 0x2D; //Power Control Register char DATA_FORMAT = 0x31; char DATAX0 = 0x32; //X-Axis Data 0 char DATAX1 = 0x33; //X-Axis Data 1 char DATAY0 = 0x34; //Y-Axis Data 0 char DATAY1 = 0x35; //Y-Axis Data 1 char DATAZ0 = 0x36; //Z-Axis Data 0 char DATAZ1 = 0x37; //Z-Axis Data 1 uint8_t howManyBytesToRead = 6; // encoder initialization Encoder enc(3, 4); int enc_switch = 2; int readings[50]; int read_index = 0; int totals = 0;; int rolling_ave = 0; int old_rolling_ave = 0; // global variables int bright = 200; int cutoff = 40; int mode = 0; // rainbow_equal int last = 0; int top = 0; double next = 0; double len = 3; // spinner double all_time = 1; double spin = 0; int mean_x = 0; int mean_y = 0; int mean_z = 0; int max_x = 200; int max_y = 200; int max_z = 200; double which = 0; // enc int last_time; int last_press; int press; int maxed = 200; int x; int y; int z; double count = 0; int last_pop = 0; void setup() { delay(2000); Serial.begin(9600); // tell FastLED about the LED strip configuration FastLED.addLeds (leds, NUM_LEDS).setCorrection(TypicalLEDStrip).setDither(bright < 255); FastLED.setBrightness(bright); pinMode(2, INPUT_PULLUP); // join i2c bus (address optional for master) Wire.begin(); // Put the ADXL345 into +/- 4G range by writing the value 0x01
// to the DATA_FORMAT register. // Think 0x00 = 2g, 00x1 = 4g, 00x2 = 8g, and 00x3 = 16g writeTo(DATA_FORMAT, 0x0B); //Put the ADXL345 into Measurement Mode by writing 0x08 to POWER_CTL register. writeTo(POWER_CTL, 0x08); } void loop() {
//read the acceleration data from the ADXL345 readFrom(DATAX0, howManyBytesToRead, _buff); // each axis reading comes in 10 bit resolution, ie 2 bytes.
// Least Significat Byte first!! // Thus we are converting both bytes in to one int x = (((int)_buff[1]) << 8) | _buff[0]; y = (((int)_buff[3]) << 8) | _buff[2]; z = (((int)_buff[5]) << 8) | _buff[4];
// the next section takes a constant average of the accelerometer
// and subtracts it from the current reading. this means that
// whatever orientation you put it in, it will tend towards readings of
// zero for all axes. I found the adxl's I got to have quite varied
// baselines, so this made sure that all of the suits would record an impulse
// based on motion "away from however you were positioned last."
mean_x = (x + mean_x) / 2; mean_y = (y + mean_y) / 2; mean_z = (z + mean_z) / 2; x = abs(x - mean_x); y = abs(y - mean_y); z = abs(z - mean_z);
// I logged some motion and figured out the top end was around 250 top = constrain(x + y + z, 0, 250); //constrain(max(x, max(y, z)), 0, 225);
// I found that a moving average might be helpful to remove super close
// instances of multiple accelerations above the threshold. I may tweak
// it some more, but it definitely helped smooth things out
readings[read_index] = top; read_index = read_index + 1; totals = 0; for(int i = 0; i < 60; i++){ totals = readings[i] + totals; } rolling_ave = totals / 60; if(read_index > 59) { old_rolling_ave = rolling_ave; read_index = 0; }
// for now, just the button is read. push it and it cycles the mode
// and flashes a color based on which one you're setting.
// eventually I'd like a long-press to set things like the acc cutoff if(!digitalRead(enc_switch)) { leds[0] = CHSV(mode * (255/4) + 1, 255, 150); FastLED.show(); delay(500); mode = mode + 1; if(mode > 3) { mode = 0;} leds[0] = CHSV(mode * (255/3) + 1, 255, 150); FastLED.show(); delay(1000); } switch(mode) { case 0:
rainbow_equal(); break; case 1: sparkler(); break; case 2: spinner(); break; case 3: rainbow_fade(); break; } } void rainbow_equal() { //top = max(x, max(y, z)); //FastLED.setBrightness(200); if(len > 1) { len = len - (.012 * len); bright = map(len, 1, NUM_LEDS / 2, 10, 150); FastLED.setBrightness(bright); } if(top > cutoff) { last = len; len = map(top, cutoff, maxed, 8, NUM_LEDS / 2); if(last > len) { len = last + 3; if (len > NUM_LEDS / 2) {len = NUM_LEDS / 2;} } } next = next + 1; int start = NUM_LEDS - len; fill_rainbow(leds, len, next, 3); fill_rainbow(leds + start, len, next, 3); FastLED.show(); FastLED.clear(); next = next + 1; delay(4); } void spinner() { //next = 0; if(spin > 4) { spin = pow(spin, 0.996); bright = map(spin, 5, 35, 50, 255); next = next + spin; FastLED.setBrightness(bright); } else { next = next + 2; } //top = max(x, y); if(top > cutoff & spin < 15) { spin = map(top, cutoff, maxed, 8, 35); bright = map(top, cutoff, maxed, 70, 200); next = next + spin; FastLED.setBrightness(bright); } if(next > 255) { next = next - 255; } fill_rainbow(leds, NUM_LEDS / 2, next, 15); fill_rainbow(leds + (NUM_LEDS / 2), NUM_LEDS / 2, 255 - next, 15); //fill_rainbow(leds + 30, 15, next, 15); //fill_rainbow(leds + 45, 15, 255 - next, 15); FastLED.show(); delay(3); } void sparkler() { FastLED.setBrightness(200); //top = max(x, max(y, z)); int num = constrain(map(top, cutoff, maxed, 20, 200), 1, 100); while(num > 0) { int i = random8(0, NUM_LEDS - 1); if (i < NUM_LEDS) leds[i] = CHSV(random8(), random8(50,255), random8(10, 200)); num = num - 1; } for (int j = 0; j < NUM_LEDS; j++) leds[j].fadeToBlackBy(random8(20, 60)); LEDS.show(); delay(50); } void rainbow_fade() { if(top > cutoff & rolling_ave > old_rolling_ave) { count = map(top, cutoff, maxed, 50, 500); if(last > count) { count = last + 5; } if(count > 500) { count = 500; } if(millis() - last_pop > 750){ last_pop = millis(); if(x > y) { if(x > z) { if(y > z) { next = 0 + (y/x * 10); } else { next = 160 + (z/x * 10); } } else { next = 160 + (x/z * 10); } } else { if(x > z) { next = 96 - (x/y * 10); } else { next = 96 + (z/y * 10); } } } } last = count; bright = constrain(map(count, 3, 500, 10, 225), 10, 225); /* if(count > last) { FastLED.setBrightness(bright); fill_rainbow(leds, NUM_LEDS, next, 150 / (count + 1)); FastLED.show(); FastLED.clear(); delay(50); } */ if(count > 3) { count = pow(count, 0.987); } else { count = 0; bright = 0; } FastLED.setBrightness(bright); fill_rainbow(leds, NUM_LEDS, next + 200/count, 1); //constrain(50 / (count + 1), 1, 20)); FastLED.show(); FastLED.clear(); delay(2); } ////////// begin accelerometer reader ////////// void writeTo(byte address, byte val) { Wire.beginTransmission(DEVICE); // start transmission to device Wire.write(address); // send register address Wire.write(val); // send value to write Wire.endTransmission(); // end transmission } // Reads num bytes starting from address register on device in to _buff array void readFrom(byte address, int num, byte _buff[]) { Wire.beginTransmission(DEVICE); // start transmission to device Wire.write(address); // sends address to read from Wire.endTransmission(); // end transmission Wire.beginTransmission(DEVICE); // start transmission to device Wire.requestFrom(DEVICE, num); // request 6 bytes from device int i = 0; while(Wire.available()) // device may send less than requested (abnormal) { _buff[i] = Wire.read(); // receive a byte i++; } Wire.endTransmission(); // end transmission } ////////// end accelerometer reader ////////// void fadeLEDs(int fadeVal, int which){ for (int i = 0; i < which; i++){ leds[29 - i].fadeToBlackBy( fadeVal ); leds[30 + i].fadeToBlackBy( fadeVal ); } }
No comments:
Post a Comment
formatting help: <i>italics</i>, <b>bold</b>