Latests posts

Navbar and "remaining-full-height" container for SPAs

In the last years I wrote several smaller single-page applications (SPAs), mainly for demos and experiments. The typical layout I want for these SPAs is:

This is what I cam currently using (demo):

Flexbox SPA example

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Awesome SPA</title>
    <style>
/* CSS RESET */
html {
  box-sizing: border-box;
  font-size: 16px;
}

*, *:before, *:after {
  box-sizing: inherit;
}

body, h1, h2, h3, h4, h5, h6, p, ol, ul {
  margin: 0;
  padding: 0;
  font-weight: normal;
}
/* END OF CSS RESET */

/* set explicit height on html => child-elements can use %-based heights*/
html {
  height: 100%;
}

/* "body" is the top-level flex container */
body {
  height: 100%;
  display: flex;  
  flex-direction: column;
}

/* titlebar is flex "child". For complex cases, make this another container */
.titlebar {
  background-color: rgb(37, 37, 37);
  color: white;
  width: 100%;
  height: 4rem;
  line-height: 4rem;  /* vertically centers text */
  padding-left: 4rem;
  font-size: 2rem;
  font-family: Arial, Helvetica, sans-serif;
}

/* main-container is flex child and at the same time another flex-container 
   for vertical+horizontal centering */
.main-container {
  flex: 1;  /* grows main-container to rest of height */
  display: flex;
  background-color: rgb(40, 40, 80);
  align-items: center;
  justify-content: center;

}

.main-container > div {
  font: 2rem Arial;
  width: 100%;
  max-width: 600px;
  height: 4rem;
  line-height: 4rem;
  margin: 20px;
  background-color:#f1f1f1;
  text-align: center;
}
    </style>
  </head>
  <body>
    <div class='titlebar'><b>Titlebar</b>&#8194;...with subtitle</div>
    <div class="main-container">
      <div>centered</div>
    </div>
  </body>
</html>

Matlab: Serial Communication with Pfeiffer MaxiGauge

Connect the MaxGauge to the PC using a simple (3-wire) cross-over serial cable.

The communication protocol (viewed from the PC) is roughly:

--> Mnemonic <CR>
<-- <ACK> <CR> <LF>
--> <ENQ>
<-- Data <CR> <LF>

The mnemonics are described in the user manual (page 85ff). CR (carriage return), ACK (acknowledge), LF (line-feed), ENQ (enquire) are standard ASCII control chararacters.

A simple script for first interactions (almost no error checks!):

maxigauge = serial('COM1');
fopen(maxigauge);

% ASCII control characters
ENQ = int8(5);
LF = int8(10);
CR = int8(13);
ACK = int8(6);
NAK = int8(21);

% Send command: I want to know the part number.
message = [int8('PNR'), CR];
fwrite(maxigauge, message)

% Device the "command received" answer from the device
answer = fscanf(maxigauge);
if all(answer == [ACK CR LF])
    % disp('Command received by MaxiGauge')
else
    error('Command not received correctly by MaxiGauge')
end
% Send the ENQ signal
fwrite(maxigauge, ENQ)

% Receive Answer
answer = fscanf(maxigauge);
disp(answer(1:end-2))

% End communication and cleanup
fclose(maxigauge);
delete(maxigauge)
clear maxigauge

Here is somewhat equivalent code as a Matlab class. I don’t do much OOP, so take it with a grain of salt.

classdef PfeifferMaxiGauge < handleAllHidden
    properties (Hidden, SetAccess = immutable)
        ENQ @ int8 scalar = 5;  % Undocumented @ syntax: value is of type doulbe, a scalar, with initinal value = 0
        LF @ int8 scalar = 10;
        CR @ int8 scalar = 13;
        ACK @ int8 scalar = 6;
        NAK @ int8 scalar = 21;
        com_port @ char vector;
    end
    properties (SetAccess = immutable)
        serial_handle @ serial scalar;
    end
    
    methods (Hidden) % Low-level methods that the user should not (but can) call
        function obj = PfeifferMaxiGauge(com_port) % constructor
            obj.com_port = com_port;
            obj.serial_handle = serial(obj.com_port);
            fopen(obj.serial_handle); 
        end
      
        function delete(obj) % destructor
            fclose(obj.serial_handle);
        end
        
        function write(obj, str)
            % Adds CR to str. 
            % Low-level function. Use send_command(), if appropriate.
            message = [int8(str), obj.CR];
            fwrite(obj.serial_handle, message)
        end
        
        function output = read(obj)
            % Removes CR LF from output
            output = fscanf(obj.serial_handle);
            if output(end-1) ~= obj.CR || output(end) ~= obj.LF
                error('MaxiGauge Read Operation: Unexpected data format - no CR LF at end!')
            end
            output = output(1:end-2);
        end
    end
    
    methods % High-level methods that the user should use.
        function send_command(obj, str)
            obj.write(str)
            ack_msg = obj.read();
            if length(ack_msg) > 1 || ack_msg ~= obj.ACK;
                error(['Command "' str '" not acknowledged by device'])
            end
        end
        
        function output = query(obj, str)
            if nargin > 1
                obj.send_command(str)
            end
            fwrite(obj.serial_handle, obj.ENQ);
            output = obj.read();
        end
        
        function pnr = get_pnr(obj)
            pnr = obj.query('PNR');
        end

    end
end

This class derives from handleAllHidden, which is a trick to hide the standard methods when deriving from the handle class. I only implemented one helper method in my class (get_pnr), the rest will come later, as I need it.


Accessing Windows Registry from Ubuntu

I needed to find the hostname of a PC, but I had its harddrive connected to my Ubuntu box as an external drive. Solution: Browse the registry file of the Windows PC using chntpw

sudo apt-get install chntpw
cd /media/myusername/WINDOWS/Windows/System32/config
chntpw -e SYSTEM

This loads the SYSTEM hive (the file containing everything that's related to HKeyLocalMachine\System). It can take a few seconds to load.

You can use "standard" cmd/bash commands to navigate the registry (use "?" for help). Find the number of the "current control set":

cd Select dir

(Look at "Current" value, usually 1) Go back and navigate to the key that contains the hostname (computer name):

cd ..
cd ControlSet001
cd Control
cd ComputerName
cd ComputerName
cat ComputerName

The cat command prints out the string of the variable ComputerName, which is the host name of the computer.

Use "q" to quit.


Running Startup Code on Mathematica

I wanted to have quicker access to the physics constants that I use most often. Therefore, I edited the init.m file of the Kernel. There are several init.m files - for the Kernel and for the FrontEnd, and in each case for the User, for the system, ...

I chose the init.m of the User&Kernel, because it's in a folder that I back up, and because it's reloaded when I restart the Kernel. In my case, the file path was "C:\Users\myusername\AppData\Roaming\Mathematica\FrontEnd\init.m". You can find the User directory by running $UserBaseDirectory in Mathematica.

I added the following lines to this file:

(** User Mathematica initialization file **)

loadPhysicsShortcuts := (
  me = Quantity[1, "ElectronMass"];
  mp = Quantity[1, "ProtonMass"];
  u = Quantity[1, "AtomicMassUnit"];
  e = Quantity[1, "ElementaryCharge"];
  kB = Quantity [1, "BoltzmannConstant"];
  T = Quantity[1, "Teslas"];
  Hz = Quantity[1, "Hertz" ];
  mHz = Quantity[1, "Millihertz"];
  MHz = Quantity[1, "Megahertz"];
  m = Quantity[1, "Meters"];
  eV = Quantity[1, "Electronvolts"];
  c = Quantity[1, "SpeedOfLight"];
  mm = Quantity[1, "Millimeters"];
  V = Quantity[1, "Volts"];
  s = Quantity[1, "Seconds"];
)

I use setDelayed ( := ) to define the variable (or rather, the expression!) loadPhysicsShortcuts. Since it's defined through setDelayed, the definitions in it are only exececuted when I execute loadPhysicsShortcuts. Thereby my definitions don't pollute my workspace unless I need them.

I guess professionals would package their definitions, but I am not at that level yet. Also, I like how easy it is to call these definitions when I need them.


Keyboard Shortcuts in Matlab 2016a (Windows 7, German)

I extracted the following list from Matlab by clicking the preferences wheel INSIDE the keyboard shortcuts preferences. I replaced German keyboard descriptions with English (Strg -> Ctrl).

It's possible these shortcuts are somehow tied to Locale, i.e. they might be different on a US keyboard. Also, note that these are not all keyboard shortcuts: There are keyboard shortcuts that cannot be customized, see bottom of this page. Most important: Ctrl+0 takes you to the command window (the "console"), and Ctrl+Shift+0 takes you to the editor window.

MATLAB Desktop
Alt+Backspace                    Undo
Alt+Shift+Backspace              Redo
Ctrl+A                           Select All
Ctrl+C                           Copy
Ctrl+F                           Find...
Ctrl+F5                          Pause
Ctrl+F6                          Next Window
Ctrl+H                           Find...
Ctrl+Insert                      Copy
Ctrl+N                           New Script
Ctrl+O                           Open...
Ctrl+P                           Print...
Ctrl+Page down                   Next Tab
Ctrl+Page up                     Previous Tab
Ctrl+Q                           Exit MATLAB
Ctrl+S                           Save
Ctrl+S                           Save Workspace...
Ctrl+Shift+D                     Dock
Ctrl+Shift+F                     Find Files...
Ctrl+Shift+F6                    Previous Window
Ctrl+Shift+M                     Maximize/Restore Docked Window
Ctrl+Shift+Tab                   Previous Tool
Ctrl+Shift+U                     Undock
Ctrl+Shift+Z                     Redo
Ctrl+Tab                         Next Tool
Ctrl+V                           Paste
Ctrl+W                           Close
Ctrl+X                           Cut
Ctrl+Y                           Redo
Ctrl+Z                           Undo
Entf                             Delete
F1                               Product Help
F10                              Step
F11                              Step In
F5                               Run or Continue Execution
Shift+Entf                       Cut
Shift+F1                         Function Browser
Shift+F11                        Step Out
Shift+F5                         Exit Debug Mode
Shift+Insert                     Paste


Command Window
Alt+Backspace                    Undo
Alt+Shift+Backspace              Redo
Backspace                        Delete Previous Character
Ctrl+\                           Clear Selection
Ctrl+A                           Select All
Ctrl+B                           Cursor Backward
Ctrl+C                           Copy
Ctrl+D                           Open Selection
Ctrl+E                           Cursor End Line
Ctrl+End                         Cursor End Document
Ctrl+F                           Find...
Ctrl+F1                          Function Hints
Ctrl+H                           Find...
Ctrl+Insert                      Copy
Ctrl+K                           Kill Line
Ctrl+Left                        Cursor Previous Word
Ctrl+N                           New Script
Ctrl+P                           Print...
Ctrl+Pos 1                       Cursor Begin Document
Ctrl+Return                      Follow Hyperlink
Ctrl+Right                       Cursor Next Word
Ctrl+S                           Save Workspace...
Ctrl+Shift+End                   Selection End Document
Ctrl+Shift+F                     Find Files...
Ctrl+Shift+Left                  Selection Previous Word
Ctrl+Shift+Pos 1                 Selection Begin Document
Ctrl+Shift+R                     Start Incremental Search Backwards
Ctrl+Shift+Right                 Selection Next Word
Ctrl+Shift+S                     Start Incremental Search Forwards
Ctrl+Shift+Z                     Redo
Ctrl+U                           Clear Text at Prompt
Ctrl+V                           Paste
Ctrl+W                           Close
Ctrl+X                           Cut
Ctrl+Y                           Redo
Ctrl+Z                           Undo
Down                             Next History Command
End                              Cursor End Line
Entf                             Delete
ESC                              Clear Text at Prompt
F1                               Help on Selection
F9                               Evaluate Selection
Left                             Cursor Backward
Page down                        Page Down
Page up                          Page Up
Pos 1                            Cursor Begin Line
Return                           Break Line
Right                            Cursor Forward
Shift+Backspace                  Delete Previous Character
Shift+Down                       Selection Down
Shift+End                        Selection End Line
Shift+Entf                       Cut
Shift+F1                         Function Browser
Shift+Insert                     Paste
Shift+Left                       Selection Backward
Shift+Page down                  Selection Page Down
Shift+Page up                    Selection Page Up
Shift+Pos 1                      Selection Begin Line
Shift+Return                     Break Line Without Code Execution
Shift+Right                      Selection Forward
Shift+Up                         Selection Up
Tab                              Tab
Up                               Previous History Command


MATLAB Editor
Alt+Backspace                    Undo
Alt+Down                         Go To Next Underline or Highlight
Alt+Return                       Autofix Message
Alt+Shift+Backspace              Redo
Alt+Up                           Go To Previous Underline or Highlight
Backspace                        Delete Previous Character
Ctrl+.                           Fold Code
Ctrl+[                           Decrease Indent
Ctrl+]                           Increase Indent
Ctrl+=                           Fold All
Ctrl+A                           Select All
Ctrl+Backspace                   Remove Previous Word
Ctrl+C                           Copy
Ctrl+D                           Open Selection
Ctrl+Down                        Next Section
Ctrl+Down                        Scroll Down
Ctrl+End                         Cursor End Document
Ctrl+Entf                        Remove Next Word
Ctrl+F                           Find...
Ctrl+F1                          Function Hints
Ctrl+F2                          Set/Clear Bookmark
Ctrl+F3                          Find Selection
Ctrl+G                           Go To...
Ctrl+H                           Find...
Ctrl+I                           Smart Indent
Ctrl+Insert                      Copy
Ctrl+J                           Wrap Comments
Ctrl+Left                        Cursor Previous Word
Ctrl+M                           Open Message or Expand Details
Ctrl+N                           New Script
Ctrl+NumPad -                    Decrement Value Near Cursor and Evaluate Section
Ctrl+NumPad *                    Multiply Value Near Cursor and Evaluate Section
Ctrl+NumPad /                    Divide Value Near Cursor and Evaluate Section
Ctrl+NumPad +                    Increment Value Near Cursor and Evaluate Section
Ctrl+O                           Open...
Ctrl+P                           Print...
Ctrl+Pos 1                       Cursor Begin Document
Ctrl+Q                           Exit MATLAB
Ctrl+R                           Comment
Ctrl+Return                      Evaluate Current Section
Ctrl+Right                       Cursor Next Word
Ctrl+S                           Save
Ctrl+Shift+.                     Expand Folded Code
Ctrl+Shift+=                     Expand All
Ctrl+Shift+End                   Selection End Document
Ctrl+Shift+F                     Find Files...
Ctrl+Shift+F3                    Find Previous Selection
Ctrl+Shift+H                     Highlight all occurrences of selected variable
Ctrl+Shift+Left                  Selection Previous Word
Ctrl+Shift+NumPad -              Decrease Increment Amount
Ctrl+Shift+NumPad *              Increase Multiplication Factor
Ctrl+Shift+NumPad /              Decrease Multiplication Factor
Ctrl+Shift+NumPad +              Increase Increment Amount
Ctrl+Shift+Pos 1                 Selection Begin Document
Ctrl+Shift+R                     Start Incremental Search Backwards
Ctrl+Shift+Return                Evaluate Current Section and Advance
Ctrl+Shift+Right                 Selection Next Word
Ctrl+Shift+S                     Start Incremental Search Forwards
Ctrl+Shift+Z                     Redo
Ctrl+T                           Uncomment
Ctrl+Up                          Previous Section
Ctrl+Up                          Scroll Up
Ctrl+V                           Paste
Ctrl+W                           Close
Ctrl+X                           Cut
Ctrl+Y                           Redo
Ctrl+Z                           Undo
Down                             Cursor Down
End                              Cursor End Line
Entf                             Delete
ESC                              Clear Selection
F1                               Help on Selection
F12                              Set/Clear Breakpoint
F2                               Next Bookmark
F3                               Find Next
F5                               Run or Continue Execution
F6                               Switch Active File in Split Screen
F9                               Evaluate Selection
Left                             Cursor Backward
Page down                        Page Down
Page up                          Page Up
Pos 1                            Cursor Begin Line
Return                           Break Line
Right                            Cursor Forward
Shift+Backspace                  Delete Previous Character
Shift+Down                       Selection Down
Shift+End                        Selection End Line
Shift+Entf                       Cut
Shift+F1                         Function Browser
Shift+F2                         Previous Bookmark
Shift+F3                         Find Previous
Shift+Insert                     Paste
Shift+Left                       Selection Backward
Shift+Page down                  Selection Page Down
Shift+Page up                    Selection Page Up
Shift+Pos 1                      Selection Begin Line
Shift+Return                     Break Line Without Indenting
Shift+Right                      Selection Forward
Shift+Tab                        Shift Tab
Shift+Up                         Selection Up
Tab                              Tab
Up                               Cursor Up


Coder Editor
Ctrl+F                           Find...
Ctrl+H                           Find...
Ctrl+Shift+F                     Find Files...
F3                               Find Next
Shift+F3                         Find Previous


Command History
Alt+Backspace                    Undo
Ctrl+A                           Select All
Ctrl+C                           Copy
Ctrl+F                           Find...
Ctrl+H                           Find...
Ctrl+Insert                      Copy
Ctrl+P                           Print...
Ctrl+Shift+A                     Match Anywhere
Ctrl+Shift+B                     Match Beginning
Ctrl+Shift+C                     Match Case
Ctrl+Shift+L                     Filter Matches
Ctrl+X                           Cut
Ctrl+Z                           Undo
Entf                             Delete
F9                               Evaluate Selection
Return                           Evaluate Selection
Shift+Entf                       Cut


Current Folder
Backspace                        Up One Level
Ctrl+A                           Select All
Ctrl+C                           Copy
Ctrl+D                           Open Selection
Ctrl+F                           Find Files...
Ctrl+Insert                      Copy
Ctrl+Shift+End                   Selection End Document
Ctrl+Shift+F                     Find Files...
Ctrl+Shift+Pos 1                 Selection Begin Document
Ctrl+V                           Paste
Ctrl+X                           Cut
End                              Cursor End Document
Entf                             Delete
F1                               Help on Selection
F2                               Rename Selection
F5                               Refresh
F9                               Evaluate Selection
Left                             Collapse or Select
NumPad -                         Collapse
NumPad +                         Expand
Pos 1                            Cursor Begin Document
Return                           Extract Archive
Return                           Open Selection
Right                            Expand or Select
Shift+End                        Selection End Document
Shift+Insert                     Paste
Shift+Pos 1                      Selection Begin Document


Deployment Tool
Ctrl+C                           Copy
Ctrl+D                           Open Selection
Ctrl+Insert                      Copy
Ctrl+Shift+End                   Selection End Document
Ctrl+Shift+Pos 1                 Selection Begin Document
Ctrl+V                           Paste
Ctrl+X                           Cut
End                              Cursor End Document
Entf                             Delete
F2                               Rename Selection
F5                               Refresh
Pos 1                            Cursor Begin Document
Return                           Open Selection
Shift+End                        Selection End Document
Shift+Insert                     Paste
Shift+Pos 1                      Selection Begin Document


Find Dialog Box
Ctrl+A                           Select All
Ctrl+C                           Copy
Ctrl+Insert                      Copy
Ctrl+V                           Paste
Ctrl+X                           Cut
F3                               Find Next
Shift+Entf                       Cut
Shift+F3                         Find Previous
Shift+Insert                     Paste


Help and HTML Viewers
Alt+Left                         Back
Alt+Pos 1                        Home
Alt+Right                        Forward
Ctrl+=                           Zoom In
Ctrl+C                           Copy
Ctrl+D                           Open Selection
Ctrl+F                           Find...
Ctrl+H                           Find...
Ctrl+Insert                      Copy
Ctrl+Minus                       Zoom Out
Ctrl+N                           New Browser Window
Ctrl+NumPad -                    Zoom Out
Ctrl+NumPad +                    Zoom In
Ctrl+P                           Print...
Ctrl+Plus                        Zoom In
Ctrl+Shift+=                     Zoom In
Ctrl+T                           New Browser Tab
F1                               Help on Selection
F5                               Refresh
F9                               Evaluate Selection


Help Browser
Ctrl+=                           Collapse All
Ctrl+Shift+=                     Expand All
Ctrl+Shift+T                     Reopen Last Closed Help Browser
ESC                              Clear Search


MATLAB Comparison Tool
Ctrl+Down                        Go To Next Change
Ctrl+N                           Start New Comparison
Ctrl+Up                          Go To Previous Change


Coder App
Ctrl+Shift+Tab                   Go to the previous workflow step
Ctrl+Tab                         Go to the next workflow step


MATLAB Function Block Editor
Ctrl+B                           Simulation Build
Ctrl+D                           Update Diagram
Ctrl+F                           Find...
Ctrl+G                           Go To...
Ctrl+H                           Find...
Ctrl+N                           New Simulink Model
Ctrl+O                           Open...
Ctrl+P                           Print...
Ctrl+Q                           Exit MATLAB
Ctrl+S                           Save
Ctrl+Shift+A                     Update Ports
Ctrl+W                           Close
F10                              Step
F11                              Step In
F12                              Set/Clear Breakpoint
F5                               Run or Continue Execution
F5                               Start Simulation
F9                               Evaluate Selection
Shift+F11                        Step Out
Shift+F5                         Exit Debug Mode
Shift+F5                         Stop Simulation


Workspace Browser
Ctrl+P                           Print...
Ctrl+S                           Save Workspace...
Ctrl+V                           Paste to Workspace...
Shift+Insert                     Paste to Workspace...


Workspace Browser Table
Ctrl+A                           Select All
Ctrl+C                           Copy
Ctrl+D                           Open Selection
Ctrl+Insert                      Copy
Entf                             Delete
F5                               Refresh


Variable Editor
Ctrl+A                           Select All
Ctrl+D                           Open Selection
Ctrl+P                           Print...
Ctrl+S                           Save Workspace...


Variable Editor Table
Alt+Backspace                    Undo
Alt+Shift+Backspace              Redo
Ctrl+A                           Select All
Ctrl+C                           Copy
Ctrl+Insert                      Copy
Ctrl+Minus                       Delete Selected Rows/Columns
Ctrl+Plus                        Insert Rows/Columns
Ctrl+Shift+=                     Insert Rows/Columns
Ctrl+Shift+Leertaste             Select All
Ctrl+Shift+V                     Paste Excel Data
Ctrl+Shift+Z                     Redo
Ctrl+V                           Paste
Ctrl+X                           Cut
Ctrl+Y                           Redo
Ctrl+Z                           Undo
End                              Stop Editing Spreadsheet
Entf                             Delete
Shift+Entf                       Cut
Shift+Insert                     Paste
Shift+Entf                       Cut
Shift+Insert                     Paste

Minimal Working Example in LaTeX

A Minimal Working Example (MWE) for a LaTeX document:

\documentclass{article}
\begin{document} 
Hello World.
\end{document}

I use this template as the basis for my questions on tex.stackexchange.com.

Small rant: Ironically, the most prevalent sites about LaTeX MWEs either don't provide MWEs, or they are so bloated that they only get around to it in Chapter 4...To be fair, the sites I linked to do contain lot's of helpful tricks on how to keep MWEs minimal when the circumstances are more complex (questions about the bibliography, about figures, ...).


Matlab: Asynchronous Program Flow

Matlab scripts and functions are designed to run top-to-bottom, in a synchronous fashion. However, sometimes you need to run a piece of code "a little later", or in the background.

For such occasions, Yair Altman posted a trick on Undocumented Matlab. He uses a timer to call another function asynchronously. Simplifying his example, and using an anonymous function for the callback, this can be written as

timer_cb = @(obj, e, str) disp(str);

disp('first')
t = timer('StartDelay',0.1, 'TimerFcn',{timer_cb, 'second?'});
start(t)
disp('third?')

which outputs

first
third?
second?

Birthday cake

Led Cake
envelope

One of my first memories is my grandfather's 60th birthday. My parents prepared a birthday cake for him, but instead of putting 60 candles on it, they baked a 60 Watt lightbulb into the cake, with lightswitch and everything. As a kid I was fascinated with everything that involved light, and I was heavily impressed by this cake.

So naturally, for my father's 60th birthday I wanted to make a cake with 60 LEDs on it. I bought a 5m RGB LED strip, with 30 LEDs per meter, and each LED addressable individually. The LED type was WS2812B. I bought it from China and payed 40€ for the 5m strip (now they seem to sell for 25€ for 5m, including shipping from Germany!). I also bought cheap Arduino nano clones from China for less than 3€/piece to drive it. I wanted to use battery power for the thing, so I bought a LiPo battery (10€), a USB LiPo charger (2€ ?), a 3.7V -> 5V upconverter (2€ again?), and then realized that I am essentially building a USB power-bank. So I got a cheap (7€) USB power bank from Amazon.

There were a few design iterations on how to get the LEDs on the cake. In the end, I settled for an envelope that goes around the cake. This was easiest to make, and can be "installed" on most cakes within seconds.

Unfortunately, I don't have any pictures of the build process. I bought a 100cm x 50cm sheet of aluminum (I don't recall the thickness) from the local hardware store and used tinner's snips to cut a 100cm x 20cm strip. The cut was suprisingly clean and only needed light sanding to be smooth. I bent the whole thing into a loop, overlapped the ends by a few cm and epoxied them together. I used JB auto-weld for the epoxy, which I had laying around, but most epoxies should do. I attached the LED strips to the outside using double-sided tape. My LED strip was of the IP67 waterproof variety, so it came in some clear plastic-like tubing. I tested a few glues, but most did not stick to the plastic well. Double sided tape worked best.

I wired up the Arduino and hid it in a small plastic project box. The library support for driving WS2812B LED strips is amazing, and I had to only slightly modify one of the examples to get the effect I wanted: A slowly rotating "color wheel" with the occasional (and only *slightly* cheesy) sparkle.

#include "FastLED.h"

FASTLED_USING_NAMESPACE

#define DATA_PIN    13
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    58
CRGB leds[NUM_LEDS];

#define FRAMES_PER_SECOND  120

void setup() {
  delay(1000); 
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  // FastLED.setBrightness(BRIGHTNESS);
}

uint8_t gHue = 0; // rotating "base color" used by many of the patterns
  
void loop()
{
  // Call the current pattern function once, updating the 'leds' array
  double_rainbow();
  addGlitter(2);
  FastLED.show();  
  FastLED.delay(1000/FRAMES_PER_SECOND); 

  // do some periodic updates
  EVERY_N_MILLISECONDS( 100 ) { gHue++; } // slowly cycle the "base color" through the rainbow
}


void double_rainbow() 
{
  // FastLED's built-in rainbow generator, repurposed for DOUBLE RAINBOW ALL THE WAY
  CHSV hsv;
  float fl_hue = (float) gHue;
  hsv.hue = (uint8_t) fl_hue;
  hsv.val = 150;
  hsv.sat = 255;
  for( int i = 0; i < NUM_LEDS/2; i++) {
    leds[i] = hsv;
    leds[i+(NUM_LEDS/2)] = hsv;
    fl_hue += 8.8;
    hsv.hue = (uint8_t) fl_hue;
  }
}

void addGlitter( fract8 chanceOfGlitter) 
{
  if( random8() < chanceOfGlitter) {
    leds[ random16(NUM_LEDS) ] += CRGB::White;
  }
}

Unfortunately, I don't have any pictures of the LED envelope on the actual cake. It looked nice! The only thing I would do differently is to make the cable between the envelope and the controller box a bit longer, so that you can put the controller box under the table, instead of right next to the envelope.