Christmas Tree

Christmas Tree App

Welcome back all visitors. My last post was written more than year ago. From that time in Weather Station project I made few improvements but this is not so important and I will write about it in other post in the future.

Now I would like to focus on my new project. It began almost year ago. My wife saw short movie about Christmas Tree application on mobile phone which allows you colorize your Christmas Tree as you wish. Each light can lights on different color. She said to me I wish to have such solution next Christmas (these in 2021). I accepted the challenge. First of all I thought about buying something, but the out of the box solutions was expensive and has software limitations, so I decided to do it by myself.

I made some research what kind of elements I need, what kind of lights are available, what kind of elements I have in my workshop. After few days I decided to use

  • LED RGB string 12V which I bought in Allegro (the main advantage of these lights was cable color which is green).
  • Nodemcu v3
  • step-down converter
  • charger 12V 100W (because I planed to use 4 string of lights = 200 LED)

The price of that equipment was lower from the available solutions found in the Internet for about 30% – 40%. So this was quiet good start but I didn’t have the heart of that project – software.

Assumptions

As I mentioned above the primary goal of that project is possibility to colorize the Christmas Tree, but after a short time of thinking I planed to add:

  • possibility to use effects (blinking, fade in/out, etc.)
  • possibility to control via mobile phone (native application)
  • possibility to upgrade (via WWW if we talk about microcontroller)
  • possibility to save and load some settings, templates (on microcontroller site)

And that is all, but maybe it is too much? On that time I said “I can manage”, and I started…

How to build application?

Application? We should rather say applications – one on microcontroller to control lights, and UI application to create user interface.

Microcontroller

The hart of this part of whole application is Nodemcu v3. I wrote code using Arduino IDE and C++ language. Unfortunately I quickly discovered that this IDE is not good for such project and I switch to Visual Studio Code, which has better support for coloring, jump between classes, functions and interfaces, I said “Uff… Now I can really create lines of code”.

This part of application should to be responsible for controlling lights and listen on some simple HTTP request using simple Web server.

Desktop/Mobile application

The other part of application was responsible for create user interface. As possible you know from my previous posts that I’m a big enthusiast of Angular framework, so decision was very simple – Angular. I would like to use also NativeScriptwith Angular and create in the same time desktop and native mobile application. Unfortunately this plan was failed. I was not have time and possibilities to create these two apps. I stay with concept of WWW page, which can be displayed on multiple devices. There was another problem with such approach, where should I host such web? First of all I thought about docker container (and such idea was solution over most time). Then I found that I can put my compiled UI app on my Nodemcu WWW server (that way it works now).

Challenges

As we know how the architecture looks like, now it is time to describe few basic problems that I have defeted during whole project

Reflecting the lights in the app

The hardest problem in whole project was how to reflects lights from the tree to mobile or desktop 2D UI application and then how to convert it to Adafriut Neopixel library, which was the API to control lights.

After few days of thinking and discussions with my friends I found some solutions which sounds optimistic.

We made such assumption that we start put lights on the tree from the bottom and using clock direction we are going to the top. After that we need to configure our tree. Let’s imagine virtual line which connects first and last light. Then we start to turn on lights from the bottom to the top one by one. If we cross the virtual line we can assume that we turn on a circle of the light (if you look from the top of the tree).

Split tree to segments
Split tree to ranges

For being more specific I will call that circles as ranges. Now we assume that lights are evenly distributed so I split each range of lights on two halves and know I have such tree with light as on below image (here are a lot of lights, but I am pretty sure that you know how it is placed).

Lights on the tree
Lights on the tree

As you can see now we have only read color of each light counting from the bottom to top and send to microcontroller which should turn on it. Simple? Really?

Communication ESP8266 <-> UI

Communication between UI and ESP8266 could be done in different ways but I decided to use simple REST API which use JSON format of data. This decision was obvious and simple because Angular and Nodemcu can manage it very well. During creating finally solutions I create data structure and API which works correctly on one string with 50 lights. Unfortunately when I connected 4 strings together the API and data structure didn’t work. It is occurred that size of data for 200 lights is too much for ESP8266 and the program was crashed. The ArduinoJson object in application was too big and wanted to use more memory that it was available. In that case I need to make JSON file a bit less. I changed the structure from:

[
  {
    "index": 0,
    "color": {
      "r": 255,
      "g": 255,
      "b": 255,
    }
  },
  ...,
  {
    "index": 199,
    "color": {
      "r": 255,
      "g": 255,
      "b": 255,
    }
  },
]

to:

[
  {
    "i": 0,
    "c": "#FFFFFF"
  },
  ...,
  {
    "i": 199,
    "c": "#FFFFFF"
  },
]

and everything started working perfectlly.

But this was not my last problem. I realized that if I made few API requests in a row the program is crashed once again. I figure out that I the program created multiple ArduinoJson objects and did not destroy them. This cause memory leak and program crash. In that case I create global object to parse and create JSON objects and I passed it to all necessary places as reference. This approach solves the problem.

Synchronicity vs Asynchronicity

Generally in case of Arduino or ESP8266 we have infinity loop as a main program. Taking this rule in my mind I started to write a code. I added library responsible for hosting web server I create proper listeners and after few weeks I was able to colorize my small tree, save current colors or read saved data. Amazing… Now it is time for effects. I decided to start from to basic:

  • default – display static colors = no effects
  • blink – blinking lights (0,5 second the lights are on and then 0.5 second lights are off then we repeat it in an infinity loop)

In that place next problem was revealed. When we switch from “default” to “blink” via some REST API the web listener run infinity loop with “blink” effect and not finished request. The response does not return to the browser. We have error in our UI and the microcontroller could not handle any new request because it didn’t finish previous one. Hmm… how to solve it? Is it possible? After few minutes of thinking I realized that it should be possible because in similar way works WLED application. I started to searching the web and I found solution – asynchronous web server – ESPAsyncWebServer library which allows to setup asynchronous HTTP request listener in setup function. I said “Wow, amazing”. After short period of time I had all listeners rewritten to using new library. This approach has one difference to previously solution – parsing body payload. In first approach it was one call to parse whole body, here it is made in the loop which splits body to some chains and parse it one by one. I had to add some logic which connect allparts into one data. It was not so easy but I could manage. (details of this solution I described in future posts, when I published my code on GitHub, now it needs a bit clean) .

How to serve UI?

As I mentioned previously I thought to serve my UI via docker container run on my Raspberry Pi or creating a plugin to my Home Assistant instance. Every of that solutions need to use some agent which will be responsible for delivering it. Such concept could have huge problems with debugging if something not works correctly. So I started to thing if I can use my WWW server hosted on ESP8266. If you know it is possible and I think easy to do (now I’m so smart but few weeks ago I wasn’t :)). Below you can see few screenshots from the UI.

Update

The last problem to solve is – updating. Generally it is easy to do via USB cable, but when the whole project will be delivered to the production – Christmas Tree I could not imagine situation to disconnect it, update and connect again. I need to that via some WWW upload. I could not believe that such solution is so easy. The only think I had to do was download library AsyncElegantOTA and add two lines of code and I was able to upload new binary file or event my static UI filesystem data. Thanks to the authors of that library – incredible work.

Is it all worth to do that?

I think most of you can ask “Is it worth”. I definitely answer YES and I try in few words explain it:

  • economy – on whole project I spend less money than I would spent buying ready solution on the market, I think I save 300PLN, but I spend a lot of additional time
  • learning – I put to myself a huge requirements, do I manage? I think yes, I made MVP, I learned a lot about writing a code for devices like ESP8266 wher you have limited flash memory and RAM, it was very big challenge for me, fighting about each bite of code
  • joy – I think this is most important thing, I enjoy every line of code almost like a child when gets the first box of LEGO bricks, I’m proud of myself that I create “something” which will be with me every year

As a summary I presented video that shows few of all features of my project.

What next?

Next… now I need a rest and time to think. Consider what I did, what should I optimized and publish the code on GitHub. Then I will think about new effects and obviously about native mobile application which I can not done yet. The time shows if I can manage. I f you have some ideas or concepts of effects or any othe suggestions do not hesitate to put some comments or write an email to me.

Christmas Tree
Scroll to top