5 channel aquarium LED controller with web interface for ESP32 boards. Supports DS18B20, SSD1306, ILI9341, XPT2046 and SmartConfig. Arduino IDE.
Clone or download
CelliesProjects Changed mapFloat() to map() calls if the operands are int types.
Fixed mapping from touch to screen coordinates.
Latest commit 306f204 Jan 20, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
docs Update and rename READ_ME_256x256.txt to README.md May 17, 2018
webif Trying to set a channel name with illegal character(s) will return an… Jan 16, 2019
.gitignore Save compiled files in the temp folder. Jul 15, 2018
LICENSE Initial commit Aug 4, 2017
README.md Update README.md Jan 14, 2019
aquacontrol32.ino Update Adafruit_GFX.h to 1.3.6. Jan 18, 2019
compile.sh Arduino IDE to 1.8.8. Dec 28, 2018
compile_options.md Update compile_options.md Apr 17, 2018
devicePinSetup.h Split up the config defines. Apr 15, 2018
deviceSetup.h Added bool GIT_TAG to device setup. Jan 14, 2019
dimmertask.ino Put dimmerTask at top of file. Jan 12, 2019
flash.sh Arduino IDE to 1.8.8. Dec 28, 2018
libraries.md Update libraries.md Jan 14, 2019
loggertask.ino Keep all running tasks in RAM. Jun 25, 2018
mapFloat.h Put function 'mapFloat' in a header file. May 30, 2018
moonSimtask.ino Fixed mapping of minutes and seconds to decimal hour. Aug 2, 2018
ntptask.ino Increased moonSimtask stack size by 200 bytes Jan 15, 2019
oledtask.ino Keep all running tasks in RAM. Jun 25, 2018
temptask.ino More logging. Aug 2, 2018
tft_board_pins.md -Update docs. Jan 12, 2018
tfttask.ino Changed mapFloat() to map() calls if the operands are int types. Jan 20, 2019
threeDigitPercentage.ino Fixed percentage rounding. Jun 9, 2018
webservertask.ino Trying to set a channel name with illegal character(s) will return an… Jan 16, 2019
wifitask.ino Keep all running tasks in RAM. Jun 25, 2018



Aquacontrol32 is software used to program and control 5 led strips to create more natural sunrises and sunsets in your aquarium.

Aquacontrol32 is developed and tested on hardware based on a MH-ET LIVE MiniKit ESP32.

With some modifications and provided there are enough pins broken out, Aquacontrol32 should run on basically any ESP32 based board.

The minimum hardware would be a ESP32 board with at least 5 free output pins connected via 330R gate resistors to 5 NPN mosfets. I use IRLZ44N mosfets as these are cheap and have the right ratings for my setup.

You can connect a 128x64 I2C OLED and/or a ILI9341 SPI tft display to have some feedback on the display(s).
The ILI9341 displays optionally come with a XPT2046 touch controller which is supported.

Aquacontrol32 dimming down YouTube video



  • 5 channels led dimming (common anode) at 1.22kHz with 16 bit (65535 steps) resolution.

  • Lunar cycle night light.

  • 50 timers per channel.

  • Password protected web interface to control the device.
    See it in action at my fish and my salamanders tank.

  • Automatic NTP timekeeping.

  • Timezone support.

  • OneWire Maxim ( Dallas ) DS18B20 sensor support.

  • I2C 128x64 SSD1306 OLED support.

  • SPI 320x240 ILI9341 TFT support.

  • XPT2046 touchscreen support.

  • SPIFFS storage support.

  • Temperature logging on SPIFFS.

  • All device settings are saved in NVS.

  • Easily connect your controller to WiFi with the ESP8266 SmartConfig Android app.

  • Get a notification in the web interface if a new release is available.

You will need:

Aquacontrol32 can run happily with or without OLED or TFT display.

Compile notes:

  • Compare your #included libraries version numbers against libraries.md.

  • Check your device options in deviceSetup.h.

  • Toggle the GIT_TAG option in deviceSetup.h to enable or disable version information.
    Setting GIT_TAG to true makes that the Arduino IDE can no longer compile or flash your script.
    You then have to use the script compile.sh to verify your sketch and flash.sh to verify/upload the sketch to the controller.
    Read this blog post to see why I choose this method.

  • Source are compiled for mhetesp32minikit which has support for ESP_LOGX macros.
    This can be changed to a particular esp32 board by changing the --board option in the compile.sh and flash.sh scripts.
    Look in ~/Arduino/hardware/espressif/esp32/boards.txt to find the relevant board desciption.
    custom_DebugLevel should be set to esp32_none in the flash.sh script for production use.
    When you are still testing your hardware and setup, debug level can be set to anything depending on your needs.
    (esp32_info is probably what you need, esp32_verbose gives the most info)

  • Check your compile settings and used libraries.

  • If your controller has a problem after flashing (no Wifi or stuck/not properly booting) the most probable cause is corrupted NVS.
    Erasing the complete flash memory will solve most of these problems.
    Use this command to erase flash (SPIFFS INCLUDED!) in Linux:
    ~/Arduino/hardware/espressif/esp32/tools/esptool.py --port /dev/ttyUSB1 erase_flash
    Backup your default.aqu in the file manager before erasing and upload it after you flash your controller.

Connecting the hardware:

  • Check the Aquacontrol hardware GitHub repo.

  • Read the file on connecting a ILI9341 display. Pull-ups are not optional!

  • The ILI9341 boards from AliExpress, DealExtreme or any other supplier are not all equal.
    Among the tested boards I encountered some that have no MISO pin connected, so they can't respond to read commands.
    For these boards you can enable TFT_HAS_NO_MISO (set it to true) in deviceSetup.h.

  • Some ILI9341 boards have their touch coordinates inverted.
    For these boards you can enable TOUCH_IS_INVERTED (set it to true) in deviceSetup.h.

  • Don't forget to connect the tft LED to 3.3V. (default: GPIO PIN 2)
    To be on the safe side, I use a BC547 transistor (and a 330R resistor) between the ESP32 pin and the LED connector on the tft board.
    If you connect the LED directly to a ESP32 pin, connect it through a 330R resistor in series to prevent burning up your ESP32.

Lunar cycle night light:

When enabled, the settings for the minimum levels in the channel section of the webinterface become the full moon light value. Can be disabled in deviceSetup.h. (set it to false)

The lunar images used in the web interface are rendered by Jay Tanner and licenced under the Creative Commons Attribution-ShareAlike 3.0 license.

The moon phase library is adapted from code kindly licensed by Hugh from voidware.com. Thanks Hugh!


  • If your ESP32 has connected to your WiFi router before you flash Aquacontrol to your device, it will probably connect automagically .

  • If you try to connect to an unknown WiFi network or changed your WiFi router settings, Aquacontrol will fail to connect and start SmartConfig.
    If you have no oled or tft connected, the onboard led will blink at 1Hz to show you the device is in SmartConfig mode.
    You can then use the Espressif SmartConfig app or the ESP8266 SmartConfig Android app to setup your Aquacontrol WiFi connction.

  • If after 5 minutes SmartConfig has not connected your device will reboot. This way Aquacontrol32 will reconnect after a powerout when the modem is not yet online when Aquacontrol32 has booted the first time.

Log files:

By default log files are not generated.
Log files saved on SPIFFS could reduce the lifetime of the flash memory.
To log the temperature sensor values enable LOG_FILES (set it to true) in deviceSetup.h.

Known issues:

  1. Use the master branch from PaulStoffregen's XPT2046 Touchscreen library until the next release.
    ( Current release is 1.2, which does not have the IRAM fix.) See this issue.

  2. Use the stickbreaker OneWire library for troublefree temperature sensors.

The test hardware: