Artur Rzepka
Published © CC BY-NC

Aquarium LED WiFi Controller

Controlling two (or more) LED channels via WiFi to make sunrise, sunset and set night mode too!

IntermediateFull instructions provided2 hours5,814

Things used in this project

Software apps and online services

Arduino IDE
Arduino IDE
Adafruit IO

Story

Read more

Schematics

Circuit for 9 power LEDs (6 + 3)

Code

aqua wifi LED controller

C/C++
Code for NodeMCU v2
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

#define WLAN_SSID       "my_network" //write your wifi network name
#define WLAN_PASS       "password" //write your password to wifi

#define blue_name D3 //GPIO connected with driver for blue channel
#define white_name D1 //GPIO connected with driver for white channel

#define time_zone 1 //+1 hour

// Adafruit IO
#define AIO_SERVER      "io.adafruit.com"
#define AIO_SERVERPORT  1883
#define AIO_USERNAME    "name" //write your name from adafruit site
#define AIO_KEY         "key" //write your key from adafruit site

WiFiClient client;
 
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

Adafruit_MQTT_Publish blue_channel = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/blue_channel");
Adafruit_MQTT_Publish white_channel = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/white_channel");

Adafruit_MQTT_Subscribe max_blue_channel = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/max_blue_channel");
Adafruit_MQTT_Subscribe max_white_channel = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/max_white_channel");
Adafruit_MQTT_Subscribe start_time = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/start_time");
Adafruit_MQTT_Subscribe end_time = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/end_time");
Adafruit_MQTT_Subscribe duration = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/duration");
Adafruit_MQTT_Subscribe enable_auto = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/enable_auto");
Adafruit_MQTT_Subscribe timee = Adafruit_MQTT_Subscribe(&mqtt, "time/ISO-8601");

Adafruit_MQTT_Subscribe *subscription;

int i_max_blue_channel = 100; //initial value for blue channel driver (from 0 to 100)
int i_max_white_channel = 100; //initial value for white channel driver (from 0 to 100)

//standard of notation time: HHMMSS, where minutes and seconds are calculated as follows: minutes or seconds / 60 * 100
int i_start_time = 100000; //initial time value in project standard of notation
int i_end_time = 230000; //initial time value in project standard of notation
int i_duration = 80000; //initial time value in project standard of notation
int i_timee = 0; //current time, initial value in project standard of notation
bool b_button = true;

int last_blue_value = 0;
int last_white_value = 0;

void MQTT_connect();
void set_pwm(int blue_value, int white_value);
void button_true();
void read_subscription();


void setup() 
{ 
  //asset white and blue channel
	pinMode(white_name,OUTPUT);
	pinMode(blue_name,OUTPUT);

	//turn on built-in LED to show that ESP working
	pinMode(D0,OUTPUT);
	digitalWrite(D0, LOW);

  //waiting for WiFi connect
	WiFi.begin(WLAN_SSID, WLAN_PASS);
	while (WiFi.status() != WL_CONNECTED) 
	{
	delay(200);
	}

	// Setup MQTT subscription 
	mqtt.subscribe(&max_blue_channel);
	mqtt.subscribe(&max_white_channel);
	mqtt.subscribe(&start_time);
	mqtt.subscribe(&end_time);
	mqtt.subscribe(&duration);
	mqtt.subscribe(&enable_auto);
	mqtt.subscribe(&timee);
}

void loop() 
{
  MQTT_connect();
  

  while (subscription = mqtt.readSubscription(300)) //wait for data
  {
    read_subscription();
  }
  
  if (b_button == true) //automatic drive turn on
  {      
    button_true();
  }
  else if (b_button == false) //automatic drive turn off
  {
    set_pwm(i_max_blue_channel*10, i_max_white_channel*10);
  } 
} 


//insert logic for updating PWM value
void set_pwm(int blue_value, int white_value)
{ 
  if(blue_value != last_blue_value) //update PWM if different to last set value
  {
    analogWrite(blue_name, blue_value); 
    last_blue_value = blue_value;
  }

  if(white_value != last_white_value) //update PWM if different to last set value
  {
    analogWrite(white_name, white_value); 
    last_white_value = white_name;
  }
}


// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
  int8_t ret;

  // Stop if already connected.
  if (mqtt.connected()) {
    return;
  }

  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
       retries--;
       if (retries == 0) {
         // basically die and wait for WDT to reset me
         while (1);
       }
  }
}

void button_true()
{
  int floating = (i_end_time - i_start_time - i_duration) / 2; //calculating time of sunset/sunrise
    
  if(i_timee < i_start_time + floating && i_timee > i_start_time)
  {   
    if(i_timee - i_start_time < floating / 3)
    {
      int counter = (i_timee - i_start_time) / (floating / 3.0) * 1000.0;
      set_pwm((i_max_blue_channel*10) * (counter / 1000.0), 0);
    }
    else if(i_timee - i_start_time > 2 * floating / 3.0)
    {
      int counter = (i_timee - i_start_time - 2 * floating / 3.0) / (floating / 3.0) * 1000.0;
      set_pwm(i_max_blue_channel*10, (i_max_white_channel*10) * (counter / 1000.0));
    }
  }
  else if(i_timee > i_end_time - floating && i_timee < i_end_time)
  {
    if(i_end_time - i_timee > 2 * floating / 3.0)
    {
      int counter = (i_end_time - i_timee - 2 * floating / 3.0) / (floating / 3.0) * 1000.0;
      set_pwm(i_max_blue_channel*10, (i_max_white_channel*10) * (counter / 1000.0));
    }
    else if(i_end_time - i_timee < floating / 3)
    {
      int counter = (i_end_time - i_timee) / (floating / 3.0) * 1000.0;
      set_pwm((i_max_blue_channel*10) * (counter / 1000.0), 0);
    }
  }
  else if(i_timee < i_end_time && i_timee > i_start_time) //max light blue&white
  {
    set_pwm(i_max_blue_channel*10, i_max_white_channel*10);
  }
  else //night mode
  {
    set_pwm(3, 0);         
  }        
}

void read_subscription()
{
  if (subscription == &enable_auto) 
  { 
    if (strcmp((char *)enable_auto.lastread, "ON") == 0) 
    {
        b_button = true;
    }
    else if (strcmp((char *)enable_auto.lastread, "OFF") == 0) 
    {
        b_button = false;
    } 
  }

  if (subscription == &max_blue_channel) 
  {
    char *value = (char *)max_blue_channel.lastread;
    String message = String(value);
    message.trim();   
    i_max_blue_channel = message.toInt();
  }

  if (subscription == &max_white_channel) 
  {
      char *value = (char *)max_white_channel.lastread;
      String message = String(value);
      message.trim(); 
      i_max_white_channel = message.toInt();
  }

  if (subscription == &start_time) 
  {
      char *value = (char *)start_time.lastread;
      String message = String(value);
      message.trim(); 
      i_start_time = message.toInt()*10000; //fit hours to project standard
  }

  if (subscription == &end_time) 
  {
      char *value = (char *)end_time.lastread;
      String message = String(value);
      message.trim(); 
      i_end_time = message.toInt()*10000; //fit hours to project standard
  }

  if (subscription == &duration) 
  {
      char *value = (char *)duration.lastread;
      String message = String(value);
      message.trim(); 
      i_duration = message.toInt() * 10000; //fit hours to project standard
  }


  if (subscription == &timee) 
  {
      char *value = (char *)timee.lastread;
      String message = String(value);
      message.trim(); 
      String hour = message.substring(11,13);
      String minute = message.substring(14,16);
      String second = message.substring(17,19);
      i_timee = hour.toInt() * 10000 + time_zone * 10000 +  (minute.toInt() * 10000.0)/60.0 + (second.toInt() * 100.0)/60.0;
  }
}

Credits

Artur Rzepka

Artur Rzepka

2 projects • 1 follower

Comments