Project tutorial
Voronoi101: Light Your Lamp!

Voronoi101: Light Your Lamp! © MIT

Create a Voronoi tessellated lamp with a 24 NeoPixel Ring and control it with an Arduino/Genuino101 over Bluetooth Low Energy!

  • 9,242 views
  • 2 comments
  • 23 respects

Components and supplies

Ardgen 101
Arduino 101 & Genuino 101
×1
1586 00
Adafruit NeoPixel Ring: WS2812 5050 RGB LED
The actual Part I used was NeowPixel Ring - 24x RGBW Cool LED Adafruit Part #2863
×1
12002 04
Breadboard (generic)
×1
11026 02
Jumper wires (generic)
×1
1434509556 android phone color
Android device
×1

Necessary tools and machines

3drag
3D Printer (generic)
I used a Lulzbot mini with HIPS filament for the base and Taulman Bridge Nylon for the lamp shade.

Apps and online services

About this project

Voronoi 101: Light your Lamp!

Introduction & Motivation :

The classic introduction to a new programming language is the ‘HelloWorld’ program and for a new microcontroller, it is the ‘Blink’ example. If you can get one of these going, you are on your way with whatever language or hardware platform you are learning. So there is nothing to be gained by yet another Blink example, unless maybe, you could blink 24 NeoPixels all at once, change their color and brightness and maybe you could house those 24 neopixels in a really cool 3D printed shade. Oh, and by the way, maybe there would be something to be gained if you could control all of this over Bluetooth Low Energy!

If you are interested, then keep calm and hack on!

This project is derived from 2 projects that piqued my interest and I decided to modify them to work with the Arduino/Genuino101.

The first project comes from Make: Bluetooth LE Projects with Arduino, Raspberry Pi, and Smartphones By: Don Coleman, Alasdair Allan, Sandeep Mistry ISBN-10:1457187094 (https://library.oreilly.com/book/0636920031932/make-bluetooth/toc). This is an excellent book for any maker interested in Bluetooth LE and Arduino. In my opinion, there is no better place to start. Chapter 7’s project is an Arduino/BLE controlled lamp using a NeoPixel ring. I changed the project to work with the Arduino/Genuino101. I had a chance to hear Don Coleman’s talk about BLE at the 2016 DC Maker Faire(http://makerfaire.com/maker/entry/57624/). He stated it would be easy to switch to the Arduino/Genuino101 because the BLE libraries were essentially the same. I was inspired to try and he was right!

The BLE Voronoi Feather Lamp (http://www.thingiverse.com/thing:1343925 or https://learn.adafruit.com/ble-feather-lamp/overview) is the second project. This is from the most excellent Ruiz Brothers by way of Adafruit. I enjoy 3D printing and wanted to finally combine a really neat 3D build with an Arduino project. Having it come from Adafruit and the Ruiz Brothers also increased my confidence that all would function as advertised and that the 3D build would be smooth and worth my time to print. Their project is designed to house the Adafruit Feather 32u4 Bluefruit LE (https://www.adafruit.com/products/2829) and not the Arduino. One of my objectives for future work is to make a complete enclosure compatible with the Arduino/Genuino101.

What you will need:

  • Arduino/Genuino 101 board
  • USB Cable
  • Wires, soldering iron, solder and wire cutters.
  • Helping third hand( not required, but very helpful!)
  • A mobile device, such as a tablet or cellphone, to run Evothings Viewer on.
  • Our modified app files, index.html, arduinoble.js and evothings-app.css

I will assume that you have a 3D printer or have access to one. If not, the electronics and software can all be tested without printing the Voronoi Feather Lamp, but it is really a super build and very satisfying when done.

Software:

The code for this project is commented and I encourage you to read it. Instead of providing a line-by-line breakdown of the how all the code works, I will highlight the areas that I think are most important, informative and interesting. With a BLE connected Arduino/Genuino 101 project, it is important to understand the overall layout of the software required. In addition to the sketch residing on the board , you will also have to write the software to run on the mobile device. The sketch will be written with the Arduino IDE and for the mobile app(called a hybrid wep app), we will use HTML/CSS/JavaScript with Evothings Studio.

Evothings Studio is designed to help you rapidly design and prototype hybrid web apps for the internet of things. You can learn more about this approach by taking advantage of the many tutorials on the Evothings website (https://evothings.com/doc/tutorials/tutorials.html). It is free to use. There are also Hackster.io projects using Evothings and the Arduino/Genuino101, (https://www.hackster.io/arduino/products/arduino-101-genuino-101).

The Arduino Sketch:

In order to model our lamp, let’s first consider what our connected thing is and then how this will be represented in our program and in terms of BLE services and characteristics.

Our physical thing is a NeoPixel lamp. Like any lamp we will want to be able to turn it on and off. The use of NeoPixels will allow us to control the color and brightness of our lamp. It is important when designing our code to keep in mind that while our characteristics are analogous to state variables or attributes in a program, they are not the state variables or attributes of the objects or data structures of our program. So if we wish to control a device, we will still have to represent it in the underlying programming language of the arduino, which is essentially C.

Let’s translate this model into Arduino C with a struct. The struct is a data type in C that allows us to combine different data types in one organizing unit. This is not absolutely required for this project, but it is a good time to learn and will be helpful to organize and keep track of the lamp “object” for this sketch.

We define our lamp struct as such:

struct LampStateStructure
{
boolean lampOn;
int brightness;
int green;
int red;
int blue;
};
struct LampStateStructure lampState;

We can access and set these variables using the following syntax:

lampState.lampOn = false;

Let’s translate the lamp model into BLE terms. The lamp is a service. This service should have an on/off switch, a brightness control and a color chooser. These three elements will be characteristics of our lamp service.

When we define the characteristics of our service, we will have to think of how we will represent the data of values of these characteristics and how they will behave. Specifically in this example, we will have a switch characteristic. A light switch is either on or off, so it might make sense to think of this as a boolean. There is no BLE boolean. However the basic unit of BLE data is the byte or unsigned char. This can work to our advantage, because although we may only initially need to represent on or off, we could potentially represent 255 more options under this characteristic. For example, maybe we could use another value of this characteristic to initiate special light effects or perhaps we could use the values to specify individual NeoPixels on the ring! For the brightness characteristic bytes are ideal and we can use the entire range of a byte value to represent our brightness choice.

The color characteristic is even more interesting. We can specify the color of our NeoPixel ring by specifying a Green, Red and Blue color value. The range of these values is 0..255. Again here the byte or unsigned char data type is ideal here. We could represent these each of the colors with 3 different characteristics, or one characteristic representing the array of values. One is a lonely number, but much more efficient. So will we go with one characteristic containing the three color-byte values.

Finally services and characteristics will each need universally unique identifiers or uuid’s to avoid conflict with other BLE peripherals out there. For custom services and characteristics, a 128 bit uuid is used. These are created by you for your custom service with the aid of uuid generators such as that found onant as we will have to specify these for each of our characteristics with a parameter, such as BLERead, BLEWrite, etc.

Finally services and characteristics will each need universally unique identifiers or uuid’s to avoid conflict with other BLE peripherals out there. For custom services and characteristics, a 128 bit uuid is used. These are created by you for your custom service with the aid of uuid generators such as that found on https://www.uuidgenerator.net/

This is how the BLE all looks in the sketch:

/**
* Setup our BLE service and characteristics here
*/
BLEPeripheral blePeripheral; // BLE Peripheral Device (the board you're programming)
BLEService lampService("917649A0-D98E-11E5-9EEC-0002A5D5C51B"); // Custom UUID
BLEUnsignedCharCharacteristic switchCharacteristic("917649A1-D98E-11E5-9EEC-0002A5D5C51B", BLERead | BLEWrite);
BLEUnsignedCharCharacteristic  brightnessCharacteristic("917649A2-D98E-11E5-9EEC-0002A5D5C51B", BLERead | BLEWrite);
BLECharacteristic colorCharacteristic("917649A3-D98E-11E5-9EEC-0002A5D5C51B", BLERead | BLEWrite,3);
BLEDescriptor lampDescriptor("2902", "lamp");

The above code only sets up the BLE service and characteristics. Now we will have to interact with them. In my prior projects, the BLE interactions in the loop() portion of the sketch. This reflects what most of the BLE examples at show, such as the heart rate monitor sketch:

(https://www.arduino.cc/en/Tutorial/Genuino101CurieBLEHeartRateMonitor).

However after reading Chapter 7 of Make: Bluetooth LE Projects with Arduino, Raspberry Pi, and Smartphones and talking to one of the authors at the 2016 DC Maker Faire, I decided to follow the sketch structure coded there which uses an event handler model.

In this model, the loop() only serves to continually watch for activity from the BLE peripheral. If BLE actions or events are detected, the program control flow is directed to the appropriate action or function through event handlers.This is a closer representation of the way BLE is supposed to work and it is reflected in the arduino with code. I have seen the light! :) There are additional benefits to this:

1)We are not reinventing the wheel. The activity polling mechanism has been created for us, why recreate it in our own loop() function?

2) The code is cleaner and easier to read. There is a one-to-one connection BLE event and sketch activity. Why isn’t my characteristic not updating? Go right to the function and diagnose the problem!

3) The code will also allow easier modification and scaling. Adding a new characteristic won’t require digging through an ever lengthing loop(), but simply writing a new function.

This structure will work very well when the characteristics are all written to from a central as in this project. What will the code look like when characteristics are changed from within the the thing? It does, and for more on this please read Chapter 6 of Make: Bluetooth LE Projects with Arduino, Raspberry Pi, and Smartphones.

Now on to more code. We have 3 characteristics we want to change, the lamp switch, lamp color and lamp brightness. We will create a function or callback that will be executed anytime there is a change to a characteristic. The purpose of each of these functions will be to change the state of the lamp as it is represented in the struct and to initiate the appropriate action based on this change. Let’s look at the color change, as it is the most interesting.

In the setup() portion of the sketch, we connect specific characteristics with a specific event handler:

colorCharacteristic.setEventHandler(BLEWritten, colorCharacteristicWritten);

The event handler is then specified outside of both the setup() and loop() portions of the sketch:

void colorCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristc)
{
const unsigned char* colors = colorCharacteristic.value();
lampState.green = colors[0];
lampState.red = colors[1];
lampState.blue = colors[2];
for (int i=0;i<NUMPIXELS;i++) {
ring.setPixelColor( i, ring.Color(lampState.green,lampState.red,lampState.blue)); }
ring.show();
}

We passed the parameter 3 when defining the colorCharacteristic. This specifies that the colorCharacteristic will hold 3 bytes of information. So when our mobile app changes the colorCharacteristic, it will send 3 bytes holding a value representing the R, G and B colors chosen. Because we have chosen an event handler model, updates to this characteristic are handled automatically.

And that's all I really want to say about the sketch! After you have the Arduino sketch up and running, you can debug it with a tool such as nRF Master Control before moving on to writing the mobile app. I recommend this, especially if you are new to writing BLE code or Arduino code. If you try and debug the sketch and the mobile app at one time, it will be much harder to trace down your bugs. Better to have ½ half of the software in working order first.

The Hybrid Mobile App:

The other component of the software for an IOT application is the portion of the code that will reside on our mobile device. For this we will use the Evothings platform and the triumvirate of HTML/CSS/JavaScript. The reason we can access the native features of our phone, in this case BLE, without writing a native app, is by using the use of the cordova/phonegap libraries. We won’t work with these directly, but will use the API provided for us by the good people at Evothings, named appropriately enough, easyble.js.

The hardest part of starting a project, is knowing where to start, so let’s start with the code for the a great working example found both on Hackster.io and Evothings: Arduino/Genuino 101 LED On/Off BLE example (https://evothings.com/doc/examples/arduino101-led-onoff.html).

I would like to highlight 3 specific areas in the mobile app. First will be how to connect an HTML UI element to a JavaScript action, using the writeCharacteristic method of the easyble.js library and a brief discussion of the color wheel interface.

Connecting the HTML button with an action is straight-forward. In the index.html file we add the following line to the <body>:

<button class="green wide" onclick="app.lampSwitch()">LAMP</button>

This will create a green colored button labeled “LAMP”. We connect the JavaScript action by stating that the JavaScript function app.lampSwitch() will be called when the button is clicked by stating onclick=”app.lampSwitch()”. As you might have guessed, this will function as our on/off switch for the lamp.

We then define the function in the <script> area of the index.html file:

app.lampSwitch = function() { app.device && app.device.writeLampCharacteristic( newUint8Array([0]), '917649a1-d98e-11e5-9eec-0002a5d5c51b'); }

This line will send the value of 0 to the characteristic specified by the uuid '917649a1-d98e-11e5-9eec-0002a5d5c51b'. If we wanted to increase the readability of the code we could attach this to a literal or variable. Both the data and the characteristic are then passed to the app.device.writeLampCharacteristic() function in the arduinoble.js file. This function is a wrapper around the writeCharacteristic function from the easyble.js library. We only need one function to send data to our lamp in arduinoble.js because we specify the characteristic and data sent from the index.html. Very simple, very elegant!

The Color Picker is an exciting element of the HTML design and I was inspired to use this element from the Bluefruit UI from Adafruit. In HTML5, you can easily capture the color of an image at any point where the user touches the image! For this app, I choose a circular color picker. The HTML5 canvas function canvas.getImage(x,y,1,1).data allows us to capture the image color at the x,y coordinate of the user’s touch. For a more in depth description of this, see How to create a color picker with HTML5 Canvas By Sara Vieira. (http://www.webdesignerdepot.com/2013/03/how-to-create-a-color-picker-with-html5-canvas/). There are many color wheel or color picker images on the web, I found mine at: https://commons.wikimedia.org/wiki/File:Color_Wheel.PNG

<script>
var canvas = document.getElementById('picker').getContext('2d');
var img = new Image();
img.src = 'colorWheel4.png';
$(img).load(function(){ canvas.drawImage(img,100,5,295,295);});
$('#picker').click(function(event)
{
var x = event.pageX - this.offsetLeft;
var y = event.pageY - this.offsetTop;
var imgData = canvas.getImageData(x,y,1,1).data;
var R = imgData[0];
var G = imgData[1];
var B = imgData[2];
app.changeLampColor( new Uint8Array([G,R,B]));
});
</script>

In this way, you could display any image on your UI and allow the user to change the lamp color based on the RGB data on any point on the image your user selects. If you had an image file, say “lizard.png” from EmojiOne you would put this image file in the same directory as the index.html which in this case is EvothingsStudio/MyApps/lamp/app/ and then change the image file name in the following line of code:

img.src = 'colorWheel4.png';

To

img.src = 'lizard.png';

Now you can enjoy the colors of your favorite EmojiOne (http://emojione.com/) emoji on your lamp by clicking on the image!

Yes it's a gecko, they didn't have a chameleon.

When I first wrote the HTML for this app, the slider did not look very appealing. So I did some googling and reading and found this site(url here).

For the app, locate the CSS file called evothings-app.css. It's located in the -- directory. When you scroll down to the INPUT FIELDS section, you will see that there is no style specified for the range slider. With the assistance of the range slider formatting tool above we can customize our range slider and then cut and paste the CSS directly into this file:

input[type=range]:focus {
outline: none;
}
input[type=range]{
-webkit-appearance: none;
width: 100%;
height: 25px;
cursor: pointer;
animate: 0.5s;
box-shadow: 1px
background: #AAB7B8;
border-radius: 19px;
border: 2px
}
input[type=range]::-webkit-slider-thumb {
-webkit-apperance: none;
box-shadow: 0px
border: 2px
height: 25px;
width: 36px;
border-radius: 15px;
background: #529DE1;
cursor: pointer;
-webkit-appearance: none;
margin-top: 0px;
}

That's all it takes to make a much more appealing and stylish slider to control brightness than default.

One other CSS item is worth mentioning. When I initially rendered the color wheel image on the canvas, it had a slightly grey background. I didn't like this and thought it would look better with a transparent background, this is accomplished by scrolling down to the VARIOUS ELEMENTS section and commenting out the background color item:

canvas {
padding: 7px;
border-radius: 4px;
border: none;
/* background-color: #f3f3f3; Default color: "Arctic" */
}

As you can see from the two examples above, one of the joys of taking the hybrid web app approach is the ease of creating UI and the rich set of tools provided with HTML and CSS to customize your app's UI. For myself, I only just begun the scratch the surface of HTML/CSS/JavaScript programming and can't wait to explore it more

Project Recipe:

This is an intermediate project. I am assuming you have the Arduino ide installed and setup for the Arduino/Genuino101. I am also assuming that you have EvothngsStudio up and running along with the EvothingsViewer app on the mobile device of your choice.

The project can be broken into 3 main elements: 3D printing, hardware, software.

3D Printing:

  • For printing the enclosure and lamp shade, I downloaded the files on Thingiverse (http://www.thingiverse.com/thing:1343925 ) and following the instructions there. I don’t have much to add to this. The project base does will not fit an Arduino/Genuino101, this is a project for the future, maybe for you to do and share!
  • I printed the shade with Taulman Bridge Nylon initially because it was the only translucent filament I had! It printed very well.

Hardware:

  • Solder leads to the power(PWR), ground(GND) and input(Data Input) lines of the NeoPixel 24 Ring.
  • Pull these leads through one of the openings on the enclosure base and seat the NeoPixel Ring in the groove.
  • Connect the Data Input wire to Pin 6 on the Arduino/Genuino101.
  • Connect the GND wire to the Arduino/Genuion101 ground pin.
  • Connect the PWR wire to the 5 v pin on the Arduino/Genuio101. I have powered the lamp for several days in a row with the Arduino/Genuino101 plugged into my desktop with a USB cable without any trouble.

Software:

  • Using the Arduino IDE, upload the sketch voronoiLamp.ino from the code section below to your completed circuit and enclosure.
  • Start up Evothings Studio.
  • Click on the Examples tab and scroll down to the Arduino101 LED On/Off BLE example and click the COPY button and give the folder a name for your project.
  • You can then name the new app. I named mine lamp, Then press the CREATE button.
  • Using you file viewer, find the directory of this project. On my desktop this was EvothingsStudio/MyApps/lamp/app.
  • Enter the app folder and rename index.html to index_old.html(You may wish to look at the original in the future), replace it with the index.html file from this project in the code section below.
  • The image you choose for a color picker will have to go in the same directory as the index.html file. You will also have to name this file colorWheel4.png in order for it to work with the index.html file as it is currently written.
  • Now from the ../apps directory, follow the directory tree down to the /libs/evothings/arduinoble directory. Rename the arduinoble.js to arduinoble_old.js and replace it with the arduinoble.js file from this project in the code section below.
  • Now go back to the ../app folder and follow the directory tree down to the /ui/css/ directory and rename evothings-app.css file to evothings-app_old.css. Replace it with the evothings-app.css file from this project in the code section below.

Starting it Up

  • The Arduino/Genuino should be cnnected to your computer with a usb cable. The serial port monitor should be on.
  • You should see a message like the following on the serial port monitor:
Arduino101/IntelCurie/NeoPixel-Voroni-Lamp/Evothings Example Started 
Serial rate set to 9600 
Bluetooth device active, waiting for connections...
  • Now start up EvothingsStudio on your computer and EvothingsVIewer app on your mobile device
  • Go to the Connect tab on EvothingsStudio and get your connect key.
  • Enter this into the text box at top of the EvothingsViewer app and press the CONNECT button
  • Go back to EvothingsStudio and click on the MyApps tab, find your project and click on the green RUN button.
  • Once you see the page rendered, your are ready to Light Your Lamp

Conclusion:

My hope was to show how easy it is to create a Bluetooth LE connected app with Arduino/Genuino101 and EvothingsStudio and I look forward to hearing your comments, builds and variations on the theme!

"...If it had all just worked, it would have been far less fun! I mean it!"

- Cliff Lasser, from Reader Input in Make Vol 51 June/July 2016

Code

The Arduino/Genuino101 SketchArduino
This will be uploaded to the Arduino/Genuino101 with the Arduino IDE
#include <CurieBLE.h>
#include <Adafruit_NeoPixel.h>

/**
* This project demonstrates how to control an adafruit industries NeoPixel Ring over BLE using an arduino/genuino101.
* This projct is derived from the Cproject in Chapter 7 of Make: Bluetooth: Bluetooth LE Projects with Arduino, Raspberry Pi, 
* and Smartphones and the project by the Ruiz brothers from Adafruit entitled,(http://www.thingiverse.com/thing:1343925) 
*/

/**
* Setup our BLE service and characteristics here
*/
BLEPeripheral blePeripheral;       // BLE Peripheral Device (the board you're programming)
BLEService lampService("917649A0-D98E-11E5-9EEC-0002A5D5C51B"); // Custom UUID
BLEUnsignedCharCharacteristic switchCharacteristic("917649A1-D98E-11E5-9EEC-0002A5D5C51B", BLERead | BLEWrite);
BLEUnsignedCharCharacteristic brightnessCharacteristic("917649A2-D98E-11E5-9EEC-0002A5D5C51B", BLERead | BLEWrite);
BLECharacteristic colorCharacteristic("917649A3-D98E-11E5-9EEC-0002A5D5C51B", BLERead | BLEWrite,3);
BLEDescriptor lampDescriptor("2902", "lamp");

/**
 * establish which pin the NeoPixel ring is attachd to on the Arduino/Genuino101, and the
 * number of NeoPixels on the ring.
 * 
*/
#define PIN            6
#define NUMPIXELS      24
/* 
 *  When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
 *  Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
 *  example for more information on possible values.
*/

Adafruit_NeoPixel ring = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_RGBW + NEO_KHZ800);
// Adafruit_NeoPixel pixels;
int delayTime = 150; // delay used for NeoPixel light effects.

// Lamp state structure

struct LampStateStructure
{
  boolean lampOn;
  int brightness;
  int green;
  int red;
  int blue;
};

struct LampStateStructure lampState;

void setup() {

  /** Serial 
  * Serial communication is not necessary for this project to work, but
  * is very useful for debugging. All serial references could be 
  * commented out if desried.
  */
  Serial.begin(9600); // initialize Serial communication
  while (!Serial);    // wait for the serial port to open
 
  Serial.println("Arduino101/IntelCurie/NeoPixel-Voroni-Lamp/Evothings Example Started");
  Serial.println("Serial rate set to 9600");

  // initilize the ble service, characterisitcs and advertising
  blePeripheral.setLocalName("voronoi");
  blePeripheral.setAdvertisedServiceUuid(lampService.uuid());
  blePeripheral.addAttribute(lampService);
  blePeripheral.addAttribute(switchCharacteristic);
  blePeripheral.addAttribute(brightnessCharacteristic);
  blePeripheral.addAttribute(colorCharacteristic);
  blePeripheral.addAttribute(lampDescriptor);

  // add event handlers here
  blePeripheral.setEventHandler(BLEConnected, blePeripheralConnectHandler);
  blePeripheral.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);
  switchCharacteristic.setEventHandler(BLEWritten, switchCharacteristicWritten);
  brightnessCharacteristic.setEventHandler(BLEWritten, brightnessCharacteristicWritten);
  colorCharacteristic.setEventHandler(BLEWritten, colorCharacteristicWritten);

  // set an initial values for the characteristics
  switchCharacteristic.setValue(-1);
  brightnessCharacteristic.setValue(0);
  
  /** 
   * the color characterisitc consists of the 3 GREEN,RED and BLUE values sent
   * from the mobile device as a single characterisitic of 3 bytes, each a 
   * value from 0..255
  */
  
  const unsigned char initialColor[3] = {0,0,0};
  colorCharacteristic.setValue(initialColor,3);
  
  // advertise the service
  blePeripheral.begin();
  Serial.println(("Bluetooth device active, waiting for connections..."));

  // setup the lamp state variable strucutre and set to intial values
  
  lampState.lampOn = false;
  lampState.brightness = 200;
  lampState.green = 250;
  lampState.red = 250;
  lampState.blue = 250;


  // This initializes the NeoPixel, read the code in the NeoPixellibrary to understand what it does.
  ring.begin(); 
}

void loop() {


  // continual poll the ble device for activity, connection, disconnect, characterisitc cahgnes, etc.
  blePeripheral.poll();
  
} // end loop

/**
 * BLE Event Handlers are defined in the fucntions below
 */
 
void blePeripheralConnectHandler(BLECentral& central) 
{
  // central connected event handler
  Serial.print("Connected event, central: ");
  Serial.println(central.address());
}

void blePeripheralDisconnectHandler(BLECentral& central) 
{
  // central disconnected event handler
  Serial.print("Disconnected event, central: ");
  Serial.println(central.address());
}

void switchCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic)
{
  /**
   * We will use a switch/case statement here so that we can expand the functionality of the app 
   * in the future; This will allow us to accept values up to 255 on the switch characteristic
   * and not permanently tie the characteritis to just turning the lamp on/off;
   */

   int switchValue = switchCharacteristic.value();
   Serial.print("Switch Value: "); Serial.println(switchValue);

   switch(switchValue)
   {
      case 0:
        // Turn lamp on/off
        lamp();
        break;
      case 1:
        // for debugging/expanded functionality later
        break;
      case 2:    
        // for debugging/expanded functionality later
        break;
      case 3:
        // for debugging/expanded functionality later
        break;  
   }   
}
void brightnessCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic)
{

  lampState.brightness = brightnessCharacteristic.value();
  ring.setBrightness(lampState.brightness);
  ring.show();
  
}
void colorCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic)
{
  // The colors on this neopixel are speciifed GRB not RGB!
  const unsigned char* colors = colorCharacteristic.value();
  lampState.green = colors[0];
  lampState.red = colors[1];
  lampState.blue = colors[2];
  for (int i=0;i<NUMPIXELS;i++)
  {
    ring.setPixelColor( i, ring.Color(lampState.green,lampState.red,lampState.blue));
  }
  ring.show();
}

void lamp()
{
  if (lampState.lampOn)
  {
    /** do not set the lamp state variable lampState.brightness to 0 
     *  as the expectation of turning the lamp back on will be 
     *  for the lamp to turn back on to the same brightness
     *  as before turnng off. 
     *        Consider adding a dimming effect here.
     */
    ring.setBrightness(0);
    ring.show();
    lampState.lampOn = false;
  } 
  else
  {
    ring.setBrightness( lampState.brightness );
    for (int i=0;i<NUMPIXELS;i++)
    {
      ring.setPixelColor( i, ring.Color(lampState.green,lampState.red,lampState.blue));
    }
    ring.show();
    lampState.lampOn = true;
  }
}
index.htmlHTML
This is the index.html file for the mobile app, it includes Javascript as well. . .
<!DOCTYPE html>
<html>
<!--
This is an app that demonstrates how to control a NeoPixel ring Lamp
using BLE (Bluetooth Low Energy).
-->
<head>

	<meta charset="utf-8" />
	<meta name="viewport" content="width=device-width, user-scalable=no
		initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />

	<title>Arduino/Genuino101 Voronoi Lamp</title>

	<style>
		@import 'ui/css/evothings-app.css';
	</style>

	<script>
	// Redirect console.log to Evothings Workbench.
	if (window.hyper && window.hyper.log) { console.log = hyper.log }
	window.onerror = function(msg, url, line)
	{
		console.log(msg + ": " + url + ":" + line);
	};
	</script>

	<script src="cordova.js"></script>
	<script src="libs/jquery/jquery.js"></script>
	<script src="libs/evothings/evothings.js"></script>
	<script src="libs/evothings/ui/ui.js"></script>
	<script src="libs/evothings/arduinoble/arduinoble.js"></script>

</head>

<body ontouchstart=""><!-- ontouchstart="" enables low-delay CSS transitions. -->

	<header>
		<button class="back" onclick="history.back()">
			<img src="ui/images/arrow-left.svg" />
		</button>

		<img class="logotype" src="ui/images/logo.svg" alt="Evothings" />

		<!--<button class="menu" onclick=""><img src="ui/images/menu.svg" /></button>-->
	</header>

	<h1>Voronoi 101 Lamp</h1>
 
	<p id="info">Initializing...</p>

        <button class="blue wide" onclick="app.connect()">BLE CONNECT</button>
        <canvas id="picker" width="500" height="300"></canvas>
        <button class="green wide" onclick="app.lampSwitch()">LAMP</button>
        <label for="brightness">Brightness</label>
        <input type="range" id="brightness" value="127" min="0" max="255" oninput="brightnessSelect()">
          
    <!-- ColorPicker javascript, see...
     The Color Wheel png file comes from this URL.
     The image file will need to be in the same directory as
     this index.html file and named colorWheel4.png in order
     to render the graphic in the UI.

     
     https://commons.wikimedia.org/wiki/File:Color_Wheel.PNG
     
     -->
    <script>
        /**
         * The following JavaScript code allows us to get the color value
         * as the selected point on rendered image on the UI.
         */
        var canvas = document.getElementById('picker').getContext('2d');
        var img = new Image();
        img.src = 'colorWheel4.png';
        // img.src = 'lizard.png';
        $(img).load(function(){ canvas.drawImage(img,100,5,295,295);});
        $('#picker').click(function(event)
        {
            var x = event.pageX - this.offsetLeft;
            var y = event.pageY - this.offsetTop;
            var imgData = canvas.getImageData(x,y,1,1).data;
            var R = imgData[0];
            var G = imgData[1];
            var B = imgData[2];
            app.changeLampColor( new Uint8Array([G,R,B]));
        });
    </script>
 
    <!-- brightness slider -->
    <script>
        function brightnessSelect() {
            var x = document.getElementById("brightness").value;
            app.changeLampBrightness(new Uint8Array([x]));
            // console.log( 'brightness: ' + x);
        }
    </script>
    <!-- BLE connectivity javascript, see... -->
	<script>
	// Application object.
	var app = {}

	// Connected device.
	app.device = null;

    /**
     * The following functions are connected to our UI and serve to pass data to the proper 
     * characteristic uuid. To improve the reability and ease of future modifications of this 
     * code, it would beneficial to create literals for each of these characteristic uuid's.
     */

	// Turn NeoPixel Lamp On/Off.
	app.lampSwitch = function()
	{
		app.device && app.device.writeLampCharacteristic(new Uint8Array([0]), '917649a1-d98e-11e5-9eec-0002a5d5c51b');
	}

    app.changeLampColor = function(color)
    {
        /*
         * The variable color is sent to this function as an array of 3 bytes reflecting the RGB values the
         * user has slected from the image on the UI. See lines 64-79 above.
         */
        
        app.device && app.device.writeLampCharacteristic(color, '917649a3-d98e-11e5-9eec-0002a5d5c51b');
    }
    
    app.changeLampBrightness = function(brightness)
    {
        app.device && app.device.writeLampCharacteristic(brightness, '917649a2-d98e-11e5-9eec-0002a5d5c51b');

    }
	app.showMessage = function(info)
	{
		document.getElementById('info').innerHTML = info
	};

	// Called when BLE and other native functions are available.
	app.onDeviceReady = function()
	{
		app.showMessage('Touch the connect button to begin.');
	};

	app.connect = function()
	{
		evothings.arduinoble.close();
		app.showMessage('Connecting...');

		evothings.arduinoble.connect(
			'voronoi', /* Advertised name of BLE device as specified in out Arduino sketch */
			function(device)
			{
				app.device = device;
				app.showMessage('Connected! Touch buttons to turn LED on/off.');
			},
			function(errorCode)
			{
				app.showMessage('Connect error: ' + errorCode + '.');
			});
	};

	document.addEventListener(
		'deviceready',
		function() { evothings.scriptsLoaded(app.onDeviceReady) },
		false);
	</script>

</body>

</html>
arduinoble.jsJavaScript
This is javascript to communicate over BLE. Only one function is changed here.
// File: arduinoble.js

// Load library EasyBLE.
evothings.loadScript('libs/evothings/easyble/easyble.js');

/**
 * @namespace
 * @author Mikael Kindborg
 * @description <p>Functions for communicating with an Arduino BLE shield.</p>
 * <p>It is safe practise to call function {@link evothings.scriptsLoaded}
 * to ensure dependent libraries are loaded before calling functions
 * in this library.</p>
 *
 * @todo This is a very simple library that has only write capability,
 * read and notification functions should be added.
 *
 * @todo Add function to set the write characteristic UUID to make
 * the code more generic.
 */

/**
 * This file was modifed by GV 7/1/2016 to commuincate over the onboard BLE on the
 * Arduino/Genuino101 to run the voronoi101 NeoPixel Lamp project.
 */
 evothings.arduinoble = {};

;(function()
{
	// Internal functions.
	var internal = {};

	/**
	 * Stop any ongoing scan and disconnect all devices.
	 * @public
	 */
	evothings.arduinoble.close = function()
	{
		evothings.easyble.stopScan();
		evothings.easyble.closeConnectedDevices();
	};

	/**
	 * Called when you've connected to an Arduino BLE shield.
	 * @callback evothings.arduinoble.connectsuccess
	 * @param {evothings.arduinoble.ArduinoBLEDevice} device -
	 * The connected BLE shield.
	 */

	/**
	 * Connect to a BLE-shield.
	 * @param deviceName BLE name if the shield.
	 * @param {evothings.arduinoble.connectsuccess} success -
	 * Success callback: success(device)
	 * @param {function} fail - Error callback: fail(errorCode)
	 * @example
	 * evothings.arduinoble.connect(
	 *   'arduinoble', // Name of BLE shield.
	 *   function(device)
	 *   {
	 *     console.log('connected!');
	 *     device.writeDataArray(new Uint8Array([1]));
	 *     evothings.arduinoble.close();
	 *   },
	 *   function(errorCode)
	 *   {
	 *     console.log('Error: ' + errorCode);
	 *   });
	 * @public
	 */
	evothings.arduinoble.connect = function(deviceName, success, fail)
	{
		evothings.easyble.startScan(
			function(device)
			{
				if (device.name == deviceName)
				{
					evothings.easyble.stopScan();
					internal.connectToDevice(device, success, fail);
				}
			},
			function(errorCode)
			{
				fail(errorCode);
			});
	};

	/**
	 * Connect to the BLE shield.
	 * @private
	 */
	internal.connectToDevice = function(device, success, fail)
	{
		device.connect(
			function(device)
			{
				// Get services info.
				internal.getServices(device, success, fail);
			},
			function(errorCode)
			{
				fail(errorCode);
			});
	};

	/**
	 * Read all services from the device.
	 * @private
	 */
	internal.getServices = function(device, success, fail)
	{
		device.readServices(
			null, // null means read info for all services
			function(device)
			{
				internal.addMethodsToDeviceObject(device);
				success(device);
			},
			function(errorCode)
			{
				fail(errorCode);
			});
	};

	/**
	 * Add instance methods to the device object.
	 * @private
	 */
	internal.addMethodsToDeviceObject = function(device)
	{
		/**
		 * Object that holds info about an Arduino BLE shield.
		 * @namespace evothings.arduinoble.ArduinoBLEDevice
		 */

		/**
         * The only function we need as the data and characteristics
         * are passed in here from the functions in <script>
         * sections of the index.html file
         */
  
  
        device.writeLampCharacteristic = function(uint8array,uuid)
        {
            device.writeCharacteristic(
                uuid,
                uint8array,
                function()
                {
                    console.log('write color char sucess');
                },
                    function(errorCode)
                {
                    console.log('write color char error' + errorCode);
                });
        };

  
  
  
  
	};
})();
evothings-app.cssCSS
The CSS file for the mobile app.
/* Common styles for Evothings examples and client. */

@import '../fonts/ProximaNova.css';

html, body {
	height: 100%;
	margin: 0;
	padding: 0;

	font-family: 'Proxima Nova Regular', sans-serif;
	font-weight: normal;

	background: rgb(255,255,255);

	-webkit-touch-callout: none;
	-webkit-user-select: none;
	-khtml-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
	-webkit-tap-highlight-color: rgba(0,0,0,0);
}
body {
	margin: 0 0.9em 0 0.9em;
	font-size: 150%;
	font-size: 7.5vw;
}

/* Add a top margin to the content corresponding to the height of the header. */
body::before,
section::before {
	display: block;
	width: 100%;
	height: 1.1em; /* Should correspond to header's height. */
	margin-bottom: 0.4em;

	content: '\0000a0'; /* Non-breaking space (&nbsp;) */
	font-size: 180%; /* Same as the header's font size. */
	line-height: 200%; /* Slighly more than the header's line-height. */
}

/* Add a bottom margin. */
body::after,
section::after {
	display:block;
	content: '';
	height: 1em;
}




/*  ----------------------------------------------------------
								GENERAL
	---------------------------------------------------------- */

.hidden {
	display: none;
}




/*  ----------------------------------------------------------
								HEADER
	---------------------------------------------------------- */

/* The header's height is determined by the contained text's font size. */
header {
	box-sizing: border-box; /* Width & height includes padding & border. */

	position: fixed;
	top: 0;
	left: 0;
	right: 0;

	width: 100%;
	height: 1.1em;

	/* Left and right margins should correspond to body margins. */
	margin: 0 0 3.45% 0;
	/* Left padding should correspond to the back button's width. */
	padding: 1% 2% 1% 2%;

	font-size: 180%;
	line-height: 100%;
	text-align: center;
	vertical-align: middle;

	background: #f3f3f3;

	z-index: 1000;
}
header button {
	display: block;
	position: absolute;
	top: 50%;
	max-height: 70%;

	margin: 0;

	font-size: 30%;

	-webkit-transform: translateY(-50%);
	-ms-transform: translateY(-50%);
	transform: translateY(-50%);
}
header button.back {
	position: absolute;
	left: 0;

	height: 100%;
	margin: 0;
	padding: 0 0.9em;

	/* Font size is percentage of the header's font size. */
	font-size: 50%;
	color: #000;

	text-align: left;

	background: none;

	border-radius: 0;
	border: none;

	box-shadow: none;
}
header button.back img {
	height: 0.5em;
}
header img.logotype {
	position: absolute;
	top: 50%;
	left: 0;
	right: 0;

	height: 60%;

	margin: 0 auto;

	-webkit-transform: translateY(-50%);
	-ms-transform: translateY(-50%);
	transform: translateY(-50%);
}




/*  ----------------------------------------------------------
								MENU
	---------------------------------------------------------- */

header button#menu-button {
	position: absolute;
	right: 0;

	width: 3em;
	height: 100%;
	max-height: 100%;
	margin: 0;
	padding: 0 0.9em;

	/* Font size is percentage of the header's font size. */
	font-size: 50%;
	color: #000;

	text-align: right;

	background: none;

	border-radius: 0;
	border: none;

	box-shadow: none;
}
header button#menu-button img {
	height: 34%;
}
header button#menu-button:focus {
	pointer-events: none;
	outline: none;
}
header button#menu-button:focus::-moz-focus-inner {
	border: 0;
}
header button#menu-button:focus + menu {
	opacity: 1;
	visibility: visible;
}
header menu {
	display: block;
	position: absolute;
	top: 100%;
	right: 0;

	margin: 0;
	padding: 0;

	background: #f3f3f3;

	opacity: 0;
	visibility: hidden;
	transition: visibility 0.5s;
}

header menu > * {
	display: block;

	padding: 0 1em 0 1em;

	font-family: 'Proxima Nova Bold';
	font-size: 35%;
	text-align: right;
}
header menu a {
	color: #000;
	text-decoration: none;
}

header h1 {
	width: 100%;
	margin: 0;
	padding: 0;

	font-size: inherit;
	line-height: inherit;
	font-weight: normal;
	text-align: center;
	vertical-align: middle;
	color: #eee;

	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}




/*  ----------------------------------------------------------
								SECTIONS
	---------------------------------------------------------- */

main {
	z-index: 0;
}

main footer {
	box-sizing: border-box; /* Width & height includes padding & border. */

	position: fixed;
	bottom: 0;

	width: 100%;

	margin: 0 -5% 0 -5%;
	padding: 0 5% 0 5%;

	background-color: #fff;

	box-shadow: inset 0 5px 9px -9px #000;

	z-index: 2;
}

section {
	display: none;

	box-sizing: border-box; /* Width & height includes padding & border. */

	position: absolute;

	top: 0;
	right: 0;
	bottom: 0;
	left: 0;

	width: 100%;

	padding: 0 0.9em 0 0.9em;

	background-color: #fff;

	z-index: 2;

}

section:target {
	display: block;
}



/*  ----------------------------------------------------------
							INPUT FIELDS
	---------------------------------------------------------- */

input {
	margin: 0;
	padding: 0;

	border: none;

	font-family: inherit;
	font-size: 63%;
}

input[type="text"],input[type="url"],input[type="tel"],input[type="password"],
input[type="email"],input[type="search"],input[type="number"],
input[type="date"],input[type="month"],input[type="week"],input[type="time"] {
	width: 50%;

	padding: 7px 14px 7px 14px;

	font-family: inherit;
	font-size: 63%;
	color: #000;

	border-radius: 4px;
	border: none;

	background-color: #f3f3f3; /* Default color: "Arctic". */
}

textarea {
	box-sizing: border-box; /* Width & height includes padding & border. */
	width: 100%;

	padding: 7px 14px 7px 14px;

	border-radius: 4px;
	border: none;

	font-family: inherit;
	font-size: 63%;
	line-height: 1.5;

	background-color: #f3f3f3; /* Default color: "Arctic". */
}

input[type=range]:focus {
    outline: none;
}
input[type=range]{
    -webkit-appearance: none;
    width: 100%;
    height: 25px;
    cursor: pointer;
    animate: 0.5s;
    box-shadow: 1px 1px 1px #50555C;
    background: #AAB7B8;
    border-radius: 19px;
    border: 2px solid #000000;
}
input[type=range]::-webkit-slider-thumb {
    -webkit-apperance: none;
    box-shadow: 0px 0px 0px #000000;
    border: 2px solid #000000;
    height: 25px;
    width: 36px;
    border-radius: 15px;
    background: #529DE1;
    cursor: pointer;
    -webkit-appearance: none;
    margin-top: 0px;
}



/*  ----------------------------------------------------------
								BUTTONS
	---------------------------------------------------------- */

button.clear {
	margin-left: 1%;
	background-color: #e15a64; /* Default color: "Soft Red". */
}

button,
input.btn-group + label,
.button {
	display: inline-block;
	box-sizing: border-box; /* Width & height includes padding & border. */

	font-family: 'Proxima Nova Black';
	font-size: inherit;
	line-height: 100%;
	text-align: center;
	text-transform: uppercase;

	color: #fff;

	margin: 0.5em 0 0.5em 0;
	padding: 9px 13px 8px 13px;

	border-radius: 4px;
	border: none;

	box-shadow: none;

	background-color: #b9b9b9; /* Default color: "Charcoal" */
}
body > button,
body > input.btn-group + label,
main > button,
main > input.btn-group + label {
	font-size: 63% !important;
}
button:active, button.pressed,
input.btn-group:active + label, input.btn-group + label:active,
input.btn-group:checked + label {
	box-shadow: inset 0 8px 9px -9px #000;
	background-color: #9d9d9d; /* Default color: "Charcoal" */
}
button:focus,
input.btn-group:focus {
	outline: none;
}

button.half,
input.btn-group.half + label,
input.btn-group + label.half {
	float: left;
	width: 50%; /* Fallback in case calc() is unsupported. */
	width: calc(50% - 4px);
	margin-left: 2px;
	margin-right: 2px;
}

button.third,
input.btn-group.third + label,
input.btn-group + label.third {
	float: left;
	width: 33%; /* Fallback in case calc() is unsupported. */
	width: calc(33% - 4px);
	margin-left: 2px;
	margin-right: 2px;
}

button.quarter,
input.btn-group.quarter + label,
input.btn-group + label.quarter {
	float: left;
	width: 25%; /* Fallback in case calc() is unsupported. */
	width: calc(25% - 4px);
	margin-left: 2px;
	margin-right: 2px;
}

button.wide,
input.btn-group.wide + label,
input.btn-group + label.wide {
	width: 100%;
}

button.big,
input.btn-group.big + label,
input.btn-group + label.big {
	font-size: 150%;
	line-height: 3.0;
}

/*  Input with class btn-group should be accompanied by a label acting as a
	button. */
input.btn-group {
	display: none;
}




/*  ----------------------------------------------------------
							VARIOUS ELEMENTS
	---------------------------------------------------------- */

canvas {
	padding: 7px;

	border-radius: 4px;
	border: none;

	/* background-color: #f3f3f3; /* Default color: "Arctic" */
}

figcaption {
	font-size: 63%;
}

h1 {
	padding: 0;
	margin: 1em 0 0 0;

	font-family: 'Proxima Nova Black';
	font-size: 100%;
	line-height: 1.5;

	vertical-align: middle;
}
header + h1, body h1:first-child, main h1:first-child, article h1:first-child {
	margin-top: 0;
}

h2,h3,h4,h5,h6 {
	margin: 1em 0 0 0;
	padding: 0;

	font-family: 'Proxima Nova Bold';
	font-size: 63%;

	line-height: 1.5;

	vertical-align: middle;
}

a {
	color: #52afb8; /* Default color: "Blue Hue" (dark variant) */
}

p {
	margin: 0.4em 0 0.4em 0;
	padding: 0;

	font-size: 63%;
	line-height: 1.5;
}

table {
	table-layout: fixed;
	width: 100%;
	font-size: 63%;
	text-align: left;
}
thead {
	font-family: 'Proxima Nova Bold';
}

strong {
	font-family: 'Proxima Nova Bold';
}

code {
	font-size: inherit;
}

ol,ul {
	list-style-type: none;
	list-style-position: inside;
	counter-reset: item;

	margin: 0.5em 0 0 0;
	padding: 0;

	font-size: 63%;
}
ol li, ul li {
	padding: 0.5em 0 0.5em 0;

	font-size: inherit;
	line-height: 1.5;
}
ol li:before {
	content: counter(item) ". ";
	counter-increment: item;
	font-family: 'Proxima Nova Bold';
}
ul.dynamic {
	list-style-type: none;
	padding: 0;
}
ul.dynamic li {
	padding: 4% 15% 4% 4%;

	border-radius: 4px;
	border: none;

	box-shadow: inset 0 -7px 12px -12px #000;

	background-color: #f3f3f3;
}
ul.dynamic li:last-child {
	box-shadow: none;
}
ul.dynamic li a {
	color: #000;
}
ul.dynamic.arrow li,
ul.dynamic li.arrow {
	background-image: url('../images/arrow-right.svg');
	background-position: 94% center; /* CSS 2 fallback */
	background-position: right 5% center; /* requires CSS 3 */
	background-size: 1em auto;
	background-repeat: no-repeat;
}

article {
	display: none;
	z-index: 2;

	font-size: 100%;
}




/*  ----------------------------------------------------------
								COLORS
	---------------------------------------------------------- */

/*  Color: "Soft Red"
	Class name: red
    ---------------- */
.color_softred { color: #e15a64; }
.bg_red, input.red, button.red, ul.red li, label.red,
input.red + label {
	background-color: #e15a64;
}
/* Downpressed button. */
button.red:active, button.red.pressed,
/* Input element with adjacent label. */
input.btn-group:active + label.red,
input.btn-group.red:active + label,
input.btn-group:checked + label.red,
input.btn-group.red:checked + label {
	background-color: #cb414b;
}

/*  Color: "Bright Light"
	Class name: yellow
    -------------------- */
.color_brightlight { color: #ecd53b; }
.bg_yellow, input.yellow, button.yellow, ul.yellow li, label.yellow,
input.yellow + label {
	background-color: #ecd53b;
}
/* Downpressed button. */
button.yellow:active, button.yellow.pressed,
/* Input element with adjacent label. */
input.btn-group:active + label.yellow,
input.btn-group.yellow:active + label,
input.btn-group:checked + label.yellow,
input.btn-group.yellow:checked + label {
	background-color: #d9c022;
}

/*  Color: "Wave Green"
	Class name: green
    ------------------ */
.color_wavegreen { color: #54dfb3; }
.bg_green, input.green, button.green, ul.green li, label.green,
input.green + label {
	background-color: #54dfb3;
}
/* Downpressed button. */
button.green:active, button.green.pressed,
/* Input element with adjacent label. */
input.btn-group:active + label.green,
input.btn-group.green:active + label,
input.btn-group:checked + label.green,
input.btn-group.green:checked + label {
	background-color: #3aca9c;
}

/*  Color: "Blue Hue"
	Clas name: blue
    ------------------ */
.color_bluehue { color: #6bc6ce; }
.bg_blue, input.blue, button.blue, ul.blue li, label.blue,
input.blue + label {
	background-color: #6bc6ce;
}
/* Downpressed button. */
button.blue:active, button.blue.pressed,
/* Input element with adjacent label. */
input.btn-group:active + label.blue,
input.btn-group.blue:active + label,
input.btn-group:checked + label.blue,
input.btn-group.blue:checked + label {
	background-color: #52afb8;
}

/*  Color: "Indigo"
	Class name: indigo
    ------------------ */
.color_indigo { color: #b48b9b; }
.bg_indigo, input.indigo, button.indigo, ul.indigo li, label.indigo,
input.indigo + label {
	background-color: #b48b9b;
}
/* Downpressed button. */
button.indigo:active, button.indigo.pressed,
/* Input element with adjacent label. */
input.btn-group:active + label.indigo,
input.btn-group.indigo:active + label,
input.btn-group:checked + label.indigo,
input.btn-group.indigo:checked + label {
	background-color: #9c7283;
}

/*  Color: "Arctic"
	Class name: arctic
    ------------------ */
.color_arctic { color: #f3f3f3; }
.bg_arctic, input.arctic, button.arctic, ul.arctic li,
input.arctic + label {
	background-color: #f3f3f3;
}
/* Downpressed button. */
button.arctic:active, button.arctic.pressed,
/* Input element with adjacent label. */
input.btn-group:active + label.arctic,
input.btn-group.arctic:active + label,
input.btn-group:checked + label.arctic,
input.btn-group.arctic:checked + label {
	background-color: #656565;
}

/*  Color: "Aluminium"
	Class name: aluminium
    ------------------ */
.color_aluminium { color: #e2e2e2 }
.bg_aluminium, input.aluminium, button.aluminium, ul.aluminium li,
input.aluminium + label {
	background-color: #e2e2e2;
}
/* Downpressed button. */
button.aluminium:active, button.aluminium.pressed,
 /* Input element with adjacent label. */
input.btn-group:active + label.aluminium,
input.btn-group.aluminium:active + label,
input.btn-group:checked + label.aluminium,
input.btn-group.aluminium:checked + label {
	background-color: #c0c0c0;
}

/*  Color: "Charcoal"
	Class name: charcoal
    ------------------ */
.color_charcoal { color: #b9b9b9; }
.bg_charcoal, input.charcoal, button.charcoal, ul.charcoal li,
input.charcoal + label {
	background-color: #b9b9b9;
}
/* Downpressed button. */
button.charcoal:active, button.charcoal.pressed,
/* Input element with adjacent label. */
input.btn-group:active + label.charcoal,
input.btn-group.charcoal:active + label,
input.btn-group:checked + label.charcoal,
input.btn-group.charcoal:checked + label {
	background-color: #9d9d9d;
}

/*  Color: "Stone"
	Class name: stone
    ------------------ */
.color_stone { color: #777777 }
.bg_stone, input.stone, button.stone, ul.stone li,
input.stone + label {
	background-color: #777777;
}
/* Downpressed button. */
button.stone:active, button.stone.pressed,
/* Input element with adjacent label. */
input.btn-group:active + label.stone,
input.btn-group.stone:active + label,
input.btn-group:checked + label.stone,
input.btn-group.stone:checked + label {
	background-color: #656565;
}

/*  Color: "Jet Black"
	Class name: jetblack
    ------------------ */
.color_black { color: #070707 }
.bg_black, input.black, button.black, ul.black li,
input.black + label {
	background-color: #070707;
}
/* Downpressed button. */
button.black:active, button.black.pressed,
/* Input element with adjacent label. */
input.btn-group:active + label.black,
input.btn-group.black:active + label,
input.btn-group:checked + label.black,
input.btn-group.black:checked + label {
	background-color: #000000;
}

@media	screen and (orientation: landscape) and (-webkit-min-device-pixel-ratio : 2),
		screen and (orientation: landscape) and (min--moz-device-pixel-ratio: 2),
		screen and (orientation: landscape) and (min-device-pixel-ratio : 2) {
	body { font-size: 4.5vw; }
}

Schematics

Fritzing Diagram/Schematic
Voronoi101lamp bb

Comments

Author

Govkn
Gregory O. Voronin
  • 11 projects
  • 82 followers

Additional contributors

Published on

July 10, 2016

Members who respect this project

Photo11329764 10204527425487377 2716116409825649069 nDefaultDefault1f43aScreen shot 2016 04 09 at 12.57.36 pmDefaultXneo1

and 15 others

See similar projects
you might like

Similar projects you might like

BLElectric Light 101

Project tutorial by Gregory O. Voronin

  • 3,587 views
  • 3 comments
  • 15 respects

Controlling LED light intensity using smartphone light senso

Project tutorial by Nikola Travis

  • 1,757 views
  • 0 comments
  • 3 respects

Control your Light System Using Smart Phone

Project tutorial by Ahmed Yassin

  • 35,264 views
  • 4 comments
  • 55 respects

Traffic Light Information System

Project tutorial by Pieter Luyten and Joppe Smeets

  • 16,237 views
  • 18 comments
  • 36 respects

Arduino 101 BLE RGB Lamp

Project tutorial by Gustavo Reynaga

  • 2,152 views
  • 2 comments
  • 10 respects

IMU to You!

by Gregory O. Voronin

  • 11,720 views
  • 40 comments
  • 34 respects
Add projectSign up / Login