This gadget, which resembles a BOX, contains the lighting element, which is an XIAO RGB matrix connected to an XIAO SAMD21 microcontroller board. We have added a battery board PCB to the device's backside. It has an IP5306 Power Management IC, that raises a Li-ion cell's 3.7V to a steady 5V 2A, which powers the RGB LEDs and XIAO.

DESIGN

The design process began with Fusion360.

Here, we modeled the PCB that is positioned on the front and the identical layout that is positioned on the back; the only distinction is that the rear PCB has a lithium cell holder in addition to certain SMD and THT components, such as an LED, USB port, indicator, and IC.

After that, the two PCBs are joined with the help of a rectangular box-shaped part, in the center of which is the XIAO RGB MATRIX and SAMD21 microcontroller.

The idea here was that we have placed the XIAO RGB MATRIX in the topmost region of the design. We will be adding a solder mask opening in the PCB, which will allow the RGB light to see through only in the topmost region.

The Design was finalized and then 3D printed using white PLA with 0.4mm Nozzle and 0.2mm Layer height, infill 10%.

PCB DESIGN: THE ART LAYER



Finding an appropriate Great Wave off Kanagawa image was the first step in the PCB design process. We then imported the image into Inkscape and put a circular sun on top of the wave along a few lines that extended in all directions, representing sunrays.

Next, the entire drawing is crammed within a rectangular frame.

The dimensions extracted from the Fusion360 model were used to create the board's outline and include two mounting holes.

Here, we want to put etch where all of the black lines are, then open the etch to turn all of the black borders on the PCB into silver.

Additionally, we remove the solder mask from the top section between the sun's rays and the bottom section's solder mask to let light through the top portion of the board.

Since there are no electronic components on this board, we created the design in PCB Cad without the need for a schematic and exported the Gerber data after the design was complete.

PCB DESIGN: BATTERY BOARD

The battery board, which consists of an IP5306 Minimal configuration with a few capacitors on both the input and output sides as well as a few resistors and an inductor, was then set up.

The XIAO SAMD21 and the RGB Matrix, in our case, are powered by the IP5306, a power management integrated circuit (IC) that is used in commercial power banks. It increases the 3.7V lithium cell's output to a steady 5V 2A, which may be utilized to power numerous 5V operated devices.

Along with these characteristics, it also has a battery fuel indicator light and low and high cut functions.

Regarding the board design, we used the CAD file's board shape to arrange all of the SMD components on the top side of the board and the bottom side of the board to allow for THT components such as the USB port, push button, LED, and lithium cell holder.

XIAO SAMD21 M0 and XIAO RGB 6x10 Matrix

For this project, we're using the XIAO SAMD21 M0 Development Board paired with the XIAO RGB LED 6x10 matrix, which are both made by Seeed Studio.

The Seeed Studio XIAO SAMD21 is a compact and powerful development board featuring the ATSAMD21G18A-MU microcontroller, which is based on the ARM Cortex-M0+ architecture. This board is designed for low-power applications and is compatible with the Arduino IDE.

https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html

We are using the XIAO RGB Matrix, which consists of 60 WS2812 LEDs arranged in a 6x10 grid, in addition to the XIAO SAMD21. This board is designed in a way that allows it to be directly linked to and controlled by any XIAO microcontroller. The user can easily link the board to any different setup thanks to the input and output connections provided on the bottom side of the board.

https://www.seeedstudio.com/6x10-RGB-MATRIX-for-XIAO-p-5771.html#

Seeed Fusion PCB Service

After finalizing both PCBs, we exported their Gerber data and sent them to Seeed Studio Fusion for samples.

Two orders were placed, one for the art layer and one for the back board; the art layer PCB was ordered in blue Solder mask, and the battery board was ordered in black Soldermask.

PCBs were received in a week, and their quality was super good considering the rate, which was also pretty low.

Seeed Fusion PCB Service offers one-stop prototyping for PCB manufacture and PCB assembly, and as a result, they produce superior-quality PCBs and fast turnkey PCBAs within 7 working days.

Seeed Studio Fusion PCB Assembly Service takes care of the entire fabrication process, from Seeed Studio Fusion Agile manufacturing and hardware customization to parts sourcing, assembly, and testing services, so you can be sure that they are getting a quality product.

After gauging market interest and verifying a working prototype, Seeed Propagate Service can help you bring the product to market with professional guidance and a strong network of connections.

Next is the PCB assembly process.

PCB ASSEMBLY

POWER SOURCE

We are using an 18650 3.7V 1800mAh Li-ion cell as our power supply, and it is attached to the PCB's backside lithium cell holder.

We used an multimeter to measure the board's output voltage after putting in the cell, and the result was 5.1V, confirming that the circuit is functioning.

BODY ASSEMBLY

After the XIAO SAMD21 DEV board and RGB matrix were installed, let us take a closer look at the wiring procedure.

WIRING PROCESS

The wiring of the setup was straightforward: we connected the XIAO's 5V to the LED Matrix 5V, GND to GND, and D0 to the RGB Matrix's input.

To power both XIAO SAMD21 and RGB Matrix, we added the 5V output from the battery board with 5V and GND terminals as well.

FINAL ASSEMBLY

PCB Desk Light is now complete. Let's have a look at the code.

CODE

This was the sketch used in this project, and its based around the FastLED Library, which you need to download and install first before compiling the sketch.

https://github.com/FastLED/FastLED

#include <FastLED.h>
#define LED_PIN 0
#define COLOR_ORDER GRB
#define CHIPSET     WS2811
#define BRIGHTNESS 64
// Helper functions for an two-dimensional XY matrix of pixels.
// Simple 2-D demo code is included as well.
//
//     XY(x,y) takes x and y coordinates and returns an LED index number,
//             for use like this:  leds[ XY(x,y) ] == CRGB::Red;
//             No error checking is performed on the ranges of x and y.
//
//     XYsafe(x,y) takes x and y coordinates and returns an LED index number,
//             for use like this:  leds[ XYsafe(x,y) ] == CRGB::Red;
//             Error checking IS performed on the ranges of x and y, and an
//             index of "-1" is returned.  Special instructions below
//             explain how to use this without having to do your own error
//             checking every time you use this function.
//             This is a slightly more advanced technique, and
//             it REQUIRES SPECIAL ADDITIONAL setup, described below.
// Params for width and height
const uint8_t kMatrixWidth = 6;
const uint8_t kMatrixHeight = 10;
// Param for different pixel layouts
const bool    kMatrixSerpentineLayout = true;
const bool    kMatrixVertical = false;
// Set 'kMatrixSerpentineLayout' to false if your pixels are
// laid out all running the same way, like this:
//
//     0 >  1 >  2 >  3 >  4
//                         |
//     .----<----<----<----'
//     |
//     5 >  6 >  7 >  8 >  9
//                         |
//     .----<----<----<----'
//     |
//    10 > 11 > 12 > 13 > 14
//                         |
//     .----<----<----<----'
//     |
//    15 > 16 > 17 > 18 > 19
//
// Set 'kMatrixSerpentineLayout' to true if your pixels are
// laid out back-and-forth, like this:
//
//     0 >  1 >  2 >  3 >  4
//                         |
//                         |
//     9 <  8 <  7 <  6 <  5
//     |
//     |
//    10 > 11 > 12 > 13 > 14
//                        |
//                        |
//    19 < 18 < 17 < 16 < 15
//
// Bonus vocabulary word: anything that goes one way
// in one row, and then backwards in the next row, and so on
// is call "boustrophedon", meaning "as the ox plows."
// This function will return the right 'led index number' for
// a given set of X and Y coordinates on your matrix.
// IT DOES NOT CHECK THE COORDINATE BOUNDARIES.
// That's up to you.  Don't pass it bogus values.
//
// Use the "XY" function like this:
//
//    for( uint8_t x = 0; x < kMatrixWidth; x++) {
//      for( uint8_t y = 0; y < kMatrixHeight; y++) {
//
//        // Here's the x, y to 'led index' in action:
//        leds[ XY( x, y) ] = CHSV( random8(), 255, 255);
//
//      }
//    }
//
//
uint16_t XY( uint8_t x, uint8_t y)
{
uint16_t i;
if( kMatrixSerpentineLayout == false) {
if (kMatrixVertical == false) {
i = (y * kMatrixWidth) + x;
} else {
i = kMatrixHeight * (kMatrixWidth - (x+1))+y;
}
}
if( kMatrixSerpentineLayout == true) {
if (kMatrixVertical == false) {
if( y & 0x01) {
// Odd rows run backwards
uint8_t reverseX = (kMatrixWidth - 1) - x;
i = (y * kMatrixWidth) + reverseX;
} else {
// Even rows run forwards
i = (y * kMatrixWidth) + x;
}
} else { // vertical positioning
if ( x & 0x01) {
i = kMatrixHeight * (kMatrixWidth - (x+1))+y;
} else {
i = kMatrixHeight * (kMatrixWidth - x) - (y+1);
}
}
}
return i;
}
// Once you've gotten the basics working (AND NOT UNTIL THEN!)
// here's a helpful technique that can be tricky to set up, but
// then helps you avoid the needs for sprinkling array-bound-checking
// throughout your code.
//
// It requires a careful attention to get it set up correctly, but
// can potentially make your code smaller and faster.
//
// Suppose you have an 8 x 5 matrix of 40 LEDs.  Normally, you'd
// delcare your leds array like this:
//    CRGB leds[40];
// But instead of that, declare an LED buffer with one extra pixel in
// it, "leds_plus_safety_pixel".  Then declare "leds" as a pointer to
// that array, but starting with the 2nd element (id=1) of that array:
//    CRGB leds_with_safety_pixel[41];
//    CRGB* const leds( leds_plus_safety_pixel + 1);
// Then you use the "leds" array as you normally would.
// Now "leds[0..N]" are aliases for "leds_plus_safety_pixel[1..(N+1)]",
// AND leds[-1] is now a legitimate and safe alias for leds_plus_safety_pixel[0].
// leds_plus_safety_pixel[0] aka leds[-1] is now your "safety pixel".
//
// Now instead of using the XY function above, use the one below, "XYsafe".
//
// If the X and Y values are 'in bounds', this function will return an index
// into the visible led array, same as "XY" does.
// HOWEVER -- and this is the trick -- if the X or Y values
// are out of bounds, this function will return an index of -1.
// And since leds[-1] is actually just an alias for leds_plus_safety_pixel[0],
// it's a totally safe and legal place to access.  And since the 'safety pixel'
// falls 'outside' the visible part of the LED array, anything you write
// there is hidden from view automatically.
// Thus, this line of code is totally safe, regardless of the actual size of
// your matrix:
//    leds[ XYsafe( random8(), random8() ) ] = CHSV( random8(), 255, 255);
//
// The only catch here is that while this makes it safe to read from and
// write to 'any pixel', there's really only ONE 'safety pixel'.  No matter
// what out-of-bounds coordinates you write to, you'll really be writing to
// that one safety pixel.  And if you try to READ from the safety pixel,
// you'll read whatever was written there last, reglardless of what coordinates
// were supplied.
#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
CRGB leds_plus_safety_pixel[ NUM_LEDS + 1];
CRGB* const leds( leds_plus_safety_pixel + 1);
uint16_t XYsafe( uint8_t x, uint8_t y)
{
if( x >= kMatrixWidth) return -1;
if( y >= kMatrixHeight) return -1;
return XY(x,y);
}
// Demo that USES "XY" follows code below
void loop()
{
uint32_t ms = millis();
int32_t yHueDelta32 = ((int32_t)cos16( ms * (27/1) ) * (350 / kMatrixWidth));
int32_t xHueDelta32 = ((int32_t)cos16( ms * (39/1) ) * (310 / kMatrixHeight));
DrawOneFrame( ms / 65536, yHueDelta32 / 32768, xHueDelta32 / 32768);
if( ms < 5000 ) {
FastLED.setBrightness( scale8( BRIGHTNESS, (ms * 256) / 5000));
} else {
FastLED.setBrightness(BRIGHTNESS);
}
FastLED.show();
}
void DrawOneFrame( uint8_t startHue8, int8_t yHueDelta8, int8_t xHueDelta8)
{
uint8_t lineStartHue = startHue8;
for( uint8_t y = 0; y < kMatrixHeight; y++) {
lineStartHue += yHueDelta8;
uint8_t pixelHue = lineStartHue;
for( uint8_t x = 0; x < kMatrixWidth; x++) {
pixelHue += xHueDelta8;
leds[ XY(x, y)]  = CHSV( pixelHue, 255, 255);
}
}
}
void setup() {
FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
FastLED.setBrightness( BRIGHTNESS );
}

RESULT

This is the finished project, an ARTISTIC PCB DESK LIGHT inspired by the "Great Wave off Kanagawa." By pressing the push button located on the left side of the device, the device turns ON.

The RGB Glow is visible on the front side of the PCB, where we have opened the solder mask to allow light to pass through, and the RGB matrix illuminates the interior of the desk light.

We positioned this desk light next to our monitor, and it looks amazing and enhances the aesthetics of the desk setup.

This project serves as a demonstration of how we can use electronics to create art. We may alter the PCB to make it appear less like a conventional PCB and more like an artwork by adding unique artwork, such as vectors or patterns like I added in this project.

Overall, this project was completed and requires no further revision.

Leave a comment if you need any help regarding this project. This is it for today, folks.

Thanks to Seeed Studio Fusion for supporting this project.

You guys can check them out if you need great PCB and stencil service for less cost and great quality.

And I'll be back with a new project pretty soon!