Fun with ESP, WS2812 and Homewizard

Fun with ESP, WS2812 and Homewizard

Well, I managed to get the ESP8266 working with the WS2812 in the Arduino IDE and it is time for some fun in combination with my Homewizard.

What I wanted to accomplish is this: I have solar panels at home and I have connected these to my Homewizard (a domotica appliance) along with the power meters which means my Homewizard knows about my power usage and my solar power production. What I wanted to do is have a small WS2812 ring show my usage and my production simultaneously. I defined usage as being the ‘red’ color and solar production as ‘yellow’. I want to show the production at the same time as the usage so I thought I would define each led to be the equivalent of 250 W power. I would ‘plot’ both the production and the usage on the circle starting at the same point. The overlap would be orange and excess solar power would be yellow and excess usage would be red, so if the circle showed 3 orange leds and 3 yellow, it meant I was producing 1500W (3+3 times 250W) while at the same time using 750W (3 times 250W). If the circle would show 3 orange and 3 red, it would mean 750W production and 1500W usage. After attempt 1 I found out that it was possible to use more than the LEDs would allow (ok, has not happened yet, but theoratically it is possible so I decided to add overflow. If production or usage would be over 3000W (12 times 250W), any excess would result in blue leds at the beginning, symbolizing double ‘value’ LEDs.

Still with me so far? After implementing, I found out that during Autumn, which is now when I created this project, production is not that high and my usage is usually also not that high, so often only 2 or 3 LEDs would light up. What I needed was increased resolution in such cases. I know, way too complex but he, it was meant to be a fun project. So I introduced green LEDs at the beginning. One green LED meant the resolution of the remaining 11 LEDs was 125W and two green LEDs mean the resolution of the remaining 10 LEDs was 50W.

The code will probably not be something you want to use without modifying but it might help you get some ideas on how to play with the WS2812. The code for getting the solar production and usage might be useful to others with a Homewizard.

github-mark-32px Available on GitHub with more comment in the code. Direct download.

Let’s look at the code:

#include <Adafruit_NeoPixel.h>
#include <ESP8266WiFi.h>
#include <PAM_WiFiConnect.h>
#include <PAM_WiFiClient.h>

#define CIRCLEPIN 2
#define PIXELCOUNT 12
#define POWERPERLED1 250
#define POWERPERLED2 125
#define POWERPERLED3 50

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(PIXELCOUNT,CIRCLEPIN,
  NEO_GRB+NEO_KHZ800);

int solarPower = 0;
int powerConsumption = 0;
float solarPowerDay = 0;
float powerConsumptionDay = 0;

void setup() {
  Serial.begin(115200);
  wifiConnect("YourSSID","YourPassword");
  pixels.begin();
  for(byte i=0;i<PIXELCOUNT;i++){
    pixels.setPixelColor(i, pixels.Color(0,0,0));
  }
  pixels.show();
}

void readSolar () {
  String t = getURL("YourHomewizardUrl","/YourHWPassword/get-status",80);
  t = t.substring(t.indexOf("energylinks"));
  t = t.substring(t.indexOf("s1"));
  t = t.substring(t.indexOf("po")+4);
  int xsolarPower = t.substring(0,t.indexOf(",")).toInt();
  t = t.substring(t.indexOf("dayTotal")+10);
  int xsolarPowerDay = t.substring(0,t.indexOf(",")).toFloat()*1000;
  t = t.substring(t.indexOf("used"));
  t = t.substring(t.indexOf("po")+4);
  int xpowerConsumption = t.substring(0,t.indexOf(",")).toInt();
  t = t.substring(t.indexOf("dayTotal")+10);
  int xpowerConsumptionDay = t.substring(0,t.indexOf(",")).toFloat()*1000;
  t = t.substring(0,t.indexOf("heatlinks"));
  Serial.print("Solar       now :");
  Serial.println(solarPower);
  Serial.print("Consumption now :");
  Serial.println(powerConsumption);
  Serial.print("Solar       day :");
  Serial.println(solarPowerDay);
  Serial.print("Consumption day :");
  Serial.println(powerConsumptionDay);
  Serial.println();
  if (xsolarPower!=0 || xpowerConsumption!=0) {
    solarPower = xsolarPower;
    solarPowerDay = xsolarPowerDay;
    powerConsumption = xpowerConsumption;
    powerConsumptionDay = xpowerConsumptionDay;
  }
}

void loop() {
  readSolar();

  byte solarLed;
  byte powerLed;
  byte base;
  if (_max(solarPower,powerConsumption)<=POWERPERLED3*(PIXELCOUNT-2)) {
    solarLed = round((solarPower+POWERPERLED3/2)/POWERPERLED3)+4;
    powerLed = round((powerConsumption+POWERPERLED3/2)/POWERPERLED3)+4;
    base = 2;
    for (byte i=0;i<base;i++) {
      pixels.setPixelColor(i,pixels.Color(0,42,0));
    }
  } else if (_max(solarPower,powerConsumption)<=POWERPERLED2*(PIXELCOUNT-1)) {
    solarLed = round((solarPower+POWERPERLED2/2)/POWERPERLED2)+2;
    powerLed = round((powerConsumption+POWERPERLED2/2)/POWERPERLED2)+2;
    base = 1;
    pixels.setPixelColor(0,pixels.Color(0,42,0));
  } else {
    solarLed = round((solarPower+POWERPERLED1/2)/POWERPERLED1);
    powerLed = round((powerConsumption+POWERPERLED1/2)/POWERPERLED1);
    base = 0;
    if (solarLed>PIXELCOUNT || powerLed>PIXELCOUNT) {
      base = _max(solarLed,powerLed)-PIXELCOUNT;
      for (byte i=0;i<base;i++) {
        pixels.setPixelColor(i,pixels.Color(0,0,42));
      }
    }
  }
  for (byte i=base;i<_min(solarLed,powerLed)-base;i++) {
    pixels.setPixelColor(i,pixels.Color(110,27,0));
  }
  if (powerLed>solarLed) {
    for (byte i=_max(base,_min(solarLed,powerLed)-base);i<powerLed-base;i++) {
      pixels.setPixelColor(i,pixels.Color(55,0,0));
    }
    for (byte i=powerLed-base;i<PIXELCOUNT;i++) {
      pixels.setPixelColor(i,pixels.Color(0,0,0));
    }
  } else {
    for (byte i=_max(base,_min(solarLed,powerLed)-base);i<solarLed-base;i++) {
      pixels.setPixelColor(i,pixels.Color(55,42,0));
    }
    for (byte i=solarLed-base;i<PIXELCOUNT;i++) {
      pixels.setPixelColor(i,pixels.Color(0,0,0));
    }
  }
  pixels.show();
  delay(500);
}

Ok, maybe way to much code to just dump here but it’s not that difficult to read.

Let’s start with the includes; NeoPixel library from AdaFruit, the standard ESP8266WiFi library and my own two libraries, PAM_WiFiConnect and PAM_WiFiClient. Next we define our constants and initalize the NeoPixel library.

The setup function is straight forward, set up Serial, connect to wifi and set all pixels to black.

The readSolar function connects to the Homewizard and gets the status information. This json file is than parsed a couple of times to get the current solar power production in solarPower, the days solar power production solarPowerDay, the current power consumption, powerConsumption and finally the power consumption of the day, powerConsumptionDay. Both day values are not used in this sketch. I intend to make some kind of switches where you can choose to see the current production/consumption or the totals of the day.

The loop function is where the number of leds and color is determined. The first section, the extensive if statement, determines which value to assign to each led, 250W, 125W or 5oW. This is done by checking the maximum of the values of solarPower and powerConsumption. If the maximum is small enough to fit within the 50W scale that is used, if not it is checked whether it will fit in the 125W scale and else it will be put in the 250W scale. If it is 50W, the first 2 leds are made green (signifying a change from the default scale) and 125W shows 1 green led.

Next the color of the remaining leds is determined by checking the maximum (to see if blue leds are needed) and than counting how many should be red (power usage), yellow (power production) or orange (production and usage).

As mentioned before, you probably cannot use the supplied code straight ‘out of the box’ but you can use it for ideas.

The end result of my solar meter in a small plastic box:

ws2812funa

At the bottom left, a USB to serial adapter. In the bottom middle a ESP-12E on a small breakout board. At the middle left a reed contact which allows for an update to the code by holding a magnet near the back of the box and finally the 12 bit neopixel circle.

When the box is closed, there is a normal piece of paper at the top abive the lights so that they are not too bright and slightly diffused which gives this end result:

ws2812funb

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s