Arduino Project Hub
Project showcase

LED Straw XMAS Tree © GPL3+

A simple, original and cheap Christmas tree made with LED-illuminated plastic straws that can be controlled over WiFi.

  • 808 views
  • 0 comments
  • 5 respects

Components and supplies

Apps and online services

About this project

Overview

This is an original, cheap and easy-to-do "Internet of Holiday Things" project. It consists of a small Christmas tree made with plastic straws with LEDs under them, so we can create beautiful light effects.

It can be mounted on the protoboard itself as I did, but it will look better if we solder the LEDs on a perfboard or make a simple PCB so that the tree shape is smoother (KiCad PCB files attached). If we mount the circuit on the protoboard, a custom alignment piece made with cardboard or rigid plastic is highly recommended (I made it with transparent plastic from a container cover), so that the LEDs and straws stays in place.

PCB Layout (2D/3D)

Although the code is made from the simple web server Arduino example (only works with a browser and a local IP), it's easy to take the idea to other platforms, like Blynk, Temboo, etc.

Working

Just change the WiFi SSID and credentials in the code, and type to the browser the IP that shows up on the serial monitor when the MKR1000 establishes connection with you WiFi router. On the browser, you'll see the 4 light mode options with its duration time and a third option to disconnect. You must wait until the mode you clicked finishes to start a new one.

  • Mode 1: Blue and Red fading
  • Mode 2: Green and Yellow fading
  • Mode 3: Fast random fading
  • Mode 4: All color flashing sequences
Modes 1 and 4 examples

Custom parts and enclosures

KiCad files of MKR1000 LED XMAS tree Shield
- Schematic
- PCB layout
mkr1000_led_xmashield_fhSqI1xEZc.zip

Schematics

Protoboard Circuit Diagram
Protoboard xq3lkaf3iy

Code

Arduino Code of the LED straw XMAS TreeArduino
The code (more specifically the LED mode) can be modified as you like it and can be optimised.
It should work also with all Arduino WiFi boards/shield.
#include <SPI.h>
#include <WiFi101.h>

char ssid[] = "ssid";   //  your network SSID (name)
char pass[] = "pass";   // your network password
int keyIndex = 0;       // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;
WiFiServer server(80);

// PWM LED pins (from inside to outside the tree)
int red[] = {1,0,8};
int green[] = {4,7,10};
int blue[] = {6,3,5};
int yellow[] = {A3,A4,2};

byte changeMode = 0;   // Mode selected
boolean infoDone = 0;  // Information about current mode

void setup() {
    
    // Initialize LED pins as OUTPUTS
    for(int i = 0; i < 3; i++){
        pinMode(red[i], OUTPUT);
        pinMode(green[i], OUTPUT);
        pinMode(blue[i], OUTPUT);
        pinMode(yellow[i], OUTPUT);
    }
    
    Serial.begin(9600);   // initialize serial communication

    // check for the presence of the shield:
    if (WiFi.status() == WL_NO_SHIELD) {
        Serial.println("WiFi shield not present");
        while (true);   // don't continue
    }
    // attempt to connect to WiFi network:
    while ( status != WL_CONNECTED) {
        Serial.print("Attempting to connect to Network named: ");
        Serial.println(ssid);   // print the network SSID
        status = WiFi.begin(ssid, pass);
        delay(10000);   // wait 10 seconds for connection:
    }
    server.begin();   // start the web server on port 80
    printIPAdress();  // connected, print SSID and IP
    randomSeed(analogRead(A6));
}

void loop() {
    
    WiFiClient client = server.available();   // listen for incoming clients

    if (client) {                       // if you get a client,
        Serial.println("new client");   // print a message out the serial port
        String currentLine = "";        // make a String to hold incoming data from the client
        while (client.connected()) {    // loop while the client's connected
            if (client.available()) {   // if there's bytes to read from the client,
                char c = client.read(); // read a byte, then
                Serial.write(c);        // print it out the serial monitor
                if (c == '\n') {        // if the byte is a newline character
                    // if the current line is blank, you got two newline characters in a row.
                    // that's the end of the client HTTP request, so send a response:
                    if (currentLine.length() == 0) {
                        // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
                        // and a content-type so the client knows what's coming, then a blank line:
                        client.println("HTTP/1.1 200 OK");
                        client.println("Content-type:text/html");
                        client.println();
                        // the content of the HTTP response follows the header:
                        client.print("Click <a href=\"/1\">here</a> to turn mode 1 on (red/blue), (10 min.).<br>");
                        client.print("Click <a href=\"/2\">here</a> to turn mode 2 on (green/yellow), (10 min.).<br>");
                        client.print("Click <a href=\"/3\">here</a> to turn mode 3 on (random), (10-20 min.).<br>");
                        client.print("Click <a href=\"/4\">here</a> to turn mode 4 on (colors), (30 min.).<br>");
                        client.print("Click <a href=\"/0\">here</a> to disconnect.<br>");
                        client.print("Wait until mode X has finished to start a new mode or disconnect.<br>");
                        switch (changeMode){
                            case 1:
                                client.print("(playing mode 1, wait 10 min.).<br>"); infoDone = 1; break;
                            case 2:
                                client.print("(playing mode 2, wait 10 min.).<br>"); infoDone = 1; break;
                            case 3:
                                client.print("(playing mode 3, wait 15 min. aprox.).<br>"); infoDone = 1; break;
                            case 4:
                                client.print("(playing mode 4, wait 30 min.).<br>"); infoDone = 1; break;
                            default:
                                client.print("(not playing any mode)<br>"); infoDone = 0; break;
                        }
                        // The HTTP response ends with another blank line:
                        client.println();
                        // break out of the while loop:
                        break;
                    }
                    else { // if you got a newline, then clear currentLine:
                        currentLine = "";
                    }
                }
                else if (c != '\r') {  // if you got anything else but a carriage return character,
                    currentLine += c;  // add it to the end of the currentLine
                }
                // Check to see what the client request was, and change mode:
                if (currentLine.endsWith("GET /1")) {
                    changeMode = 1;
                }
                if (currentLine.endsWith("GET /2")) {
                    changeMode = 2;
                }
                if (currentLine.endsWith("GET /3")) {
                    changeMode = 3;
                }
                if (currentLine.endsWith("GET /4")) {
                    changeMode = 4;
                }
                if (currentLine.endsWith("GET /0")) {
                    for(int i = 0; i < 3; i++){
                        digitalWrite(red[i], LOW);
                        digitalWrite(green[i], LOW);
                        digitalWrite(blue[i], LOW);
                        digitalWrite(yellow[i], LOW);
                    }
                    break;
                }
                // First we print mode info, then we activate the specific mode
                if(infoDone == 1){
                    switch(changeMode){
                        case 1: mode1(); infoDone = 0; changeMode = 0; break;
                        case 2: mode2(); infoDone = 0; changeMode = 0; break;
                        case 3: mode3(); infoDone = 0; changeMode = 0; break;
                        case 4: mode4(); infoDone = 0; changeMode = 0; break;
                        default: break;
                    }
                }
            }
        }
        // close the connection:
        client.stop();
        Serial.println("client disonnected");
    }

}

/* Mode RED/BLUE (10 min. duration). */
void mode1() {
    for(int t = 0; t < 100; t++){
        for(int i = 0; i < 3; i++){
            fade('r',i,2);
            fade('b',i,2);
        }
    }
}

/* Mode GREEN/YELLOW (10 min. duration). */
void mode2() {
    for(int t = 0; t < 100; t++){
        for(int i = 0; i < 3; i++){
            fade('g',i,2);
            fade('y',i,2);
        }
    }
}

/* Mode RANDOM (10 to 20 min. duration). */
void mode3() {
    for(int t = 0; t < 1200; t++){
        byte rand0 = random(4); // Color: 0, 1, 2 or 3
        byte rand1 = random(3); // Num LED: 0, 1 or 2
        byte rand2 = random(1,3); // Time: 1 to 2
        switch(rand0){
            case 0:
                fade('r',rand1,rand2); break;
            case 1:
                fade('g',rand1,rand2); break;
            case 2:
                fade('b',rand1,rand2); break;
            case 3:
                fade('y',rand1,rand2); break;
        }
    }
}

/* Mode COLORS (30 min. duration). */
void mode4() {
    // (T = 1.2s, loop time = T*500 = 10 min.)
    for(int t = 0; t < 500; t++){
        for(int i = 0; i < 3; i++){
            digitalWrite(red[i], HIGH); delay(50);
            digitalWrite(red[i], LOW); delay(50);
            digitalWrite(green[i], HIGH); delay(50);
            digitalWrite(green[i], LOW); delay(50);
            digitalWrite(blue[i], HIGH); delay(50);
            digitalWrite(blue[i], LOW); delay(50);
            digitalWrite(yellow[i], HIGH); delay(50);
            digitalWrite(yellow[i], LOW); delay(50);
        }
    }
    // (T = 1.5s, loop time = T*400 = 10 min.)
    for(int t = 0; t < 400; t++){
        for(int i = 0; i < 3; i++){
            for(int j = 0; j <= 250; j++){
                analogWrite(red[i],j);
                analogWrite(green[i],j);
                analogWrite(blue[i],j);
                analogWrite(yellow[i],j);
                delay(1);
            }
            for(int j = 250; j >= 0; j--){
                analogWrite(red[i], j);
                analogWrite(green[i], j);
                analogWrite(blue[i], j);
                analogWrite(yellow[i], j);
                delay(1);
            } 
        }
    }
    // (T = 2.5s, loop time = T*240 = 10 min.)
    for(int t = 0; t < 240; t++){
        for(int j = 0; j <= 250; j++){
            analogWrite(red[0], j);
            analogWrite(red[1], j);
            analogWrite(red[2], j);
            delay(1);
        }
        for(int j = 250; j >= 0; j--){
            analogWrite(red[0], j);
            analogWrite(red[1], j);
            analogWrite(red[2], j);
            delay(1);
        }
        for(int j = 0; j <= 250; j++){
            analogWrite(green[0], j);
            analogWrite(green[1], j);
            analogWrite(green[2], j);
            delay(1);
        }
        for(int j = 250; j >= 0; j--){
            analogWrite(green[0], j);
            analogWrite(green[1], j);
            analogWrite(green[2], j);
            delay(1);
        }
        for(int j = 0; j <= 250; j++){
            analogWrite(blue[0], j);
            analogWrite(blue[1], j);
            analogWrite(blue[2], j);
            delay(1);
        }
        for(int j = 250; j >= 0; j--){
            analogWrite(blue[0], j);
            analogWrite(blue[1], j);
            analogWrite(blue[2], j);
            delay(1);
        }
        for(int j = 0; j <= 250; j++){
            analogWrite(yellow[0], j);
            analogWrite(yellow[1], j);
            analogWrite(yellow[2], j);
            delay(1);
        }
        for(int j = 250; j >= 0; j--){
            analogWrite(yellow[0], j);
            analogWrite(yellow[1], j);
            analogWrite(yellow[2], j);
            delay(1);
        }
        for(int j = 0; j <= 250; j++){
            analogWrite(red[0], j);
            analogWrite(red[1], j);
            analogWrite(red[2], j);
            analogWrite(green[0], j);
            analogWrite(green[1], j);
            analogWrite(green[2], j);
            analogWrite(blue[0], j);
            analogWrite(blue[1], j);
            analogWrite(blue[2], j);
            analogWrite(yellow[0], j);
            analogWrite(yellow[1], j);
            analogWrite(yellow[2], j);
            delay(1);
        }
        for(int j = 250; j >= 0; j--){
            analogWrite(red[0], j);
            analogWrite(red[1], j);
            analogWrite(red[2], j);
            analogWrite(green[0], j);
            analogWrite(green[1], j);
            analogWrite(green[2], j);
            analogWrite(blue[0], j);
            analogWrite(blue[1], j);
            analogWrite(blue[2], j);
            analogWrite(yellow[0], j);
            analogWrite(yellow[1], j);
            analogWrite(yellow[2], j);
            delay(1);
        }
    }
}

/* Creates a fading effect (analogWrite, from 0 to 250)
   at the LED specified (color, number, time), for
   example: fade('r', 0, 5); fades red LED number 0 (of 2),
   with 5ms between analog changes.
*/
void fade(char color, byte num, byte t) {
    
    for(int i = 0; i <= 250; i++){
        if(color == 'r'){ analogWrite(red[num], i); }
        else if(color == 'g'){ analogWrite(green[num], i); }
        else if(color == 'b'){ analogWrite(blue[num], i); }
        else if(color == 'y'){ analogWrite(yellow[num], i); }
        delay(t);
    }
    for(int i = 250; i >= 0; i--){
        if(color == 'r'){ analogWrite(red[num], i); }
        else if(color == 'g'){ analogWrite(green[num], i); }
        else if(color == 'b'){ analogWrite(blue[num], i); }
        else if(color == 'y'){ analogWrite(yellow[num], i); }
        delay(t);
    } 
}

/* Prints WiFi SSID where we connected and the local
   IP adress where we can control the LED's.
*/
void printIPAdress() {
    // print the SSID of the network you're attached to:
    Serial.print("SSID: ");
    Serial.println(WiFi.SSID());
    // print your MKR1000 WiFi IP address:
    IPAddress ip = WiFi.localIP();
    Serial.print("IP Address: ");
    Serial.println(ip);
    // IP adress:
    Serial.print("Go to to http://");
    Serial.println(ip);
    Serial.print(" to start straw tree lights!");
}

Comments

Similar projects you might like

Happy birthday melody on Arduino Nano with 3-way polyphony

Project tutorial by Liss

  • 1,453 views
  • 6 comments
  • 21 respects

Easiest Way to Add A Full Color LCD Display

by Ushijima

  • 4,213 views
  • 2 comments
  • 5 respects

Kaleidoscope Infinity Mirror

Project tutorial by Lucas Ainsworth

  • 3,070 views
  • 0 comments
  • 29 respects

Pet Feeder

by Namsulee

  • 827 views
  • 0 comments
  • 5 respects
Add projectSign up / Login