Full Instructions
User Manual: Pdf
Open the PDF directly: View PDF .
Page Count: 29
Download | ![]() |
Open PDF In Browser | View PDF |
Animated LED Sand Created by Ruiz Brothers Last updated on 2018-02-06 04:55:15 PM UTC Guide Contents Guide Contents Overview 2 3 Simulated Glowy Physics! Prerequisite Guides 3 3 Adafruit Feather M0 Basic Proto - ATSAMD21 Cortex M0 Adafruit 15x7 CharliePlex LED Matrix Display FeatherWings Lithium Ion Polymer Battery - 3.7v 350mAh Adafruit LIS3DH Triple-Axis Accelerometer (+-2g/4g/8g/16g) Breadboard-friendly SPDT Slide Switch Ultimaker 2+ 3D Printer PLA Filament for 3D Printers - 1.75mm Diameter - Teal - 1KG 4 4 5 5 5 5 6 Circuit Diagram Code 3D Printing 7 8 13 Slice Settings Clean up 14 14 Assembly 15 Measure Wires Assemble Slide Switch Wire Boards Solder Slide Switch Solder Accelerometer Accelerometer Mount Spacer Attach boards Bundle wires Mount Battery Attach Spacer Plug in battery Mount inside enclosure Tuck wires Align mounting holes Face cover Slide Switch Tolerances Slide Switch Mount Attach Lid Gimbal Assemble Teeter totter © Adafruit Industries 15 15 17 17 18 19 20 20 21 22 23 24 24 24 24 25 27 27 27 27 28 https://learn.adafruit.com/animated-led-sand Page 2 of 29 Overview Simulated Glowy Physics! These LEDs interact with motion and looks like they’re affect by gravity. An Adafruit LED matrix displays the LEDs as little grains of sand which are driven by sampling an accelerometer with an Adafruit Feather. The code, written by Phillip Burgess, simulates physics by calculating collisions and terminal velocity. We designed 3d printed enclosures to take advantage of sensor readings by allowing it teeter totter as well as a gimbal to create interesting simulations. Prerequisite Guides I suggest walking through the following guides to get a better understanding of the electronics. Adafruit LIS3DH Triple-Axis Accelerometer Adafruit 15x7 CharliePlex LED Matrix Adafruit Feather M0 Basic © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 3 of 29 6 x M2X8mm Screws M2x8mm screws 2 x M2X4mm screws M2X4mm screws Adafruit Feather M0 Basic Proto - ATSAMD21 Cortex M0 PRODUCT ID: 2772 https://adafru.it/s1d $19.95 IN STOCK Your browser does not support the video tag. Adafruit 15x7 CharliePlex LED Matrix Display FeatherWings PRODUCT ID: 2965 https://adafru.it/wft $0.00 OUT OF STOCK © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 4 of 29 Lithium Ion Polymer Battery - 3.7v 350mAh PRODUCT ID: 2750 https://adafru.it/kBj $6.95 IN STOCK Adafruit LIS3DH Triple-Axis Accelerometer (+2g/4g/8g/16g) PRODUCT ID: 2809 https://adafru.it/uBq $4.95 IN STOCK Breadboard-friendly SPDT Slide Switch PRODUCT ID: 805 https://adafru.it/drN $0.95 IN STOCK Ultimaker 2+ 3D Printer PRODUCT ID: 2673 https://adafru.it/zef $2,499.00 IN STOCK © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 5 of 29 PLA Filament for 3D Printers - 1.75mm Diameter - Teal 1KG PRODUCT ID: 3069 https://adafru.it/AeV $39.95 IN STOCK © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 6 of 29 Circuit Diagram Take a moment to review the components in the circuit diagram. This illustration is meant for referencing wired connections - The length of wire, position and size of components are not exact. The Slide switch will connect to the Feather board and will need to be 70mm for the GND and 50mm for the EN pin CharliePlex Featherwing connects the Feather. The connections for SDA and SCL wires will need to be 70mm long. 3V and GND connections can both be 80mm long LIS3DH connects to the top of the Feather via the 3d printed mount and will needto be 40mm long for 3V, GND, SDA and SCL connections. © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 7 of 29 Code To use the LED Sand sketch you'll want to make sure you're using the latest version of the Arduino IDE (1.6.5 at the time of this writing). If you're totally new to Arduino take a little time to go through some introductory tutorials like how to make a LED blink. This will help you understand how to use the IDE, load a sketch, and upload code. Next you'll need to make sure the libraries used by the sketch are installed. With the latest Arduino IDE you can use its library manager to easily install libraries, or check out this guide on how to manually install a library. You'll want to install the following libraries: Adafruit LIS3DH Adafruit Unified Sensor Adafruit IS31FL3731 Charlieplex LED Search for the libraries in the library manager and they should be easy to find and install. If you already have one or more of these libraries installed then make sure to update it to the latest version. //-------------------------------------------------------------------------// Animated 'sand' for Adafruit Feather. Uses the following parts: // - Feather 32u4 Basic Proto (adafruit.com/product/2771) // - Charlieplex FeatherWing (adafruit.com/product/2965 - any color!) // - LIS3DH accelerometer (2809) // - 350 mAh LiPoly battery (2750) // - SPDT Slide Switch (805) // // This is NOT good "learn from" code for the IS31FL3731; it is "squeeze // every last byte from the microcontroller" code. If you're starting out, // download the Adafruit_IS31FL3731 and Adafruit_GFX libraries, which // provide functions for drawing pixels, lines, etc. //-------------------------------------------------------------------------#include// For I2C communication #include // For accelerometer #define #define #define #define #define #define DISP_ADDR 0x74 // Charlieplex FeatherWing I2C address ACCEL_ADDR 0x18 // Accelerometer I2C address N_GRAINS 20 // Number of grains of sand WIDTH 15 // Display width in pixels HEIGHT 7 // Display height in pixels MAX_FPS 45 // Maximum redraw rate, frames/second // The 'sand' grains exist in an integer coordinate space that's 256X // the scale of the pixel grid, allowing them to move and interact at // less than whole-pixel increments. #define MAX_X (WIDTH * 256 - 1) // Maximum X coordinate in grain space #define MAX_Y (HEIGHT * 256 - 1) // Maximum Y coordinate struct Grain { int16_t x, y; // Position int16_t vx, vy; // Velocity } grain[N_GRAINS]; Adafruit_LIS3DH accel = Adafruit_LIS3DH(); uint32_t prevTime = 0; // Used for frames-per-second throttle uint8_t backbuffer = 0, // Index for double-buffered animation img[WIDTH * HEIGHT]; // Internal 'map' of pixels © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 8 of 29 img[WIDTH * HEIGHT]; // Internal 'map' of pixels const uint8_t PROGMEM 0, 90, 75, 60, 45, 0, 0, 0, 0, 0, 91, 76, 61, 46, 14, 29, 44, 59, 0, 92, 77, 62, 47, 13, 28, 43, 58, 0, 93, 78, 63, 48, 12, 27, 42, 57, 0, 94, 79, 64, 49, 11, 26, 41, 56, 0, 95, 80, 65, 50, 10, 25, 40, 55, 0, 96, 81, 66, 51, 9, 24, 39, 54, 0, 97, 82, 67, 52, 8, 23, 38, 53, }; remap[] = { // In order to redraw the screen super 30, 15, 0, // fast, this sketch bypasses the 0, 0, 0, 0, // Adafruit_IS31FL3731 library and 31, 16, 1, // writes to the LED driver directly. 74, 89,104, 0, // But this means we need to do our 32, 17, 2, // own coordinate management, and the 73, 88,103, 0, // layout of pixels on the Charlieplex 33, 18, 3, // Featherwing is strange! This table 72, 87,102, 0, // remaps LED register indices in 34, 19, 4, // sequence to the corresponding pixel 71, 86,101, 0, // indices in the img[] array. 35, 20, 5, 70, 85,100, 0, 36, 21, 6, 69, 84, 99, 0, 37, 22, 7, 68, 83, 98 // IS31FL3731-RELATED FUNCTIONS -------------------------------------------// Begin I2C transmission and write register address (data then follows) uint8_t writeRegister(uint8_t n) { Wire.beginTransmission(DISP_ADDR); Wire.write(n); // No endTransmission() - left open for add'l writes return 2; // Always returns 2; count of I2C address + register byte n } // Select one of eight IS31FL3731 pages, or the Function Registers void pageSelect(uint8_t n) { writeRegister(0xFD); // Command Register Wire.write(n); // Page number (or 0xB = Function Registers) Wire.endTransmission(); } // SETUP - RUNS ONCE AT PROGRAM START -------------------------------------void setup(void) { uint8_t i, j, bytes; if(!accel.begin(ACCEL_ADDR)) { // Init accelerometer. If it fails... pinMode(LED_BUILTIN, OUTPUT); // Using onboard LED for(i=1;;i++) { // Loop forever... digitalWrite(LED_BUILTIN, i & 1); // LED on/off blink to alert user delay(250); // 1/4 second } } accel.setRange(LIS3DH_RANGE_4_G); // Select accelerometer +/- 4G range Wire.setClock(400000); // Run I2C at 400 KHz for faster screen updates // Initialize IS31FL3731 Charlieplex LED driver "manually"... pageSelect(0x0B); // Access the Function Registers writeRegister(0); // Starting from first... for(i=0; i<13; i++) Wire.write(10 == i); // Clear all except Shutdown Wire.endTransmission(); for(j=0; j<2; j++) { // For each page used (0 & 1)... pageSelect(j); // Access the Frame Registers for(bytes=i=0; i<180; i++) { // For each register... © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 9 of 29 for(bytes=i=0; i<180; i++) { // For each register... if(!bytes) bytes = writeRegister(i); // Buf empty? Start xfer @ reg i Wire.write(0xFF * (i < 18)); // 0-17 = enable, 18+ = blink+PWM if(++bytes >= 32) bytes = Wire.endTransmission(); } if(bytes) Wire.endTransmission(); // Write any data left in buffer } memset(img, 0, sizeof(img)); // Clear the img[] array for(i=0; i = 3) ? 1 : 4 - az; ax -= az; ay -= az; int16_t az2 = az * 2 + 1; // // // // // Transform accelerometer axes to grain coordinate space Random motion factor Clip & invert Subtract motion factor from X, Y // Range of random motion to add back in // ...and apply 2D accel vector to grain velocities... int32_t v2; // Velocity squared float v; // Absolute velocity for(int i=0; i 65536) { // If v^2 > 65536, then v > 256 v = sqrt((float)v2); // Velocity vector magnitude grain[i].vx = (int)(256.0*(float)grain[i].vx/v); // Maintain heading grain[i].vy = (int)(256.0*(float)grain[i].vy/v); // Limit magnitude } } // // // // // // // // // // ...then update position of each grain, one at a time, checking for collisions and having them react. This really seems like it shouldn't work, as only one grain is considered at a time while the rest are regarded as stationary. Yet this naive algorithm, taking many nottechnically-quite-correct steps, and repeated quickly enough, visually integrates into something that somewhat resembles physics. (I'd initially tried implementing this as a bunch of concurrent and "realistic" elastic collisions among circular grains, but the calculations and volument of code quickly got out of hand for both the tiny 8-bit AVR microcontroller and my tiny dinosaur brain.) uint8_t i, bytes, oldidx, newidx, delta; int16_t newx, newy; const uint8_t *ptr = remap; for(i=0; i MAX_X) { newx = MAX_X; grain[i].vx /= -2; } else if(newx < 0) { newx = 0; grain[i].vx /= -2; } if(newy > MAX_Y) { newy = MAX_Y; grain[i].vy /= -2; } else if(newy < 0) { newy = 0; grain[i].vy /= -2; } // New position in grain space // If grain would go out of bounds // keep it inside, and // give a slight bounce off the wall oldidx = (grain[i].y/256) * WIDTH + (grain[i].x/256); // Prior pixel # newidx = (newy /256) * WIDTH + (newx /256); // New pixel # if((oldidx != newidx) && // If grain is moving to a new pixel... img[newidx]) { // but if that pixel is already occupied... delta = abs(newidx - oldidx); // What direction when blocked? if(delta == 1) { // 1 pixel left or right) newx = grain[i].x; // Cancel X motion grain[i].vx /= -2; // and bounce X velocity (Y is OK) newidx = oldidx; // No pixel change } else if(delta == WIDTH) { // 1 pixel up or down newy = grain[i].y; // Cancel Y motion grain[i].vy /= -2; // and bounce Y velocity (X is OK) newidx = oldidx; // No pixel change } else { // Diagonal intersection is more tricky... // Try skidding along just one axis of motion if possible (start w/ // faster axis). Because we've already established that diagonal // (both-axis) motion is occurring, moving on either axis alone WILL © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 11 of 29 // (both-axis) motion is occurring, moving on either axis alone WILL // change the pixel index, no need to check that again. if((abs(grain[i].vx) - abs(grain[i].vy)) >= 0) { // X axis is faster newidx = (grain[i].y / 256) * WIDTH + (newx / 256); if(!img[newidx]) { // That pixel's free! Take it! But... newy = grain[i].y; // Cancel Y motion grain[i].vy /= -2; // and bounce Y velocity } else { // X pixel is taken, so try Y... newidx = (newy / 256) * WIDTH + (grain[i].x / 256); if(!img[newidx]) { // Pixel is free, take it, but first... newx = grain[i].x; // Cancel X motion grain[i].vx /= -2; // and bounce X velocity } else { // Both spots are occupied newx = grain[i].x; // Cancel X & Y motion newy = grain[i].y; grain[i].vx /= -2; // Bounce X & Y velocity grain[i].vy /= -2; newidx = oldidx; // Not moving } } } else { // Y axis is faster, start there newidx = (newy / 256) * WIDTH + (grain[i].x / 256); if(!img[newidx]) { // Pixel's free! Take it! But... newx = grain[i].x; // Cancel X motion grain[i].vy /= -2; // and bounce X velocity } else { // Y pixel is taken, so try X... newidx = (grain[i].y / 256) * WIDTH + (newx / 256); if(!img[newidx]) { // Pixel is free, take it, but first... newy = grain[i].y; // Cancel Y motion grain[i].vy /= -2; // and bounce Y velocity } else { // Both spots are occupied newx = grain[i].x; // Cancel X & Y motion newy = grain[i].y; grain[i].vx /= -2; // Bounce X & Y velocity grain[i].vy /= -2; newidx = oldidx; // Not moving } } } } } grain[i].x grain[i].y img[oldidx] img[newidx] = = = = newx; // Update grain position newy; 0; // Clear old spot (might be same as new, that's OK) 255; // Set new spot } // Update pixel data in LED driver pageSelect(backbuffer); // Select background buffer for(i=bytes=0; i = 32) bytes = Wire.endTransmission(); } if(bytes) Wire.endTransmission(); } © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 12 of 29 3D Printing The 3D printed parts are fairly easy to make with most common home desktop 3D printers that are on the market. And if you don’t have access a 3D printer, you can order our parts by visiting our Thingiverse page and have someone local 3D print the parts and ship them to you. Download the Fusion360 files (dome version) https://adafru.it/ArR Download the Fusion 360 files (gimbal version) https://adafru.it/ArS Download from Thingiverse https://adafru.it/ArT Download from Youmagine https://adafru.it/svF Download from Pinshape https://adafru.it/ArU © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 13 of 29 Slice Settings Download the STL file and import it into your 3D printing slicing software. You'll need to adjust your settings accordingly if you're using material different than PLA. 230C Extruder Temp No heated bed (65C for heated) 1.0 Extrusion Multiplier .4mm Nozzle 0.38 Extrusion Width .2mm Layer Height 30% infill No Supports skirt 60mm/s | 120mm travel speed Clean up We used a flush diagonal cutter to clean up any stringing and overhangs around the port openings and around the standoffs inside the enclosure. Make sure the openings for the USB ports are cleaned before mounting components. Use a hobby knife to help cut away stringing that could block components from mounting. © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 14 of 29 Assembly Measure Wires First we'll need to measure wires for each component so its long enough to reach each mount inside the enclosure. The Slide Switch will connect to the Feather board and will need to be 70mm for the GND and 50mm for the EN pin. CharliePlex Featherwing connects the Feather. Connections for SDA and SCL wires will need to be 70mm long. Measure the 3v and GND connections to both be 80mm long. LIS3DH connects to the Feather and will need all four connections to be 40mm long. Assemble Slide Switch A slide switch is used to tie the enable and ground pins so we can turn off the 3 volt regulator, while still enabling you to charge the lipo battery through a USB cable. Use heat shrink to prevent the pins from touching other components when inserted into the enclosure. We used 1x45mm sized heat shrink tubes. You can use the side of the soldering iron to heat up and shrink the tubes around the solder connections. Use a flush diagonal cutter to remove the unused third © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 15 of 29 pin. © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 16 of 29 Wire Boards The LED matrix is free-wired to the Adafruit Feather to make the assembly as slim as possible. We can solder the wires from the bottom side of the boards to make them easy to attach to each other. This also gives room for the battery to fit between the two boards. We used 30AWG silicone coated wires to provide flexibility and durable handling. Solder Slide Switch Next, we'll solder the slide switch to the EN and GND pin on the top of the Feather board. © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 17 of 29 Solder Accelerometer The LIS3DH is soldered in the same way, with the wires underneath the board. We can then solder connections for SDA, SCL, GND and 3V to the top side of the Feather board. Later, will mount it to the top of the Feather board with the help of a 3d printed mount. © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 18 of 29 Accelerometer Mount This 3d printed mount will secure the LIS3DH to the top of the Feather board. We'll use M2x4mm screws to connect the LIS3DH to the 3d printed mount. Next we'll fasten the the 3d printed mount on top of the feather board. We'll use the two mounts close to the prototyping area. Use two M2x8mm screws so they can reach through the Feather and in the 3d printed spacer. © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 19 of 29 Spacer This 3d printed spacer will join the Feather and CharliePlex board together. This will allow a 350mAh lipo battery to safely sit between the two boards, with just enough space to fit the wires from both boards. Attach boards First fasten the two screws on the accelerometer mount. Leave the other two screws unfastened until we fit the battery cable through the opening on the spacer. © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 20 of 29 Bundle wires Next, we'll want to tidy up the wires by bundling them up with a small pieces of kapton tape. This will make it easier to arrange the wires allowing the battery to fit between the boards. © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 21 of 29 Mount Battery Now we can pass the battery wire through the opening on the side of the 3d printed spacer. Reference the picture so the wires wraps around the board with enough space to plug into the Feather board. © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 22 of 29 Attach Spacer Now we can fasten the other two M2x8mm screws through the Feather board. Tighten them in from the top of the Feather, into the spacer. The Feather board should now be firmly attached to the 3d printed spacer. The CharliePlex board will attach after we mount it into the enclosure. © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 23 of 29 Plug in battery First we'll need to plug in the battery before we insert it into the enclosure. Reference the picture to route the wire along the side of the spacer, to the JST PH-2 connector on the Feather board. If the LEDs light up, use the slide switch to turn the circuit off. Mount inside enclosure Align the CharliePlex to the enclosure, making sure the display cutout matches the LED matrix. (We're showing the box enclosure, but all of the design variants mount the same). Tuck wires © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 24 of 29 One side of the enclosure is wider to accommodate the JST connection on the side of the Feather board. Carefully fit the wires inside the enclosure. You can use tweezers to arrange them next to the spacer. Align mounting holes Flip the enclosure to the display cutout. Move the CharliePlex board so it aligns with the mounting holes on the front face of the enclosure. Use four M2x8mm screws on the front face of the enclosure to attach the CharliePlex to the spacer. Face cover To hide the screws on the front of the enclosure, we used a small amount of tac to adhere one of the printed face cover. © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 25 of 29 © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 26 of 29 Slide Switch Tolerances To adjust for different printer tolerances and to ensure the slide switch tightly press fits into the enclosure, we might need to gently spread the two metal sides. This will help the slide switch snap fit into place on the printed part. Slide Switch Mount First, carefully flip the slide the switch into the middle position. This will make it easier to pass through the opening in the enclosure. Now we can insert the slide switch into the mount. Tilt the slide switch at an angle and then press fit into place. Attach Lid The lid press fits onto the enclosure by aligning the nubs on both parts. Insert the protruding nubs on the lid into its matching cavity on the enclosure. Gimbal Assemble To assemble the gimbal version of the enclosure, simply insert the points on the sides, one by one, at an angle. Use by holding the outer ring close, but not over the points that attach them to each other ring. Gently move in an up and down motion to spin the center of the gimbal! © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 27 of 29 Teeter totter The boards are offset so the display can mount to the center of the enclosure. This make it unstable on a dome, making the "grains of sand" bounce in unexpected fun ways. Simply push on the side close to the USB port to randomly spin the enclosure on a flat table. © Adafruit Industries https://learn.adafruit.com/animated-led-sand Page 28 of 29 © Adafruit Industries Last Updated: 2018-02-06 04:55:12 PM UTC Page 29 of 29
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.4 Linearized : No Title : Creator : wkhtmltopdf 0.12.4 Producer : Qt 4.8.7 Create Date : 2018:02:06 16:55:16Z Page Count : 29 Page Mode : UseOutlinesEXIF Metadata provided by EXIF.tools