Featured image of post Neopixel Drinks Coaster

Neopixel Drinks Coaster

Building an unnecessarily complex Neopixel based Drinks coaster

This little project involved building something unnecessarily complex when there are many much cheaper options that would have done the job just fine. The reason for this was that my girlfriend likes the light up gin bottles from Marks and Spencer’s, and I though there could be a better way to create my own, and if your going to have a Light up bottle, it is always going to be improved by having programable RGB LED’s.

The design was to be simple, a drinks coaster made from a 10cm square PCB, which could be powered by one of the many USB-C chargers that we have round the house, with a number of RGB LED’s on the top, which could light up any bottle or glass when placed on top of it. To detect when a drink was placed on, I planned on using small switches on each corner, that a micro-controller on board, could then be triggered by to set the RGB colors of.

kiCad Schematic for Rp2040 Coaster

The design is a simple one that uses the parts I had readily available, given the on-going parts shortage, as a result the microcontroller is a RP2040, which seems massively overpowered but I have many at home and you have to use what is avalible today, but who needs a Duel Core processor to just drive a couple of LED’s? The LED’s are essentially Neopixels, the WS2812B LEDs, which I had a reel I purchased earlier in the year from Aliexpress, when I was building some little displays I used with the Thermal Sensor. Much of the rest of the design is based on the RP2040 Reference design, so was quick to pull together using KiCad, and before you know it the PCB is off to be manufactured.

Render of the Rp2040 Coaster PCB

With the PCB order, the next job was to add some sort of case or cover for the board, and protect it from the contents of the bottle which wuld be placed on top. For this I used OpenSCAD to produce a tight fitting cover which could be 3D printed. The Case makes use of a few simple shapes, producing a square with the shape of the PCB cut away, and by matching the dimensions closely I’m able to get a case the pushes onto the board.


difference(){
    difference() {
        translate([0,0,-0])
            cube([95,95,7],true);
        {translate([0,0,0])
            cube([86,90,2.5],true);
        translate([0,0,2.5])
            cube([91,91,3.1],true);};
    }
    {translate([41.5,-6.61,-1.5])
        cube([13,10,3.2],true);

     translate([47.5,-6.61,-0.9])
        cube([3,10,3.2],true);

     translate([46.5,-6.61,0.9])
        cube([3,12,8],true);

     translate([43,-6.61,0.25])
        cube([5,30,3],true);
    }  
}

OpenSCAD is great when you just want to assemble a few simple shapes pragmatically, but I found it difficult to use in this context building a more complex piece with elements that need to fit together. I might look at trying something like FreeCAD next time, as it might be better suited to my needs especially as the PCB can be easily imported into freecad to see how the shapes interact. Even with these issues, having a 3D printer at home means that even an error such as this can be quickly corrected and solved, although it seems wasteful taking 4 attempts to get a part to fit together well.

PCB with problems

The first revision of the PCB, was a bit of a fail, as after making a few late changes to the PCB, a power rail was added that went though the ground plane on the back of the PCB. I was able to bodge this, with a bit of thin wire and some careful cutting with a scalpel, to test the design, before making some quick corrections and then getting a fresh PCB made up. One advantage of this was it let me work on a case, and getting it to fit with the board I had made up which would have the same dimensions as the final board.

Asseembled PCB with the 3D printed cover

The code for controlling the board is just based on the examples provided with the Pico Board, which provides the functionality to send a stream of RGB values, to the interface and select the LED to be turned on. The decision on if to turn the coaster on is based on the number of the switches that are not high, the Pin Numbers for the switches are stored in BUTTON_PINS, and the first loop checks if they are high or low, the color that is then set is driven by the counter my_test

for(int level = 0; level<180; level++ ){

  int my_test = 0;
  for (int i = 0; i < (4); ++i) {
    if(gpio_get(BUTTON_PINS[i])!=1){
	     my_test++;
		}
	}

	//Set the center LED's
	if(my_test>2){
	   if (level < 90) {
		     setcenter(RGB_LOOKUP[level][0], RGB_LOOKUP[level][1], RGB_LOOKUP[level][2]);
		}
		else {
	     int pos = 179 - level;
			 setcenter(RGB_LOOKUP[pos][0], RGB_LOOKUP[pos][1], RGB_LOOKUP[pos][2]);
		}
	}
	else{
	set_colour(49,2,0,0);
	}
}

In the case where at least 3 of the buttons have triggered, the color is set from an array of values in RGB_LOOKUP, this contains the 180 RGB values that create the smooth color transitions, with the next value in the lookup table being selected after each loop, before resetting once all values have been used.

The completed RP2040 powered coaster

With the code completed, the PCB and case assembled we can bring it all together, and see what we have. I’m happy with the results, and the code, PCB and case can all be found on Github if you want to have a look. gihub.com/jjhorton/

The changing colors work well on the textured glass of this bottle very well, the next task is to work out how I could make it battery powered…

Built with Hugo
Theme Stack designed by Jimmy