-
1CIRCUIT ASSEMBLY
- Using a solder paste dispenser needle, we apply solder paste to each component pad to begin the circuit assembly process. In this case, we are using 63/37 SnPB Solderpaste.
- After that, we pick each WS2812B LED and place it into their correct position.
- The PCB is then heated from below to the solder paste melting temperature by placing the circuit on the Reflow Hotplate, which causes all of the SMD LEDs to be connected to their pads.
- After reflow, we place the THT components, which consist of female header pin connectors for the Raspberry Pi Pico, and MPU6050 along with a USB type C port.
- Using a soldering iron, we solder the leads of every through-hole component from the bottom side of the board.
- Finally, we position the MPU6050 and Raspberry Pi Pico on the header pins, and the assembly is now complete.
-
2"MPU Control Pixel" Sketch
We start testing this matrix by uploading a sketch we created, which is essentially a pixel control sketch that makes use of the MPU6050. In this sketch, a bright pixel in the center moves in response to the MPU6050's orientation, simulating a particle of sand. For a future hourglass project that senses movement and controls pixel particles that travel around like sand particles, our goal is to refine this sketch further.
#include <Adafruit_NeoPixel.h> #include <Adafruit_GFX.h> #include <Adafruit_NeoMatrix.h> #include <Wire.h> #include <MPU6050_light.h> #define MATRIX_PIN 0 #define MATRIX_WIDTH 10 #define MATRIX_HEIGHT 10 #define NUMPIXELS (MATRIX_WIDTH * MATRIX_HEIGHT) Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_PIN, NEO_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_ROWS, NEO_GRB + NEO_KHZ800); MPU6050 mpu(Wire1); int prevX = MATRIX_WIDTH / 2; int prevY = MATRIX_HEIGHT / 2; void setup() { matrix.begin(); matrix.setBrightness(50); // Initialize I2C1 with pins 26 (SDA) and 27 (SCL) Wire1.setSDA(26); Wire1.setSCL(27); Wire1.begin(); mpu.begin(); mpu.calcOffsets(true, true); // Calculate and apply offsets // Display initialization success matrix.fillScreen(0); matrix.show(); } void loop() { mpu.update(); // Normalize accelerometer values float axNorm = -mpu.getAccX() * 5; // Invert X-axis sensitivity float ayNorm = mpu.getAccY() * 5; // Adjust sensitivity // Clear the previous pixel matrix.drawPixel(prevX, prevY, matrix.Color(0, 0, 0)); // Calculate the new position int centerX = MATRIX_WIDTH / 2; int centerY = MATRIX_HEIGHT / 2; int newX = constrain(centerX + (int)ayNorm, 0, MATRIX_WIDTH - 1); // Horizontal movement int newY = constrain(centerY - (int)axNorm, 0, MATRIX_HEIGHT - 1); // Vertical movement // Update the matrix with the new position matrix.drawPixel(newX, newY, matrix.Color(255, 0, 0)); // Display influenced pixel matrix.show(); // Update the previous position prevX = newX; prevY = newY; delay(20); // Reduce delay for smoother movement }
These are the libraries that you first need to install before using the sketch.
#include <Adafruit_NeoPixel.h> #include <Adafruit_GFX.h> #include <Adafruit_NeoMatrix.h> #include <MPU6050_light.h>
-
3SCROLLING TEXT
The scrolling text animation was the next interesting thing we tried. It was made up of a humorous statement that we put to our sketch and that said the following: "Why don't scientists trust atoms? Because they make up everything!"
Here's the sketch we used.
#include <Adafruit_NeoPixel.h> #include <Adafruit_GFX.h> #include <Adafruit_NeoMatrix.h> #define MATRIX_PIN 0 // GPIO pin connected to the LED matrix data pin #define MATRIX_WIDTH 10 #define MATRIX_HEIGHT 10 Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_PIN, NEO_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_ROWS, NEO_GRB + NEO_KHZ800); int x = 0; // Initialize position void setup() { Serial.begin(115200); Serial.println("Matrix scrolling text display setup..."); matrix.begin(); matrix.setTextWrap(false); matrix.setBrightness(50); matrix.setTextColor(matrix.Color(0, 0, 255)); // White color for text matrix.setTextSize(1); // Ensure text size is appropriate x = matrix.width(); // Start cursor position at the matrix width } void loop() { matrix.fillScreen(0); // Clear screen const char *text = "Why don't scientists trust atoms? Because they make up everything!"; matrix.setCursor(x, 0); matrix.print(text); Serial.print("Cursor X position: "); Serial.println(x); Serial.print("Text to display: "); Serial.println(text); int textWidth = 6 * strlen(text); // Calculate the width of the text if (--x < -textWidth) { x = matrix.width(); Serial.println("Resetting cursor position."); } matrix.show(); delay(110); // Adjust the delay to control the scrolling speed }
You need the following libraries before using this sketch.
#include <Adafruit_NeoPixel.h> #include <Adafruit_GFX.h> #include <Adafruit_NeoMatrix.h>
-
4FIRE
Next, we use one of the FastLED Library's example sketches, Fire, which imitates Flame's color pallet, which is composed of red, orange, and white. This sketch is simple to use if you want to create a digital fire or fireplace project. For more intense animation, you may use a diffuser to spread the LED glow, which will make the setup look more realistic.
#include <FastLED.h> #define LED_PIN 0 #define COLOR_ORDER GRB #define CHIPSET WS2811 #define NUM_LEDS 100 #define BRIGHTNESS 100 #define FRAMES_PER_SECOND 60 bool gReverseDirection = false; CRGB leds[NUM_LEDS]; void setup() { delay(3000); // sanity delay FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip ); FastLED.setBrightness( BRIGHTNESS ); } void loop() { // Add entropy to random number generator; we use a lot of it. // random16_add_entropy( random()); Fire2012(); // run simulation frame FastLED.show(); // display this frame FastLED.delay(1000 / FRAMES_PER_SECOND); } // Fire2012 by Mark Kriegsman, July 2012 // as part of "Five Elements" shown here: //// // This basic one-dimensional 'fire' simulation works roughly as follows: // There's a underlying array of 'heat' cells, that model the temperature // at each point along the line. Every cycle through the simulation, // four steps are performed: // 1) All cells cool down a little bit, losing heat to the air // 2) The heat from each cell drifts 'up' and diffuses a little // 3) Sometimes randomly new 'sparks' of heat are added at the bottom // 4) The heat from each cell is rendered as a color into the leds array // The heat-to-color mapping uses a black-body radiation approximation. // // Temperature is in arbitrary units from 0 (cold black) to 255 (white hot). // // This simulation scales it self a bit depending on NUM_LEDS; it should look // "OK" on anywhere from 20 to 100 LEDs without too much tweaking. // // I recommend running this simulation at anywhere from 30-100 frames per second, // meaning an interframe delay of about 10-35 milliseconds. // // Looks best on a high-density LED setup (60+ pixels/meter). // // // There are two main parameters you can play with to control the look and // feel of your fire: COOLING (used in step 1 above), and SPARKING (used // in step 3 above). // // COOLING: How much does the air cool as it rises? // Less cooling = taller flames. More cooling = shorter flames. // Default 50, suggested range 20-100 #define COOLING 55 // SPARKING: What chance (out of 255) is there that a new spark will be lit? // Higher chance = more roaring fire. Lower chance = more flickery fire. // Default 120, suggested range 50-200. #define SPARKING 120 void Fire2012() { // Array of temperature readings at each simulation cell static uint8_t heat[NUM_LEDS]; // Step 1. Cool down every cell a little for( int i = 0; i < NUM_LEDS; i++) { heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / NUM_LEDS) + 2)); } // Step 2. Heat from each cell drifts 'up' and diffuses a little for( int k= NUM_LEDS - 1; k >= 2; k--) { heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3; } // Step 3. Randomly ignite new 'sparks' of heat near the bottom if( random8() < SPARKING ) { int y = random8(7); heat[y] = qadd8( heat[y], random8(160,255) ); } // Step 4. Map from heat cells to LED colors for( int j = 0; j < NUM_LEDS; j++) { CRGB color = HeatColor( heat[j]); int pixelnumber; if( gReverseDirection ) { pixelnumber = (NUM_LEDS-1) - j; } else { pixelnumber = j; } leds[pixelnumber] = color; } }
-
5CONCLUSION
Overall, this project was a success and required no further revision.
Making a matrix test board that can be used to explore with WS2812B to run various demo sketches and create our own—the sand particle sketch we are working on right now—was the aim of our project. We will be sharing a future project soon that includes an hourglass demo sketch.
This is it for today, folks. All the documents related to this project are attached, which you can checkout in this article. If you need any additional information, feel free to leave a comment, and I will be happy to assist you.
Special thanks to HQ NextPCB for providing components that I've used in this project; check them out for getting all sorts of PCB or PCBA-related services for less cost.
Thanks for reaching this far, and I will be back with a new project soon.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.