Open Arduino

Enter Your Project for a chance to win a grand prize for the most innovative use of Arduino or a $200 shopping cart! The Birthday Special: Arduino Projects for Arduino Day!

Back to The Project14 homepage

Project14 Home
Monthly Themes
Monthly Theme Poll


This project was a derivation of my Illuminated Beer Tap Beer Tap



The basis for this article came from a visit to a night market where one of the vendors was selling small edge lit signs.

While these aren’t new, the ones he showed could change colour with a touch of your finger.


Edge Lighting is based on sending light into the edge of Glass or Acrylic where it bounces around until it escapes.

You may have viewed the EXIT signs which hang from the roof and are 6-8mm thick.


Some restaurants and shops have a plain edge lit panel which they write specials or other enticing offers in bold colours.

I built a similar device when LED’s were still in their early days and not as bright as they are now.

Colour changing options were limited in those days but have become very cheap and readily available.


So having the catalyst for making something, it became an exercise in how.




The idea is to introduce light into the panel, but the size meant a high density was required

I also wanted to adjust the colour and brightness, which meant NeoPixels become the obvious choice.


If you recall your schooling days, light travels in straight lines, so when you have light entering at the bottom, enviably it will continue to the top where it tries to escape.

The top transition will reflect and scatter the light, which cause the brightness at the edge that you sometimes see on LCD's and will see in these signs.


The brighness of LED's changes depending on the colour as three seperate parts mix to produce the colour, so having the ability to adjust it is important.



My signs were going to be 100 mm or so, and to get the maximum LED density I used the neopixel strip.

These were soldered together to form a 16 LED strip.




The illuminated panel slots into a base which hides all the workings.

Once you've decided on the LED's and sign size, you can start making it.


Woodwork isn't my best/favourite material so there was some trepidation ....  how many ways I could muck this up, and at what step would it go pear shaped.

I had a router and not much experience (read none) using it, so the first thing to try was a slot for the panel.

I found the masking tape helped to see the pencil marks, and it gave a very clear start and stop point.




The neopixel is slightly offest, so the slot to house these is not centered.



The controller was always going to be a Digispark (or clone) so space for that was made.


I left enough room for the wires and the USB plug which will power it.

The base was cut to size and then sanded to tidy it up and make it ready for a coating.




Having decided on the panel size, you need to cut it to size.

I've found that it's best to use a thin woodwork blade in a variable speed jigsaw and set it to the slowest you can when cutting acrylic.

Take it slowly to stop the heat build-up which will cause the blade to grab, which usually causes a break or cracking (as I did on one panel )


Once it's cut you can sand the edges and finish with 2000 grit paper or finer.

I also polished the edge that will sit on the LED's using some car polish and a buffer in a drill.


Whatever you do make sure you protect the front and rear sides from scratches as they will be visible when lit.

I use masking tape to stop the jigsaw from scratching the panel.





I decided on a Xmas theme and tried a couple of different methods and patterns.



A Dremel 3000 was used with mixed results. This was due to my acrylic being very soft and was constantly blocking the tip, making it a etch - stop - clear tip - etch - stop ... affair.

The project has made me look seriously at a CNC machine, and I'm sure the quality would be great (well I've convinced myself it will be)


With the design taped to the rear, everything is white, making depth perception difficult, you also get a parallax errors, so in the end I found transferring the pattern onto the front panel was better.

You really need to be careful how much material you are removing as it will illuminate more/less depending on the depth.



I did see a method where they provided edge illumination, but I found that I needed to turn the panel as I etched which meant the illumination would be difficult.


I tried using the stand arrangement they provide with the Dremel kit.

It certainly made the depth variance go away and allowed you to use both hands to control the movement.


I did make use of the Hot Air Rework with the smallest tip to heat the rough etched piece.

It did clean up very well, however you do need to be careful as it will cause the acrylic to bubble.



Because the light bounces off any break in the surface, sandblasting the surface should work.

I found some cake decorating patterns at a large retailer and they are a piece of mylar like plastic material.


Controlling how much blasting and the distance to obtain an even pattern is one problem, plus once you start blasting in a small cabinet, visibility becomes very limited.

Another issue is the mask lifting and grit getting underneath.


The mask was taped onto the panel and a couple of blasts at right angles to the panel was enough.

The mask held up very well, but there was some creepage underneath.


As the photo shows the edge is not as sharp as it could be and there are marks out from the edge that the photo doesn't show very well

For something more critical, a thin aluminum mask would be perfect.




Like the Illuminated Beer Tap you should be able to adjust the brightness and colour, and have it stored for the next power cycle.

I hadn't found a way of doing the finger detection thing, and my attempt to detect vibration with a spring vibration sensor proved frustrating.

Stolen from


I resorted back to the magnet and hidden Hall Effect switch.


It will ramp up and when it reaches the maximum (255) it drops to a lower value for 1 sec then back to full bright for 1 sec.

This gives you time to remove the magnet before it starts ramping down.


The colour cycle starts from green, and slowly cycles, so leaving the magnet in place means a continually changing colour sign.

These show the variation of the etching process. Obviously straight lines will not etch well so a varying pattern is more suitable.


Note the scratch which happened during the process, buffing it out can be done but avoiding the problem is the best and easiest method.

These show the sandblasted version and are suitable for dense areas or logos, etc.

They certainly don't pop as well as the etched versions, but the marks and scratches do reduce the contrast, so there is room for improvement.

A combination of both sandblasting and etching might yeld some really interesting effects.


Both of these were done to trial the techniques and demonstrate the effects, so the acrylic panel had a few "war wounds" before I started.

However I did crack one and chip the corner on the other.



This picture give a view of the leakage from the opposite end of the LEDs. (It is quite bright)

Painting the edges white and then adding black over the top will help bounce light back into the panel and stop the leakage outwards.

I didn't bother addressing the leakage at the base, but should be easy to resolve.





You could power this from a battery and use Wireless Charging if your base is large enough.

I decided on fitting a usb cable and plugging it in for this version.





      Controller that allows colour and brightness to be adjusted for 
      an Edge Lit sign using a Digispark, Hall Effect switches and NeoPixel display
      Mark Beckett 
    Pin connections
  Digi  tiny85
  P0     (5)= 
  P1     (6)= On board LED (Rev A)
  P2     (7)= NeoPixel
  P3     (2)= Hall Effect (Colour change)
  P4     (3)= Hall Effect (Brightness change)
  P5     (1)= 
   Created 14 Aug 2017
   by Mark Beckett
   0.1  Initial Code  started 14 Aug 2017
     To Do :
  #include <adafruit_neopixel.h><adafruit_neopixel.h>
  #define PIN 2                    //neopixel connected to P2
  #define NUM_LEDS 16              // How many leds in your strip? 
  // Inputs 
  const byte ButtonColour = 3;
  const byte ButtonBright = 4; 
  // General
  long LastButtonCheck = 0;  
  int ChangeTime = 25;
  int Brightness = 5;        //setting for the Brightness
  int Colour = 0;            //setting for colour
  // State Flags  
  boolean setColour =0;          // used to decide if colour change is happening
  boolean SetBright =0;       // used to decide if set Brightness is happening 
  boolean ButtonStateColour = 0;    // boolean to store last change
  boolean ButtonStateBright =0;     // boolean to store last change 
  byte ButtonCountColour = 0;
  byte ButtonCountBright = 0; 
  // Parameter 1 = number of pixels in strip  
  // Parameter 2 = Arduino pin number (most are valid)  
  // Parameter 3 = pixel type flags, add together as needed:  
  //   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)  
  //   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)  
  //   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)  
  //   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)  
  Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);  
  // IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across  
  // pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input  
  // and minimize distance between Arduino and first pixel.  Avoid connecting  
  // on a live circuit...if you must, connect GND first.  
  void setup() {  
    strip.begin();;                       // Initialize all pixels to 'off' 
    Brightness = (;      //read the value set.
    Colour = (;          //read the value set.
    pinMode (ButtonColour, INPUT);  
    digitalWrite (ButtonColour, HIGH);        // internal pull-up
    pinMode (ButtonBright, INPUT);  
    digitalWrite (ButtonBright, HIGH);        // internal pull-up  
    for (int i=0; i<strip.numpixels(); i++)=""  ="" <br="">    {  
      strip.setPixelColor(i, Wheel((Colour) & 255));;  
  void loop() {  
    if (setColour == 1)  
      rainbow(75);          // Calls the Rainbow routine with a 75mS delay
      // stay doing nothing  
    if (SetBright == 1)  
      BrightAdj(30);          // Calls the Rainbow routine with a 30mS delay
      // stay doing nothing  
void Check_Buttons()  
  /* This routine checks the timer (LastButtonCheck) and if necessary reads the button input 
     If the button is detected, it waits unitl it counts it 10 times at the set time rate. 
     This prevents button bounce from triggering and ensures the button is pressed. 
     Once a valid button press has been detected, it starts a timer (ButtonPressTime), 
      if (millis() - LastButtonCheck > 5)                    // Reads button state every 5mS and then updates button counts  
        ButtonStateColour = digitalRead(ButtonColour);
        ButtonStateBright = digitalRead(ButtonBright);   
        LastButtonCheck = millis();  
        if (ButtonStateColour == LOW)  
          ButtonCountColour ++;                                     // Increment the Count by 1  
          if (ButtonCountColour > 5)                               // the button should be LOW for 5x5mS = 25mS  
            // Button has been pressed for longer than 25mS so its valid  
             ButtonCountColour = 0;  
            setColour =1;                                      // Do something with the valid button press  
        else                                                  // Button is HIGH  
          ButtonCountColour =0;                                     // Reset the counter as the button has been released  
          setColour =0;  
        if (ButtonStateBright == LOW)  
          ButtonCountBright ++;                                     // Increment the Count by 1  
          if (ButtonCountBright > 5)                               // the button should be LOW for 5x5mS = 25mS  
            // Button has been pressed for longer than 25mS so its valid  
            ButtonCountBright = 0;  
            SetBright =1;                                      // Do something with the valid button press
        else                                                  // Button is HIGH  
          ButtonCountBright =0;                                     // Reset the counter as the button has been released  
          SetBright =0;
  // The user wishes to change colour  
void rainbow(uint8_t wait) {  
  byte i, j; 
  for(j=0; j<256; j++) {  
    for(i=0; i<strip.numpixels(); i++)=""  ="" <br="">    {  
      strip.setPixelColor(i, Wheel((j) & 255));  
      if (setColour == 0)  
        EEPROM.write(2, j);              // Write it to EEPROM 
        break;      //get out  
uint32_t Wheel(byte WheelPos) {  
  if(WheelPos < 85) {  
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);  
  } else if(WheelPos < 170) {  
   WheelPos -= 85;  
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);  
  } else {  
   WheelPos -= 170;  
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);  

void BrightAdj(uint8_t wait) 
  byte j;  
  for(j=10; j<256; j++) 
        Brightness = j;  
        strip.setBrightness(Brightness); ;
        if (SetBright == 0)  
            EEPROM.write(1, j);             // Write it to EEPROM 
            break;      //get out  


There should be enough comments in the code to work out what is happening.

The connection details are at the top and I'd encourage anyone doing Arduino to include this so you don't need to hunt down that piece of paper you put in the safe place.



The video shows the effects possible, and the camera doesn't really do it justice.



Hopefully this has shown someone how easy it is to make something that is very effective.

The hardware cost is minimal so it suits someone that has plenty of time on their hands.