Finishing Up - Final Project Step 6
Code:
See code made in Arduino for our project. For full breakdown of code see this post.
#include "Adafruit_NeoPixel.h" #include "Adafruit_NeoTrellis.h" #include <math.h> #ifdef __AVR__ #include <avr/power.h> #endif #define LED_PIN 6 #define PIXELS_PER_STRIP 15 #define NUM_STRIPS 15 Adafruit_NeoPixel pixels(PIXELS_PER_STRIP*NUM_STRIPS, LED_PIN, NEO_GRB + NEO_KHZ800); char data[100]; // for debugging print statements with sprintf bool trellisKeys[NEO_TRELLIS_NUM_KEYS] = ; int formerButton = 0; int buttonState = 0; Adafruit_NeoTrellis trellis; //define a callback for key presses TrellisCallback blink(keyEvent evt) { // Check is the pad pressed? if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING) { if (trellisKeys[evt.bit.NUM] == false) { trellisKeys[evt.bit.NUM] = true; trellis.pixels.setPixelColor(evt.bit.NUM, 255, 255, 255); //white trellis keys } else { trellis.pixels.setPixelColor(evt.bit.NUM, 0); //off falling trellisKeys[evt.bit.NUM] = false; } } trellis.pixels.show(); return 0; } void setup() { pinMode (2, INPUT); //pixels Serial.begin(9600); #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000) clock_prescale_set(clock_div_1); #endif pixels.begin(); // TRELLIS if (!trellis.begin()) { //Serial.println("Could not start trellis, check wiring?"); while (1); } else { //Serial.println("NeoPixel Trellis started"); } //activate all keys and set callbacks for (int i = 0; i < NEO_TRELLIS_NUM_KEYS; i++) { trellis.activateKey(i, SEESAW_KEYPAD_EDGE_RISING); // trellis.activateKey(i, SEESAW_KEYPAD_EDGE_FALLING); trellis.registerCallback(i, blink); } //do a little animation to show we're on for (uint16_t i = 0; i < trellis.pixels.numPixels(); i++) { trellis.pixels.setPixelColor(i, Wheel(map(i, 0, trellis.pixels.numPixels(), 0, 255))); trellis.pixels.show(); delay(50); } for (uint16_t i = 0; i < trellis.pixels.numPixels(); i++) { trellis.pixels.setPixelColor(i, 0x000000); trellis.pixels.show(); delay(50); } //PIXELS for (int i = 0; i < PIXELS_PER_STRIP * NUM_STRIPS; i++) { pixels.setPixelColor(i, 0x181818); //set to gray light (dimmed so it doesnt pull too much power and turn yellow at the bottom) } pixels.show(); } void loop() { buttonState = digitalRead(2); Serial.println(buttonState); if ( buttonState != formerButton && buttonState == 1) { //if former button state does not equal current button state && current button equals 1 reset(); } int NEWmappedPotH = map(analogRead(A1), 0, 1023, 0, 65536); //HUE int NEWmappedPotS = map(analogRead(A3), 0, 1023, 0, 255); //SATURATION int NEWmappedPotV = map(analogRead(A7), 0, 1023, 0, 140); //VALUE Serial.print(NEWmappedPotH); Serial.print(","); Serial.print(NEWmappedPotS); Serial.print(","); Serial.println(NEWmappedPotV); //ALL TRELLIS KEYS for (int i = 0; i < NEO_TRELLIS_NUM_KEYS; i++) { //look through array of trellis keys if (trellisKeys[i] == true) { //if key state is true // use division then modulo to map a 1d array to a 2d array int row = i / 4; // 4 = number of trellis rows int col = i % 4; // 4 = number of trellis columns //effecting color of LED matrix uint32_t rgbcolor = pixels.gamma32(pixels.ColorHSV(NEWmappedPotH, NEWmappedPotS, NEWmappedPotV)); setGridColor(row, col, rgbcolor); // Serial.print(row); // Serial.print(", "); // Serial.println(col); } } trellis.read(); // interrupt management does all the work! :) pixels.show(); delay(20); //the trellis has a resolution of around 60hz formerButton = buttonState; } // Input a value 0 to 255 to get a color value. // The colors are a transition r - g - b - back to r. uint32_t Wheel(byte WheelPos) { if (WheelPos < 85) { return trellis.pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0); } else if (WheelPos < 170) { WheelPos -= 85; return trellis.pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3); } else { WheelPos -= 170; return trellis.pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3); } return 0; } void setGridColor(int row, int col, uint32_t rgbcolor) { // unsigned 32 bit integer can represent 0 to (2^32)-1 // signed 32 bit integer can represent -(2^16) to (2^16)-1 float lightsPerRow = (float)NUM_STRIPS / 4.0; int startRow = (int)max(0, floor(lightsPerRow * row)); int endRow = (int)min(NUM_STRIPS, ceil(lightsPerRow * (row + 1))); float lightsPerCol = (float)PIXELS_PER_STRIP / 4.0; int startCol = (int)max(0, floor(lightsPerCol * col)); int endCol = (int)min(PIXELS_PER_STRIP, ceil(lightsPerCol * (col + 1))); // sprintf(data, "Selected (%d, %d)", row, col); // Serial.println(data); // // Serial.println(NUM_STRIPS / 4.0); // sprintf(data, "\tRows %d - %d (%f lights per row)", startRow, endRow, lightsPerRow); // Serial.println(data); // sprintf(data, "\tCols %d - %d (%f lights per col)", startCol, endCol, lightsPerCol); // Serial.println(data); // sprintf(data, "\tSet to color %d", rgbcolor); // Serial.println(data); //Dealing with the way the pixels are assembled on the lightwall to account for the squiggle for (int r = 0; r < NUM_STRIPS; r++) { for (int c = 0; c < PIXELS_PER_STRIP; c++) { if (r >= startRow && r < endRow && c >= startCol && c < endCol) { int pixelIndex; if (r % 2 == 0) { //math to map back from the 2d index to a 1d index pixelIndex = r * PIXELS_PER_STRIP + c; } else { //reverse math to accomodate the snaking of LEDs pixelIndex = (r + 1) * PIXELS_PER_STRIP - c - 1; } //sprintf is a serial print format // sprintf(data, "\tSetting pixel %d to color %d", pixelIndex, rgbcolor); // Serial.println(data); pixels.setPixelColor(pixelIndex, rgbcolor); } } } } void reset() { pixels.begin(); for (int i = 0; i < NEO_TRELLIS_NUM_KEYS; i++) { trellisKeys[i] = false; } for (uint16_t i = 0; i < trellis.pixels.numPixels(); i++) { trellis.pixels.setPixelColor(i, 0x000000); trellis.pixels.show(); delay(50); } //PIXELS for (int i = 0; i < PIXELS_PER_STRIP * NUM_STRIPS; i++) { pixels.setPixelColor(i, 0x181818); //set to gray light (dimmed so it doesnt pull too much power and turn yellow at the bottom) } pixels.show(); }
Solder Board:
One big step was moving our solderless breadboard to a solder board. This took some spatial planning. I started out by making a list of all the connection on the solderless board and then mapping them out onto a printout of the solder board. This made it petty easy to know where all the wires needed to go.
I then checked each of the components in the serial monitor to make sure everything was running correctly. Everything looked ok except for the neotrellis which wouldnt turn on. I used the multimetor set to continuity to check all of the wires. At first we were having an issue were the positive and negative sides of the bus lines were connecting. I think there was a tiny piece of a stranded wire that was connecting two wires because I put all the equipment away one night and then next morning when I came in to figure out why the bus lines were connected they were no longer connected so something must have been fixed when I moved the equipment. Even with the corrected bus lines though the neotrellis was not reading when plugged in. I de-soldered the neotrellis and tried it in a solderless breadboard - it worked fine. So then I re-soldered it but moved it lower down the breadboard because the top left area was getting crowded. I plugged it in and the neotrellis still didnt work. Finally, after asking for someone else to check over the breadboard we realized that I had forgotten to connect to the vin pin and to ground the Arduino! Once those were connected everything worked perfectly!
Light Wall:
The next step was to work on filling out our 15x15 neopixel matrix. We de-soldered our neopixel strands so that we had strips of 15 pixels and then soldered them together with 2 inch wires so that we would be able to make our snaking matrix. We needed to be carful to make sure that we were always soldering 5v to 5v, ground to ground and Din to Dout. We then did a strand test to make sure all of our soldering was done correctly and that all of our pixels were working.
Next Sydney used double sided tape to adhere the pixels to the foamcore in a grid.
We then made some light displays to see how everything was working
One problem we ran into was that if the lights were on full brightness and saturation we would see a gradient of color starting at the pure color near the power source and then getting dimmer/warmer farther from the power source. We knew we could solve this by adding another positive and negative power line to the matrix but we ended up changing the brightness value so that it wouldnt pull as much current. The mapping used to be 0-1023 changed to 0-255, and we changed this to 0-1023 changed to 0-140.
The last thing that we worked on was adding the semi-transparent plexi to diffuse the neo-pixels. We chose to mount the plexi 1” from the neopixels. And we added a wooden back and wooden sides or shields to minimize light spillover.
Box Construction
For playtesting we laser cut a cardboard top for our control panel. Once we confirmed the layout for the panel top we added holes for the screws which we measured with the caliper. We screwed in our components, then made a couple adjustments to the AI file and then laser cut it on plexi. We then mounted all of our components to the plexi using screws.
We cut holes in the box for the connection to the neopixels and to the power source and one whole in the side for the reset button.