Optimized for Arduino Nano R3 (ATmega328P)
I made this project to make use of an old 8 channels relay board with a single Arduino Nano and a really low cost ESP-01 module... π The goal is to control my garden irrigation, lights, etc, using home assistant with MQTT protocol (e.g., mosquitto broker) or autonomous with some "standalone" intelligence on Arduino Nano. Sure you can use a plain Arduino relay module instead π (with any number of channels, with maximum of 8)...
- works with home assistant to control garden watering and more 7 switches (MQTT), lights, etc
- alternatively, works autonomous with up to 50 programmable timers (using real time clock - optional, see config flags)
- soil moisture sensor to (avoids watering when the soil is wet - optional, see config flags)
- watering watchdog (prevents watering for long time... π° - optional, see config flags)
- turn on/off watering with local push button (optional, see config flags)
However, Arduino Nano is not easy integrated with Wifi (I could have used a NodeMCU instead, but I already got this Nano and plain ESP-01 module... And after all, what's the fun? π€ͺ kkk).
To solve this issue, I made a sketch apart to be flashed on the ESP8266-01 module (esp8266-01.ino) (using board "Generic ESP8266 Module"). The ESP-01 should communicate with Home Assistant using MQTT and act as bridge (like "man-in-the-middle") to Arduino Nano using plain serial communication.
Therefore, to use serial communication on this sketch to debug with "Serial Monitor" set the flag macro "DEBUG_MODE true", otherwise the serial communication is intended to ESP-01 module itself.
Drivers (CH340g) for both Arduino Nano and ESP-01:
- CH340g USB/Serial driver (windows 11 compatible driver)
- driver install instructions (pt-BR)
- flashing ESP-01 tutorial (pt-BR)
REMARK: this sketch should be pushed into an Arduino Nano board using the ATmega328P processor at Arduino IDE:
- Board: "Arduino Nano"
- Processor: "ATmega328P (Old Bootloader)"
Use these configurations flags to set gardeino behaviour (as you wish). You can avoid dispensable hardware and features to fit your needs...
macro | default | description |
---|---|---|
RELAY_SIZE | 8 | number of relays (valid: 1 to 8) |
USE_RELAY_TIMERS | true | true to use timers, false otherwise - dont need the RTC |
MAX_NUMBER_OF_TIMERS | 50 | maximum number of standalone timers (valid: 3 to 200) |
USE_MOISTURE_SENSOR | true | true to use moisture sensor, false otherwise - dont need the moisture sensor |
SOIL_WET | 450 | defines max soil conductivity value we consider soil "wet" (valid: 0 to 1023) |
SOIL_DRY | 750 | defines min soil conductivity value we consider soil "dry" (valid: 0 to 1023) |
USE_WATERING_BUTTON | true | true to use push button, false otherwise - dont need the push button |
USE_WATERING_WATCHDOG | true | true to set a watering time limit, false otherwise |
WATERING_WATCHDOG_INTERVAL | 300000 | watering time limit (milisseconds) |
BAUD_RATE | 9600 | serial communication speed with ESP-01 (adjust both sketches) |
DEBUG_MODE | false | true to debug on serial monitor (debug), false to communicate with ESP-01 (prod) |
- Arduino Nano R3 (ATmega328P)
- Wifi Module ESP8266-01 (ESP-01)
- ESP8266 USB serial adapter CH340g (see next session)
- Logic Level Converter (LLC) 5v-3.3v (bi-directional) (see note)
- Real Time Clock (RTC) DS3231 (optional: uses for standalone timers support, see config flags)
- solenoid valve 3/4" 110 v (normally closed)
- relay module 5v 8-ch (optional: less than 8 channels can be used, see config flags)
- soil moisture sensor (optional: avoids watering when the soil is wet, see config flags)
- push button and 10 k ohms resistor (optional: turn on/off watering, see config flags)
- power supply 5vdc (1A)
The ESP-01 module should be programed with the sketch (esp8266-01.ino), using ESP8266 USB serial adapter CH340g as show bellow:
One "detail" is that this USB/serial adapter can connect ESP-01 to USB (Arduino IDE), but CAN'T flash it π΅. In order to program the ESP-01, a small modification is needed: add a push button over GPIO and GND pins π.
In order to write the code, press the button when connecting the USB Adapter to your computer's USB port π€.
See more details in this flashing ESP-01 tutorial (pt-BR)
- circuito.io (step by step)
- Arduino Nano pin29 (GND) --> power supply 5vdc (negative/Gnd)
- Arduino Nano pin27 (Vin) --> power supply 5vdc (positive/Vcc)
- Arduino Nano pin27 (Vin) --> power supply 5vdc (positive/Vcc)
- RTC DS3231 pin1 (GND) --> Arduino Nano pin29 (GND)
- RTC DS3231 pin4 (SCL) --> Arduino Nano pin (A5)
- RTC DS3231 pin3 (SDA) --> Arduino Nano pin (A4)
- RTC DS3231 pin2 (VCC) --> Arduino Nano pin17 (3.3v)
- ESP8266-01 pin8 (RXD) --> LLC pin1 (LV1)
- ESP8266-01 pin1 (TXD) --> LLC pin2 (LV2)
- ESP8266-01 pin7 (VCC) --> Arduino Nano pin17 (3.3v)
- ESP8266-01 pin2 (GND) --> Arduino Nano pin29 (GND)
- ESP8266-01 pin3 (CH_PD) --> Arduino Nano pin17 (3.3v)
- LLC pin3 (LV) --> Arduino Nano pin17 (3.3v)
- LLC pin3 (GND) --> Arduino Nano pin29 (GND)
- LLC pin11 (HV2) --> Arduino Nano pin13 (D10)
- LLC pin12 (HV1) --> Arduino Nano pin14 (D11)
- LLC pin12 (HV) --> Arduino Nano pin27 (5v)
- Relay 8 ch (VCC) --> Arduino Nano pin27 (5v)
- Relay 8 ch (GND) --> Arduino Nano pin29 (GND)
- Relay 8 ch (D0) --> Arduino Nano pin7 (D4)
- Relay 8 ch (D1) --> Arduino Nano pin8 (D5)
- Relay 8 ch (D2) --> Arduino Nano pin9 (D6)
- Relay 8 ch (D3) --> Arduino Nano pin10 (D7)
- Relay 8 ch (D4) --> Arduino Nano pin11 (D8)
- Relay 8 ch (D5) --> Arduino Nano pin12 (D9)
- Relay 8 ch (D6) --> Arduino Nano pin15 (D12)
- Relay 8 ch (D7) --> Arduino Nano pin16 (D13)
- Soil moisture sensor VIN (right) --> Arduino Nano pin6 (D3)
- Soil moisture sensor GND (center) --> Arduino Nano pin29 (GND)
- Soil moisture sensor SIG/A0 (left) --> Arduino Nano pin19 (A0)
- push button (term 1) --> Arduino Nano pin16 (D2 - interruption)
- push button (term 1) --> Arduino Nano pin27 (5v)
- push button (term 2) --> 10k olhms resistor (term 1)
- 10k olhms resistor (term 2) --> Arduino Nano pin29 (GND)
(connected pins: D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, A0, A4, A5)
-
gardenino/available: sensors availability ("online"/"offline")
-
gardenino/cmd: pushes commands to Arduino Nano (home assistant -> gardenino):
- "water on/off": turn on/off watering valve (i.e., relay 1)
- "relay 4 on/of": turn on/of relay by number (1-8)
- "reset": reset internal states
- "relays on/off": turn on/off all relays
- "enable/disable timers": enables/disables relay timers routine (avoid execution with out delete/update)
- "enable/disable timer: 04": disable timer by "id" (checks MQTT state topic for gets to "timer id")
- "add timer: relay hh mm hh mm": adds new relay timer (parameters: relay number, turn on hour, turn on minute, turn off hour, turn off minute)
- "update timer: id hh mm hh mm": updates relay timer by "id" (parameters: timer id, turn on hour, turn on minute, turn off hour, turn off minute)
- "delete timer: 04": delete timer by "id"
- "delete all timers": deletes all relay timers (warning: all timers will be erased!)
- "default timers": sets default relay timers (i.e. timers "factory reset", warning: all timers will be erased!)
-
gardenino/state: retrieves states as json (gardenino -> home assistant)
{ "moisture": 50, "timers_on": "on", "relays": { "water": "on", "relay 2": "off", "relay 3": "off", ... }, "timers": { "timer_01": { "id": 4, "enabled": "on", "relay": 1, "on": "12:20:00", "off": "15:30:00"} ... }, }
-
ha/datetime: (optional) creates a automation on home assistant in order to synchronize data & time π€
alias: MQTT date time sync description: "syncronize data & time on client MQTT devices" trigger: - platform: time_pattern minutes: /1 condition: [] action: - service: mqtt.publish data: qos: "0" retain: false topic: ha/datetime payload_template: "{{ now().timestamp() | timestamp_custom('%d %m %Y %H %M %S') }}" mode: single
This is a code detail just for documentation purposes
These are the codes send from ESP-01 to Arduino Nano (as single bytes) (mostly as response to MQTT topic gardenino/cmd):
code | minemonic | MQTT topic cmd | description |
---|---|---|---|
0x00 | NOP | not operation (NOP) | |
0x01 | CONNECTED | notifies Arduino that MQTT is connected (CONNECTED) | |
0x02 | DISCONNECTED | notifies that mqtt is disconnected (DISCONNECTED) | |
0x03 | SYNC | datetime synchronization (uses home assistant as "time server" - SYNC) | |
0x04 | CLEAR | clear | clears states (CLEAR / mqtt: "clear") |
0x05 | ALL_RELAYS_ON | relays on | turns on all relays (ALL_RELAYS_ON / mqtt: "relays on") |
0x06 | ALL_RELAYS_OFF | relays off | turns off all relays (ALL_RELAYS_OFF / mqtt: "relays off") |
0xA0 | turn on relay 1 (i.e., watering relay) | ||
0xA1 | turn on relay 2 | ||
0xA2 | turn on relay 3 | ||
0xA3 | turn on relay 4 | ||
0xA4 | turn on relay 5 | ||
0xA5 | turn on relay 6 | ||
0xA6 | turn on relay 7 | ||
0xA7 | turn on relay 8 | ||
0xB0 | turn off relay 1 (i.e., watering relay) | ||
0xB1 | turn off relay 2 | ||
0xB2 | turn off relay 3 | ||
0xB3 | turn off relay 4 | ||
0xB4 | turn off relay 5 | ||
0xB5 | turn off relay 6 | ||
0xB6 | turn off relay 7 | ||
0xB7 | turn off relay 8 | ||
0xC0 | ENABLE_TIMERS | enable timers | enables timers routine (ENABLE_TIMERS / mqtt: "enable timers") |
0xC1 | DISABLE_TIMERS | disable timers | enables timers routine (DISABLE_TIMERS / mqtt: "disable timers") |
0xC2 | ADD_TIMER | add timer | add new timer (ADD_TIMER / mqtt: "add timer: [relay] [hh] [mm] [hh] [mm]") |
0xC3 | ENABLE_TIMER | enable timer | enables timer by id (ENABLE_TIMER / mqtt: "enable timer: [id]") |
0xC4 | DISABLE_TIMER | disable timer | disables timer by id (DISABLE_TIMER / mqtt: "disable timer: [id]") |
0xC5 | DELETE_TIMER | delete timer | deletes timer by id (DELETE_TIMER / mqtt: "delete timer: [id]") |
0xC6 | DELETE_ALL_TIMERS | delete timers | deletes all timers (DELETE_ALL_TIMERS / mqtt: "delete timers") |
0xC7 | UPDATE_TIMER | update timer | updates timer by if (UPDATE_TIMER / mqtt: "update timer: [id] [hh] [mm] [hh] [mm]") |
0xC8 | SET_DEFAULT_TIMERS | default timers | sets default timers, i.e. "factory reset" (SET_DEFAULT_TIMERS / mqtt: "default timers") |
0xFE | START | token for message start (START) | |
0xFF | END | token for message end (END) |
These are the payloads send back from Arduino Nano to ESP-01 (mostly as response to MQTT topic gardenino/state):
- 1st byte: START token (START - 0xFE)
- 2nd byte: gardeino states
- bit 0 - timers enabled
- 3th byte: relay states:
- bit 0 - relay 1 state
- bit 1 - relay 2 state
- bit 2 - relay 3 state
- bit 3 - relay 4 state
- ...
- 4th byte: soil moisture in range [0-100] %
- 5th byte: number of timers (EEPROM)
- 6th byte: END token (END - 0xFF)
- next bytes (optional, for each active timer)
- timer id (bit 7 = enable/disabled) [00-49]
- relay number [01-08]
- start hour in range [00-23]
- start minute in range [00-59]
- end hour in range [00-23]
- end minute in range [00-59]
- "mem"
- "reset"
- "sync"
- "relay on/off"
- "relays on/off"
- "enable/disable timers"
- "enable/disable timer""
- "add timer"
- "update timer"
- "delete timer"
- "delete all timers"
- "default timers"
Logic Level Converter (LLC) 5v-3.3v is not required if you make voltage divider (5v to 3.3v) for the RX serial communication.
In order to do that, all you will need is a 1k ohms and a 2.2k ohms resistors, and make these circuit changes:
- 2.2k ohms resistor (terminal 1) --> Arduino Nano pin29 (GND)
- 2.2k ohms resistor (terminal 2) --> ESP8266-01 pin8 (RXD)
- 2.2k ohms resistor (terminal 2) --> 1k ohms resistor (terminal 1)
- 1k ohms resistor (terminal 1) --> Arduino Nano pin14 (D11)
Jorge Albuquerque (2022)