Blynk-ing an ANAVI Light Controller

The ANAVI Light Controller is an open source hardware WiFi development board. As the name suggests it controls 12V RGB LED strip lights and can retrieve data from various I2C sensor modules for temperature, humidity, light and gestures. In this application, I am not using any of these sensors, however, in the future I do intend to experiment with an APDS-9960, primarily for gesture detection.

I want to incorporate LED strip lighting into my existing home automation project. This project is primarily controlled via a Blynk application on my android phone. In this demonstration project, the Blynk application requires 4 slider widgets- one each for the R, G, B colors and an additional one for controlling overall brightness of the LEDs. An additional button widget can be added to provide instant on/off capability and a timer widget could be used for scheduled operation. I further use the functionality of the button to incorporate Alexa voice commands. Use of the timer widget option is not discussed here.

At the heart of the ANAVI Light Controller is an ESP8266-12E. The ESP8266 programming pins are exposed, so the ANAVI board can easily be re-flashed. GPIO0 of ESP8266 is connected to the button called SW1 allowing effortless entry into the programming mode. Furthermore, there is a small red indication LED marked as D1 which could be used for various purposes. In my application, I use this red LED to signal completion of device setup. In order to flash new firmware on ANAVI Light Controller you need a USB to UART serial debug cable and a 12V power supply. Full instruction for re-flashing can be found here.

My replacement firmware code is below. For this project I utilized the PlatformIO IDE with Visual Studio Code, however the Arduino IDE development environment could also be used. In my application, the Alexa voice commands simply allow turning all of the LEDS on and off and is not used for color selection. Also, please note my choice of Blynk virtual pin numbers is purely arbitrary. Good luck.

/*************************************************************************
 * Title: Simple ESP-8266 Wifi RGB LED Strip Light Controller
 * File: main.cpp (esp8266_anavi_rgb_led_controller.ino)
 * Author: James Eli
 * Date: 4/19/2019
 *
 * Program controls an RGB LED strip light via ANAVI light controller device. 
 *
 *************************************************************************
 * 4/19/2019: Migrated to platformio. JME
 *************************************************************************/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <WiFiManager.h> 
#include <ESP8266WebServer.h>
#include <BlynkSimpleEsp8266.h>
#include <WiFiUdp.h>
#include <SimpleTimer.h>
#include "WemoSwitch.h"
#include "WemoManager.h"
#include "CallbackFunction.h"
#include <ArduinoOTA.h>

// Blynk App authentication token, wifi ssid and password.
char auth[] = "...";
char ssid[] = "...";
char pass[] = "...";

// Amazon echo response term & Wifi access point name.
#define ECHO_KEY_WORD "cabinets"

// Maximum brightness.
#define MAX_BRIGHTNESS 255

// Esp8266 pins.
const int ESP8266_RED_PIN   = 12;
const int ESP8266_GREEN_PIN = 13;
const int ESP8266_BLUE_PIN  = 14;
const int ALARM_PIN = 16;
// Blynk virtual pin vs. anavi hw pin assignments.
// Red   = Blynk virtual pin V30 = anavi pin 12
// Green = Blynk virtual pin V31 = anavi pin 13
// Blue  = Blynk virtual pin V32 = anavi pin 14
// V29 = BUTTON
// RGB slider values (0-255).
int red, green, blue;
// Brightness slider (0-255).
int brightness;
// Button status.
int button;
// Connect resync flag.
bool isFirstConnect = true;

WemoManager wemoManager;
WemoSwitch *device = NULL;

void otaStarted() { Serial.println("OTA update started!"); }
void otaFinished() { Serial.println("OTA update finished!"); }
void otaProgress(unsigned int progress, unsigned int total) { Serial.printf("OTA progress: %u%%\r", (progress / (total / 100))); }
void otaError(ota_error_t error) {
    Serial.printf("Error [%u]: ", error);
    switch (error) {
        case OTA_AUTH_ERROR:
            Serial.println("auth failed!");
            break;
        case OTA_BEGIN_ERROR:
            Serial.println("begin failed!");
            break;
        case OTA_CONNECT_ERROR:
            Serial.println("connect failed!");
            break;
        case OTA_RECEIVE_ERROR:
            Serial.println("receive failed!");
            break;
        case OTA_END_ERROR:
            Serial.println("end failed!");
            break;
    }
}

// Turn all LED lines off.
void LEDsOff() 
{
  analogWrite(ESP8266_RED_PIN, 0);
  analogWrite(ESP8266_GREEN_PIN, 0);
  analogWrite(ESP8266_BLUE_PIN, 0);
}

// Turn LEDS on.
void LEDsOn() 
{
  analogWrite(ESP8266_RED_PIN, (red*brightness)/MAX_BRIGHTNESS);
  analogWrite(ESP8266_GREEN_PIN, (green*brightness)/MAX_BRIGHTNESS);
  analogWrite(ESP8266_BLUE_PIN, (blue*brightness)/MAX_BRIGHTNESS);
}

void setup() 
{
  // LED.
  pinMode(ALARM_PIN, OUTPUT);
  digitalWrite(ALARM_PIN, HIGH);

  // WiFiManager intialization.
  WiFiManager wifi;               

  // Init pins.
  pinMode( ESP8266_RED_PIN, OUTPUT );
  pinMode( ESP8266_GREEN_PIN, OUTPUT );
  pinMode( ESP8266_BLUE_PIN, OUTPUT );

  // Set ota details.
  ArduinoOTA.onStart(otaStarted);
  ArduinoOTA.onEnd(otaFinished);
  ArduinoOTA.onProgress(otaProgress);
  ArduinoOTA.onError(otaError);
  ArduinoOTA.setHostname("cabinets");
  ArduinoOTA.begin();

  // Create AP, if necessary
  wifi.autoConnect( ECHO_KEY_WORD ); 
  // wemoManager used for alexa interface.
  wemoManager.begin();

  // Set WIFI module to STA mode
  WiFi.mode( WIFI_STA );

  // Format: Alexa invocation name, local port no, on callback, off callback
  device = new WemoSwitch( ECHO_KEY_WORD, 80, LEDsOn, LEDsOff );
  wemoManager.addDevice( *device );

  // Report success.
  digitalWrite(ALARM_PIN, LOW);

  // Initialize Blynk.
  Blynk.config( auth );
}

void loop() 
{
  wemoManager.serverLoop();
  ArduinoOTA.handle();
  Blynk.run();
}

void syncPins()
{
  LEDsOn();

  if (red || green || blue || brightness)
  { 
    Blynk.virtualWrite(V29, 1);
    button = 1;
  }
  else 
  {
    Blynk.virtualWrite(V29, 0);
    button = 0;
  }
}

// Read value from r, g, b and brightness sliders.
BLYNK_WRITE(V30) { red = param.asInt();  syncPins(); }
BLYNK_WRITE(V31) { green = param.asInt(); syncPins(); }
BLYNK_WRITE(V32) { blue = param.asInt(); syncPins(); }
BLYNK_WRITE(V33) { brightness = param.asInt(); syncPins(); }

// Button.
BLYNK_WRITE(V29)
{
    button = param.asInt();
    
    if (button == 0) 
      LEDsOff();
    else if (red || green || blue || brightness)
      LEDsOn();
    else 
    {
      Blynk.virtualWrite(V29, 0);
      button = 0;
    }  
}

BLYNK_CONNECTED()
{
  if (isFirstConnect)
  {
    Blynk.syncAll();
    isFirstConnect = false;
  }
}
Advertisements

About Jim Eli

µC experimenter
This entry was posted in arduino, iot and tagged , , , . Bookmark the permalink.

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