|
Home Assistant OS |
|
|
Esp Home Flasher |
|
|
Esp Home Home Assistant AddonEsp Home
|
|
|
arduino IDEArduino
|
Build your own IoT Controller
Design and Build an ESP8266 Based IoT Controller – Part 1
by makeriot2020
August 16, 2021
Update: 28/02/2023
I have recently uploaded new Gerber files for this project. I had to change the two push-buttons ( used for Flash and Reset, as the original parts were recently discontinued. The new Gerber files is just an update to accommodate the slightly different footprints of the new switches,
Update: 08/09/2021
I am pleased to announce that I have obtained permission from Nabu Casa and ESP Home, to use the "Made for ESPHome" Logo on this device. My thanks to Jesse and everyone else involved. ESPHome recently launched a "Made for ESPHome" project. You can find out more about that here-> https://esphome.io/guides/made_for_esphome.html
Please note that the Gerber files ( currently rev 1.7) has been updated to reflect this change.
OSHWA certification is now completed, with ID TH0008 being allocated to this project.
Table of contents
Introduction
My Requirements
My Solution
Expandability
Prototyping
–> Initial Software Installation
—–> Start Home Assistant
—–> Install ESPHome
—–> Flashing ESPHome
–> Designing the Hardware
—–> The Relay Driver Circuit(s)
——–> Relay Driver Schematic
——–> Status LED and User Input Schematic
——–> The USB to Serial Schematic
——–> The ESP-12E schematic with strapping pins, as well as the power supply circuit(s)
—–> Designing the PCB
——–> PCB Layout (Raw layers and Silkscreen, not Rendered)
——–> Top Layer
——–> Bottom Layer
——–> 3D Render ( Top Layer from left )
Introduction
The Internet of Things (IoT), as well as Home Automation, are steadily gaining popularity all the time. You can already buy quite a lot of commercial products or do your own D.I.Y implementation. Many different companies offer various devices and modules to help you do your project easily. But many of us will know that these modules always come with a lot of wires and connections, which can be very unreliable, and also unsightly to look at.
Most of these solutions are also relying on you placing some stuff on an electronics-breadboard, or strip-board for more permanent installations. You can also decide to design and manufacture your own custom PCB.
On the software side of this problem, there are many commercial and open-source solutions available, and most of them work with almost anything on the market (With various degrees of complexity and a varying learning curve).
My Requirement(s)
Having access to a few ( four to be exact ) Raspberry Pi Computers, as well as a huge number of ESP8266, ESP32, Arduino and STM32 Development boards that are lying around in my working area, as well as being quite lazy to do repetitive tasks, I have been playing with the idea for quite a while to automate some or maybe all of the lights in my house. I have also built quite a few device prototypes, only to tear them down again after testing them.
The reason for this, and this is only my own opinion, is that an electronics breadboard is meant for prototyping only.
They are not reliable in the long term, and they look extremely messy. Using a certain development board, and connecting all of the supporting components and modules to it, also leaves quite a mess. So,
1) The project must be contained on a single PCB.
2) It must have WiFi and or Bluetooth support (ESP8266 does not have this [ Bluetooth ])
3) It must be able to be powered from 220v mains directly, OR, through a single Plug Type AC to DC converter, preferably something already available on the market.
4) The power supply unit must supply adequate power to the unit.
5) I want to make some actual use of a Raspberry Pi, as they were not meant to lie around gathering dust
6) Once completed, the project should be able to be updated OTA or with as little fuss as possible.
7) The freedom to code in whatever language I want, as well as be easy to use with prebuilt firmware like ESPHome and or Tasmota and the likes.
My Solution (Hardware and Software)
Taking into consideration cost, as well as flexibility, I decided on using the ESP8266 and in later versions ESP32.
These have WiFi and Bluetooth already built-in but have a nasty breadboard form factor. The popular NodeMCU is a great starting point, but it has many small design flaws, most of which were fixed in later versions, but, as I live in SE Asia, and electronics are super cheap, you never know what you get.
With this in mind, I have decided to design my own controller, based on the ESP-8266 12E Module. This will give me the flexibility I need while allowing me to add custom components and features as needed, which is not possible with a stock version.
As far as Software is concerned, Home Assistant, running on a Raspberry Pi 4B with 4Gb Ram will be sufficient to control all of this. Firmware on the ESP12-E can be either ESPHome, Tasmota, or something that I write on my own, connecting to the internet and using MQTT for communication. (The options here are also almost too many to mention, but, IFTTT, Adafruit IO, and Blynx come to mind… Alexa and Google Assistant support are also possible, but definitely not required in my application at this moment.
Addon Hardware and Expandability
Any permanent project grows on you, and over time, you will want to add features and functions. Keeping this in mind when you start designing saves a lot of headaches later. I will thus definitely make sure to provide access to the I2S, SPI and Serial Peripherals.
Prototyping and Initial Testing
Software
It is quite impossible to design something without building a prototype, and doing some very rigorous testing.
To do this, I have started with a copy of Home Assistant running in a VM on my HP ML350G Debian server computer. This way, I can quickly test Home Assistant, and make sure everything works as I want it to, without having to do it on the PI. This will mean that I will have to re-do most of the software configuration again on the PI,
but it gives me the flexibility to take snapshots and restore them if something goes wrong.
Start Home Assistant
When you have completed the installation, you can go ahead and start Home Assistant.
You may now open Home Assistant in your browser by going to http://<your-ip-address>:8123 and pressing enter.
You will see something similar to this:
Install ESPHome
You may now scroll down to the Supervisor Menu Item, Click on the Addon Store link, and Install ESPHome.
Please make sure that you select “start on boot”, “watchdog”, “auto-update” and “show in the sidebar”
Also, make sure to start the add-on
Flashing ESPHome to your device
You are now ready to flash ESPHome onto your development board. Please note that you will have to repeat this step on the actual PCB device that we will design and build later.
For now, we will however use a standard NodeMCU v3 module, as it contains the ESP-12E module that we require.
As we have not configured HTTPS in our Home Assistant installation, we can only flash the initial firmware using an external application. This application is called ESPHome Flasher, and you can download it here.
Prepare to Flash
We need to create an initial device in ESPHome. to do this, you need to click on the ESPHome Menu Item in the Home Assistant sidebar. Then click on the Green and White + sign at the bottom right corner…
Give your device a descriptive name, I went with iot-con-prototype. Also, add your WiFi network credentials (SSID and Password). Then click on NEXT.
You now have to select your ESP board. I went with NodeMCU.
Click on NEXT when you are done.
You will now be alerted that a configuration has been created. Click on the Close button.
You will now see your device in the list. The red line means that the device is OFFLINE.
If you have not installed ESPHome Flasher yet, now is a good time to do it. When you are done, connect the NodeMCU module to the computer’s USB port and start ESPHome Flasher.
Note: On Linux, you dont have to install it. you can just start it from the terminal using
./ESPHome-Flasher-1.3.0-Ubuntu-x64.exec ( this example is for Debian ) yours may differ … sudo may be required
Select the communications port from the dropdown menu.
Now go back to Home Assistant, ESPHome Screen.
Click on the Install link (in yellow) of the device that we added previously.
Then click on Manual Download
ESPHome will now compile your initial firmware and prompt you to save the .bin file it has generated.
Take note of the location of this file, we will need it for the next step.
Now you can go back to the ESPHome Flasher window, and browse to the .bin file that you have just generated and downloaded.
When this is done, you can click on Flash ESP. The firmware will now be flashed onto the NodeMCU device that we will use as our prototype.
You can close the Flasher application when you see predominantly purple text in the console window. This means that the device has connected successfully with your WiFi network, and by extension, also with ESPHome and Home Assistant.
If you now go back to ESPHome, you will see that the device has a green line above its name, which means that it is online. Please note that at this stage, the device does not do anything, as we have not yet configured it. That will be our next task, but before we do that, we will have to start playing with some of the physical hardware yet.
Designing the Hardware
I have decided to base this controller on the popular NodeMCU v3 development board. This little board makes use of the ESP12-E module, designed by AITinker, from whom I have bought many well-designed modules before. The module (NodeMCU) is in a BreadBoard form factor, and thus clearly meant for prototyping, or use on a base-board of some kind. I do however have some issues with this module, namely:
1. Many of these units are in fact clones. Some of these does not have proper protection between the board and the USB port to power them. This makes it dangerous to connect power to the VIN pin.
2. The board does not have a built-in 5v regulator. The 5v output (VIN) is thus taken directly from the USB port that powers it. This limits the total available current to the board and all peripherals to the 500mA available from the USB port.
All of these issues are however easy to overcome, as Espressif has made available excellent documentation on using their modules. I will thus be using this documentation as a reference design for my own device.
Another issue is expandability. The module provides many broken out GPIO pins (D0 to D8), but in order to remain super flexible for future expansion, I would have to make sure that I keep the built-in peripherals, like i2c, spi, and uart free for connection to external addon components in future. To solve this, I have decided on using the PCF8574 I2C IO Expander. This means that…
D0 (GPIO16) needs to be kept free for Wake up from deep sleep mode
D1 (GPIO5) SCL line of I2C Bus
D2 (GPIO4) SDA line of I2C Bus
D3 (GPIO0) connected to Flash Button, and also a strapping pin
D4 (GPIO2) Tx of UART 1
D5 (GPIO14) HSCLK – SPI Clock
D6 (GPIO12) HMISO – SPI MISO
D7 (GPIO13) Rx UART 2 / HMOSI – SPI MOSI
D8 (GPIO15) Tx UART 2 / HCS – SPI CS as well as a strapping pin
D9 ([Rx] GPIO03) Rx UART 0
D10 ([Tx] GPIO01) Tx UART 0
Looking at this, it is thus very clear that I2C is the way to go, as it will use only two pins, leaving the other GPIO’s free for future expansion.
Go back to the Table of Contents
Relay Driver Circuit, status led(s) and user control
The PCF8574 has very weak current sourcing capabilities, but it can sink 25mA per IO pin. As I will be driving the chip from 3v, this will however not be enough to drive a 5v relay. I will thus be making use of an optocoupler to drive the relay from 5v, using a general-purpose NPN transistor. That way, I can make sure that I do not overload the IO line on the PCF8574, as well as keep the 3v and 5v lines isolated from each other. (They will however still share a common ground).
Relay Driver Schematic
As you can see from the schematic above, the relay driver(s) will be connected to P0 and P1 of the PCF8574. A 200-ohm resistor will limit the current to about 16.5mA @ 3.3v. This is well within the tolerance of 25mA for the PCF8574 as well as the 50mA limit of the EL357N Optocoupler chip.
On the output side, I made use of the S8050 general purpose NPN transistor, capable of a 25v collector-emitter voltage, ant a continuous current of 500mA. Move than sufficient to drive the +/- 70mA to 80mA of current required by the relay coil. The current through the phototransistor side of the optocoupler is limited by a 1k resistor to the base of the transistor, to 5mA.
PCF8574 IO Expander Status LED(s) and User Input Schematic
Go back to the Table of Contents
Provision is made for up to four (4) pushbuttons, by pulling pins P4 to P7 down to ground, through an external push-button connected to a 2-way pin header. The design allows for the pin to be used for another function as well, with an additional breakout pin provided on the edge of the board.
Likewise, the two status LED’s on P2 and P3 is connected via a 470-ohm resistor each, driving them at approximately 7mA each. This is once again within the 25mA sink limit of the PCF8574. These pins can also be used to connect to other hardware instead via the breakout header at the edge of the board.
The user input(s) and status led circuit was purposefully kept as plain as possible, as it is very likely that the additional 6 ports taken up by these will be used for other purposes instead.
USB to Serial Interface
The USB-to-Serial interface is done by using a CH340G. I have not modified the reference design from the original NodeMCU v3 too much, as it works well, and thus need no changes. I did however make sure that there is a protection diode between the USB 5v line and the VIN line on the PCB. Most of the existing NodeMCU boards does not do this, or when they do have the protection diode, that line is directly connected to the VIN pin. in my view, that is not ideal, and can cause unnecessary damage to your computer’s USB port or NodeMCU board in the event that you power it from an external source, and also use USB power to upload code… Not that it should be done that way anyway, but rather safe than sorry later.
USB-to-Serial Schematic
The two transistors (VT1, and VT2) is used to do very cleverly put the board into programming mode, as well as reset it after flashing, without the end-user having to press any of the flash or reset buttons. This is also part of the reference design on some of the NodeMCU boards. I can not comment if it is standard. I found it useful, so decided to include it as well.
ESP-12E with strapping pins and power supply
The ESP-12E module, as manufactured by AITinker, seems to be quite stable and easy to use. It does however have a couple of caveats, to enable it to function as intended. The strapping pins (discussed later) should be in a certain state at bootup time, and failure to adhere to that will definitely cause a failed boot or wrong startup mode.
GPIO0, GPIO2, EN and RST should be pulled HIGH for a NORMAL boot, while GPIO15 should be pulled LOW.
Pulling GPIO0 LOW at boot, will put the board into FLASH mode.
Another change that I made is that I did not break out the raw Analog input pin, as is done on some of the boards ( as a VV pin, or sometimes as an unlabeled, or reserved pin). The Analog input pin on the stock module is designed for around 1.0v input. This is fed from a resistor divider, to effectively scale your 5v input down to valid levels.
ESP-12E and Power Supply Schematic
GPIO16 (D0) is used internally by the ESP-12E to wake the module from deep sleep. This is done by connecting GPIO16 to the reset pin. To wake up the module, GPIO16 is internally pulled LOW, thereby resetting the module.
I have decided to add a user-selectable jumper that can be enabled to connect GPIO16 to RESET, that enabling this functionality. It is however to be noted that the jumper must ONLY be set AFTER the relevant deep sleep mode has been enabled in the firmware for the module.
The standard NodeMCU has only a single 3.3v voltage regulator installed. I added a dedicated 5v voltage regulator as well and powered it directly from the VIN pin. This regulator will only function when the device is powered from an external power source, with an upper voltage limit of 15v DC. Protection for the USB port is provided by a diode between VCC_USB and VCC5V.
Designing the PCB
As I have mentioned at the start of the article, this is a show and tell, of how I solved a particular problem that I had.
I do not believe in re-inventing the wheel, but to adapt and improve as and where I see fit, to my own purpose. This project will by no means be unique, or better or worse than other similar devices on the market today. It is however designed to suit my particular needs for my particular project.
The design of the PCB and Schematics was done in EasyEDA, which I believe to be quick and easy to use, as well as Linux friendly. (There does not seem to be many of those around, KiCAD being the exception to that rule. I have however not been too successful in using that before, to no fault of KiCAD at all. I am just not prepared to learn a new EDA CAD package just for the sake of doing it. Time is precious, and I can get everything I need to do done with EasyEDA).
PCB Layout
The PCB is dual-layer 99.06mm x 83.058mm. Six mounting holes are provided. The ESP-12E is placed at the top,
roughly in the left-hand corner. As per Espressif design recommendations, no tracks are routed underneath the antenna area. An approximate 15mm x Board width area is also kept clear of any tracks or ground plane(s) to also prevent interference with the RF signal generated by the device. All components are mounted on the top payer of the PCB and are as far as possible grouped together by their function and purpose in the circuit. As the two onboard relay modules will very likely be used to switch mains power, they have also been excluded from the ground plane(s). Cutouts around all possible mains power carrying pads and tracks were also added to prevent tracking.
A DC Power Socket, and USB port, as well as access to the single Analog Input, Enable, Reset Pin and Button and VIN pin is provided on the left-hand side of the PCB. All other IO pins, as well as the six remaining ports on the PCF8574 IO expander, is accessible on the right. Note that GPIO4 and GPIO5 ( D1 and D2 ) were hard-wired as I2C lines. They should thus not be used for any other purpose. All other pins are accessible and broken out, clearly labelled with their GPIO numbers, as well as NodeMCU style Dx numbers. There are also an additional 6 IO pins broken out at the bottom of the ESP-12E module, to provide access to the seldom-used SDCard interface.
PCB Top Layer ( Rendered )
PCB Bottom Layer (Rendered)
3D Render PCB from Left
Our next step will be to write the YAML configuration file...
YAML configuration
Our next step will be to write the YAML configuration file...
YAML configuration
ESPHome uses the YAML language to define IO and automation. These files are then parsed, converted into C/C++ and compiled. The resulting Binary File is the uploaded OTA to the device via WiFi.
We will still be using our Virtual Machine Image of Home Assistant, running inside VirtualBox on our PC.
Go ahead and start that, and then open Home Assistant in your Web Browser. Then click on ESPHome.
You will see a screen similar to the one above.
While we are at this point, I believe it is a good time to clarify why we do the development in a virtual PC, and not directly on our Home Assistant instance running on a Raspberry Pi. The reason is actually very simple. Home Assistant seems to have issues with completely removing unused entities. This is not a problem, but you could potentially end up with a lot of stale entries in your production Home Assistant Server. The VM solution allows us to test everything away from the actual server, and then, when we are done, recreate the working device on the actual server. That way, there is almost no chance of damaging your existing Home Assistant Server, which you may already have spent some time on to set up just the way you want it...
Continue by clicking on the EDIT link, in the iot-con-prototype device that we created in the last tutorial.
You will see a file similar to this ...
esphome:
name: iot-con-prototype
platform: ESP8266
board: nodemcuv2
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
password: "3f132fc270315361e4d2393a50c2bac5"
wifi:
ssid: "<your ssid here>"
password: "<your password here>"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Iot-Con-Prototype"
password: "4uSytyPTx1TO"
captive_portal:
This is the default configuration file generated by ESPHome. We will build on this file... Note that your OTA Password will be different. DO NOT CHANGE OR MODIFY IT IN ANY WAY!
When we edit YAML, indentations are extremely important, so try to follow exactly what I am doing.
Our IoT Controller uses I2C to communicate with the PCF8574 chip. Let us assume that you have set your address to 0x22h by using the dip switch on the PCB, you could of course set any other address, just make sure that you know what it is.
We now need to tell ESPHome that we have an I2C Bus and that it needs to scan this bus for devices. That way, we can see in the logs if it actually detects our device or not.
Add the following 5 lines to your file:
i2c:
sda: GPIO4
scl: GPIO5
scan: true
id: i2c_bus_a
They mean that we will have an I2C bus with SDA on GPIO4, and SCL on GPIO5.
The bus will have an ID of i2c_bus_a and the bus should be scanned
The next section will be the actual PCF8574 Io Expander
Add the following lines to the file:
pcf8574:
- id: 'pcf8574_hub'
address: 0x22
pcf8575: false
We give this device the id of pcf8574_hub and specify its address as 0x22. We also NEED to specify that it is NOT the 16 port pcf8575 variant.
Now we can start configuring our outputs. for our purposes, we will have two relay outputs, as well as two status LEDs. In the actual circuit, the pcf8574 will sink the pins connected to these, as the chip can sink more current than it can safely source. Refer to the relay driver schematic for more information on that.
Go ahead, and add the following to your file.
output:
- platform: gpio
id: relay_1
pin:
pcf8574: pcf8574_hub
number: 0
mode: OUTPUT
inverted: true
- platform: gpio
id: relay_2
pin:
pcf8574: pcf8574_hub
number: 1
mode: OUTPUT
inverted: true
- platform: gpio
id: led_status_1
pin:
pcf8574: pcf8574_hub
number: 2
mode: OUTPUT
inverted: true
- platform: gpio
id: led_status_2
pin:
pcf8574: pcf8574_hub
number: 3
mode: OUTPUT
inverted: true
The syntax should be straightforward, every output will have a platform, in this case, gpio.
Then we will need a unique ID, let us say relay_1
Now, we need to specify the physical pin to use. Now here, you could also specify a native pin on the actual NodeMCU device that we are using for testing, but we will specify a pin on the pcf8574 instead.
This is done with the pin: directive
pin:
pcf8574: pcf8574_hub // This tells the parser to use the device at address 0x22 that we specified before.
number: 0 // use GPIO 0
mode: OUTPUT // this can be either INPUT or OUTPUT, for our case, it should be OUTPUT.
inverted: true // Invert the logic of the pin.
Once again, it is needed, as we are sinking current into the pin, and the circuit was designed that way...
You can however use it noninverted if you really want, it will just look a bit odd on Home Assistant, if your On state, actually meant Off
The next section will be called binary inputs and may seem a bit confusing at first. But, trust me, it is not. This is just the way that we define our physical push buttons on the device. We need those, in the event that our Home Assistant Server is offline, or when we need to physically press a button on the device.
What? Why? Are we not building an IoT Controller? Why should we press any physical buttons on it?
Well, the answer to that is quite obvious. There will definitely be times that you want to control an attached device by pressing a physical button. It does not make sense to scurry around, swiping through apps on your smartphone, while you are standing right next to the device in question. To leave out this basic functionality, would be plain silly, and in my view, bad engineering.
binary_sensor:
- platform: gpio
id: push_button_1
name: 'Relay1 Pushbutton'
device_class: ''
pin:
pcf8574: pcf8574_hub
number: 4
mode: INPUT
inverted: true
on_press:
then:
- switch.toggle: switch_relay1
filters:
- delayed_on_off: 50ms
- platform: gpio
id: push_button_2
name: 'Relay2 Pushbutton'
device_class: ''
pin:
pcf8574: pcf8574_hub
number: 5
mode: INPUT
inverted: true
on_press:
then:
- switch.toggle: switch_relay2
filters:
- delayed_on_off: 50ms
The syntax is almost the same as the outputs above, but we are also adding automation:
We want the relay to be toggled each time the button is pressed. This will allow us to use only one button per relay to switch it on or off.
We are also adding a filter, in this case, a bit of debouncing, of 50ms. This will prevent the chattering of the contacts on the switch from generating more than one event for each button press.
The final section of the file will be a switch: section. This will allow you to control the relays from inside Home Assistant. ( The outputs are considered an internal to ESPHome function, and will thus not be exposed to Home Assistant.
Add the following lines to the file
switch:
- platform: output
id: switch_relay1
name: "Relay No. 1 (#0)"
output: relay_1
on_turn_on:
- output.turn_on: led_status_1
on_turn_off:
- output.turn_off: led_status_1
- platform: output
id: switch_relay2
name: "Relay No. 2 (#1)"
output: relay_2
on_turn_on:
- output.turn_on: led_status_2
on_turn_off:
- output.turn_off: led_status_2
You can see that the syntax is once again very easy to understand. We also specify that the status LED for the relevant relay channel be switched on or off with the relay. This also happens when you press the physical switch.
The name element will be the Name of the Output that will be displayed in Home Assistant. You can change it to your liking here, or you can also change it inside Home Assistant itself.
The completed file should now look like this. NOTE that if you decide to copy-paste the file from here, as I would recommend, you should only copy from the i2c section to the end of the file. Do not copy the WiFi and other sections. Your own file already has your own settings.
esphome:
name: iot-con-prototype
platform: ESP8266
board: nodemcuv2
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
password: "3f132fc270315361e4d2393a50c2bac5"
wifi:
ssid: "<your ssid here>"
password: "<your password here>"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Iot-Con-Prototype"
password: "4uSytyPTx1TO"
captive_portal:
#DO NOT COPY ANYTHING ABOVE THIS LINE --------
i2c:
sda: GPIO4
scl: GPIO5
scan: true
id: i2c_bus_a
pcf8574:
- id: 'pcf8574_hub'
address: 0x22
pcf8575: false
output:
- platform: gpio
id: relay_1
pin:
pcf8574: pcf8574_hub
number: 0
mode: OUTPUT
inverted: true
- platform: gpio
id: relay_2
pin:
pcf8574: pcf8574_hub
number: 1
mode: OUTPUT
inverted: true
- platform: gpio
id: led_status_1
pin:
pcf8574: pcf8574_hub
number: 2
mode: OUTPUT
inverted: true
- platform: gpio
id: led_status_2
pin:
pcf8574: pcf8574_hub
number: 3
mode: OUTPUT
inverted: true
binary_sensor:
- platform: gpio
id: push_button_1
name: 'Relay1 Pushbutton'
device_class: ''
pin:
pcf8574: pcf8574_hub
number: 4
mode: INPUT
inverted: true
on_press:
then:
- switch.toggle: switch_relay1
filters:
- delayed_on_off: 50ms
- platform: gpio
id: push_button_2
name: 'Relay2 Pushbutton'
device_class: ''
pin:
pcf8574: pcf8574_hub
number: 5
mode: INPUT
inverted: true
on_press:
#min_length: 50ms
#max_length: 500ms
then:
- switch.toggle: switch_relay2
filters:
- delayed_on_off: 50ms
switch:
- platform: output
id: switch_relay1
name: "Relay No. 1 (#0)"
output: relay_1
on_turn_on:
- output.turn_on: led_status_1
on_turn_off:
- output.turn_off: led_status_1
- platform: output
id: switch_relay2
name: "Relay No. 2 (#1)"
output: relay_2
on_turn_on:
- output.turn_on: led_status_2
on_turn_off:
- output.turn_off: led_status_2
Well done, That was quite easy.
Copy and paste the file into the edit screen that you have opened in ESPHome.
If everything went well. you should see an option to save or install as in the picture below.
YAML configuration file. ESPHome
If you can see both Save and Install, it means that your file syntax is correct. If not, go back and carefully check your indentations, as well as the spelling of the commands. It should not be a problem if you copied it from above...
Now click on save. You will get a confirmation.
Make sure that the prototype is connected to the USB port of the computer, or to another power source. Wait a few seconds to make sure that it is connected to the network, and then click Install.
ESPHome will now parse your YAML file, generate the needed code, and compile it. After that, it will upload the new firmware to your device. Wait until you can see the device restart and connect to the network in the log window.
The Firmware is compiled and the uploaded OTA
The device had booted, note that the PCF8574 has been detected and that we can see our configuration data (in purple text)
Configuring Home Assistant
We can now start to add this all to Home Assistant. It is also very likely that you will be prompted to add the device by Home Assistant itself. If this did not happen, or like with my testing image on the VM, you have a lot of old stuff floating around as well, we can do it manually ...
Go to the Configuration Menu, and click on Integrations.
Click on the esp8266-nodemcu option on ESPHome
Click on the entities, next to the device ...
The available entities ( selected with a blue checkmark ). Entities with a red warning are stale, meaning old, unavailable or offline... You can remove them, but they tend to show up again on their own...
We can now select the two relays, as well as the Pushbuttons. Then click on Enable selected.
When you now go back to the Home Assistant Home screen, you will see your device with its controls, on the screen. You can now control the device from Home Assistant. You will note that the two push-buttons are also present in Home Assistant, but, they are only indicators. This means that while they will change state briefly when you press the physical switches, they can not be controlled directly from Home Assistant. They can however be used in automation, or at least I believe so. The debouncing times are however rather short, so I would recommend that you base any automation on the actual relay states instead.
A sneak preview of the PCB
So let us look at these boards...
PCB's in packaging
Securely packaged in vacuum-packed bubble wrap
Topside of the PCB
Top Side of PCB
Back of PCB, isolation cutouts clearly visible
The PCB's have arrived.
My biggest frustration now will be to wait for the rest of the components to arrive. I already have some of them in stock, and can repurpose some others, but I think that I will rather wait for everything to arrive so that I don't have to
assemble them in stages. I plan to assemble 2 of the 10 boards and make some of the remaining 8 available to interested people. Contact me on messenger if you are interested.
Assembly and Initial Testing
The majority of the components have finally arrived, and I can at long last start with assembly. I have also discovered, to my irritation, that I have made 3 small errors on the PCB design ( all of which have been fixed in the Gerber Files, as well as on the schematics, as ver 1.5)
These errors were however easily fixed in every case, to render the board completely useable and functional. Some disclosure seemed important :)
Let us look at what was wrong, and how I fixed it.
1) No Ground on C10, C11 and U2
Somewhere during the design stage, I decided to add a dedicated 5v LDO regulator, as the PCB would be powered from various sources. These include the DC Input Jack on the left-hand side of the PCB. This will allow for up to 15v DC input, You can also power directly from any pin marked 5v, or directly from 3.3v ( in which case only the ESP12-E and related circuitry would function, the relay(s) won't work in this case).
I fixed this by adding two wire links from the ground at C10 and C11 to the Ground at C1.
Please note that the capacitor at C1 is a 10uf Tantalum. It is designed as a 100uf electrolytic, which has not yet arrived :( I was not prepared to recycle any 100uf electrolytic from somewhere else, as I don't consider them stable after being desoldered and reused. The 10uf Tantalum cap does however work well.
2). Wrong labelling and tracks at PCF8574 I2C Port. This one was a little bit more difficult to find. On the ESP-12E, GPIO5 is usually used as SCL and GPIO4 as SDA. Being a bit overconfident, I forgot to verify with the PCF8574 Datasheet, and thus connected the nets in reverse, meaning GPIO5 went to SDA on the PCF8574, and GPIO4 went to SCL. This is not really a problem, as I2C is assigned in software, but it could lead to confusion. The labels on the Pin Header were also reversed.
3.) The 5v output pin next to D3 was left unconnected to any net. This was fixed with a wire loop on the bottom of the board from another 5v pin.
Making mistakes on a prototype is in my opinion not the end of the world, as long as you find them, document them, and of course, fix them asap. In this case, all errors were promptly fixed and updated to the design files.
Testing the PCB.
The PCB was next tested for correct operation, and all parts of the circuit passed, with exception of the USB to Serial circuit, as the 12Mhz crystal was incorrectly supplied at 8Mhz, and the CH340G would not function correctly with that crystal.
This was however NOT a problem, as the board can easily be flashed with an external FTDI or similar USB-to-Serial adapter, while keeping in mind that you should press and hold down the flash button, then reset the board by pressing the reset button, and after a few seconds, letting go of the flash button. You should also manually reset the board after every upload procedure to start running your firmware.
This would all have been happening automatically, but due to logistics issues, was not possible on the prototypes. The correct 12Mhz crystal will be retrofitted to the boards when it eventually arrives.
Power consumption with the board in an idle state was 75mA and 255mA with all relays energised, and all status led's lit up. Well within the 800mA limit of the LDO voltage regulators used.
Updating the ESPHome firmware.
I proceeded to make more changes to the ESPHome yaml code used to control the board.
I added a remote reset switch, as well as monitors for the WiFi signal and Vcc to the ESP-12E.
I also connected a DHT11 Temperature and Humidity sensor, as well as an LM73 I2C temperature chip, to measure the temperature of the device enclosure.
The LM73 is currently not directly supported by ESPHome, so I had to write a custom driver. ( File to be included in the attachments )
This header file needs to be uploaded into the ESPHome config folder on the home Assistant Server and referenced as an include file in the yaml configuration.
To make the device even more flexible, I configured a local mosquito MQTT server on a separate server and added that configuration to the yaml file as well. This, combined with some local automation rules running directly on the ESP-12E, will allow me to control the device with an app like MQTT Dash on my Android phone, without needing Home Assistant to be running.
The picture above shows the initial integration into the Home Assistant Testing Server. Note that in this picture, the LM73 was not yet implemented.
We can see the device in the EE Lab area, and the administrative details, like Vcc, WiFi signal and Reboot switch, in the Master Control Panel card.
In the pictures below, I will show you the full integration, of two devices into Home Assistant.
Please see attached code under attachments.
Tasmota
It would not be fair not to mention Tasmota. It is a great way to get remote control of a lot of devices. It does run on my PCB, but with a few issues, none of which I believe to be problems caused by myself or my design. :)
1) You need to recompile a custom version of Tasmota, with support for PCF8574 compiled in.
( This is not supported in the stock version of Tasmota, thus the need to recompile)
2) Tasmota custom compile seems to run extremely slow, ( that is in comparison with the stock version.)
3) I found that the custom compiled version was not very stable, crashing often, with no apparent reason.
I dont know the reason for that, as I did not go into detail with the code myself... More knowledgeable persons may know why, and how to fix it.
Control the device from MQTT
This works extremely well. I managed to control the device from a local Mosquitto server, via MQTT Dash on my Android Phone.
This makes it possible to use the device without Home Assistant running.
In Conclusion
I now consider the project complete, I have plans to do future revisions to it, like adding support for powering it from Mains Power, adding more relays via an expansion card, adding more power outputs, (3,3v and 5v) as well as more GPIO using either another PCF8574 or an MCP23017...
OSHW Certification is completed, You may freely use the PCB and software in an open-source project.
Thank you.
The Project is released under the following Open Source Licences:
esphome:
name: iot-controller-8266-01
includes: lm73.h # Note the inclusion of the Header file for the lm73
platform: ESP8266
board: nodemcuv2
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
password: "2f8a73f47f1893f3f7baa391c4d0ba96"
#------ Dont copy paste anything above this line. It is unique to every ESPHome device ------
wifi:
ssid: "<your ssid here>"
password: "<your password here>"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Iot-Controller-8266-01"
password: "y4aaH7vMITsC"
captive_portal:
# MQTT configuration to connect to a local Mosquitto Server
mqtt:
broker: 192.168.100.19
username: "<username>"
password: "<password>"
# Automations to allow control from apps like MQTT Dash
on_message:
- topic: iot-controller-8266-01/switch/relay_no_1_0/state
payload: "ON"
then:
- switch.turn_on: switch_relay1
- topic: iot-controller-8266-01/switch/relay_no_1_0/state
payload: "OFF"
then:
- switch.turn_off: switch_relay1
- topic: iot-controller-8266-01/switch/relay_no_2_1/state
payload: "ON"
then:
- switch.turn_on: switch_relay2
- topic: iot-controller-8266-01/switch/relay_no_2_1/state
payload: "OFF"
then:
- switch.turn_off: switch_relay2
- topic: iot-controller-8266-01/switch/reboot_me/state
payload: "ON"
then:
- switch.turn_on: reboot_switch
#deep_sleep:
# run_duration: 5min
# sleep_duration: 2min
i2c:
# PCB Prototype
sda: GPIO5
scl: GPIO4
# PCB Rev 1.5 or higher, comment the above 2 lines
# and uncomment
#sda: GPIO4
#scl: GPIO5
#################### - IMPORTANT ###########
scan: true
id: i2c_bus_a
pcf8574:
- id: 'pcf8574_hub'
address: 0x22 # Set at 0x22, feel free to change to your liking, Remember to set the chip to the address you choose as well
pcf8575: false
status_led:
pin:
number: GPIO16
inverted: true
sensor:
# Custom code for LM73 -
- platform: custom
lambda: |-
auto my_sensor = new MyCustomSensor();
App.register_component(my_sensor);
return {my_sensor};
sensors:
name: "Enclosure Temperature"
unit_of_measurement: "°C"
accuracy_decimals: 2
device_class: "temperature"
state_class: "measurement"
filters:
- sliding_window_moving_average:
window_size: 6
send_every: 2
- platform: adc
pin: VCC
name: "Device Input Voltage"
unit_of_measurement: "V"
- platform: wifi_signal
name: "WiFi Signal Sensor"
unit_of_measurement: "dBm"
update_interval: 240s
- platform: dht
pin: GPIO2
temperature:
name: "Room Temperature"
unit_of_measurement: "°C"
icon: "mdi:temperature"
device_class: "temperature"
state_class: "measurement"
accuracy_decimals: 2
filters:
# Some calibration to get the DHT11 to be a bit more accurate... Values are in Meassured -> True Value format.
- calibrate_linear:
- 0.0 -> 0.0
- 29.16 -> 29.46
- 29.23 -> 29.50
- 29.36 -> 29.75
- 29.43 -> 29.75
- 29.54 -> 30.00
- 29.77 -> 30.00
- 30.39 -> 30.50
- 30.66 -> 30.75
- sliding_window_moving_average:
window_size: 6
send_every: 2
humidity:
name: "Room Humidity"
unit_of_measurement: "%"
icon: "mdi:water-percent"
device_class: "humidity"
state_class: "measurement"
accuracy_decimals: 2
update_interval: 60s
output:
- platform: gpio
id: relay_1
pin:
pcf8574: pcf8574_hub
number: 0
mode: OUTPUT
inverted: true
- platform: gpio
id: relay_2
pin:
pcf8574: pcf8574_hub
number: 1
mode: OUTPUT
inverted: true
- platform: gpio
id: led_status_1
pin:
pcf8574: pcf8574_hub
number: 2
mode: OUTPUT
inverted: true
- platform: gpio
id: led_status_2
pin:
pcf8574: pcf8574_hub
number: 3
mode: OUTPUT
inverted: true
binary_sensor:
- platform: gpio
id: push_button_1
name: 'Relay1 Pushbutton'
device_class: ''
pin:
pcf8574: pcf8574_hub
number: 4
mode: INPUT
inverted: true
on_press:
then:
- switch.toggle: switch_relay1
filters:
- delayed_on_off: 50ms
- platform: gpio
id: push_button_2
name: 'Relay2 Pushbutton'
device_class: ''
pin:
pcf8574: pcf8574_hub
number: 5
mode: INPUT
inverted: true
on_press:
#min_length: 50ms
#max_length: 500ms
then:
- switch.toggle: switch_relay2
filters:
- delayed_on_off: 50ms
switch:
- platform: output
id: switch_relay1
name: "Relay No. 1 (#0)"
output: relay_1
on_turn_on:
- output.turn_on: led_status_1
on_turn_off:
- output.turn_off: led_status_1
- platform: output
id: switch_relay2
name: "Relay No. 2 (#1)"
output: relay_2
on_turn_on:
- output.turn_on: led_status_2
on_turn_off:
- output.turn_off: led_status_2
- platform: restart
id: reboot_switch
name: "Reboot Me"
#include "esphome.h"
#include "Wire.h"
class MyCustomSensor : public PollingComponent, public Sensor {
public:
// constructor
MyCustomSensor() : PollingComponent(50000) {}
float get_setup_priority() const override { return esphome::setup_priority::BUS; }
void setup() override {
// This will be called by App.setup()
// For PCB Prototype
Wire.begin(5,4);
// For PCB rev 1.5 or higher, comment line 13 and uncomment line 15
//Wire.begin(4,5);
}
void update() override {
// This will be called every "update_interval" milliseconds.
Wire.beginTransmission(0x4C);
Wire.write(0x00); // Temperature Data Register
Wire.endTransmission();
uint8_t count = Wire.requestFrom(0x4C, 2);
float temp = 0.0;
if (count == 2)
{
byte buff[2];
buff[0] = Wire.read();
buff[1] = Wire.read();
temp += (int)(buff[0]<<1);
if (buff[1]&0b10000000) temp += 1.0;
if (buff[1]&0b01000000) temp += 0.5;
if (buff[1]&0b00100000) temp += 0.25;
if (buff[0]&0b10000000) temp *= -1.0;
}
publish_state(temp);
}
};
Build your own IoT Controller
*PCBWay community is a sharing platform. We are not responsible for any design issues and parameter issues (board thickness, surface finish, etc.) you choose.
- Comments(2)
- Likes(14)
- Engineer Sep 08,2024
- Engineer May 09,2024
- Engineer Feb 18,2024
- Engineer Oct 10,2023
- nordMaker Jul 11,2023
- Engineer May 23,2023
- Engineer Apr 25,2023
- Yurii Bondarenko Jan 02,2023
- Sergey Medvedev Jun 01,2022
- Engineer Feb 10,2022
- Enes Mercan Nov 15,2021
- Engineer Sep 11,2021
- Engineer Sep 06,2021
- Engineer Aug 26,2021
- 2 USER VOTES
- YOUR VOTE 0.00 0.00
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
-
9design
-
7usability
-
8creativity
-
8content
-
10design
-
10usability
-
10creativity
-
10content
More by Jean Redelinghuys MakerIoT2020
- PCB_MCP23008_2023-10-08 MCP23008 BreakoutI designed this breakout to assist me during prototyping my next version of the “RP...
- PCB_XiaoRP2040-Mouse-REV2 Xiao RP2040 Joystick Mouse – revision 2.00Revision 1.0 of the ProjectOver the last few months, I hav...
- Multi Purpose IO Card Multi-Purpose IO CardWhen we are working on a prototype, we always need access to pushbuttons, encod...
- Variable Voltage Power Module Variable Voltage Power ModulePowering electronics projects are always challenging. This Variable vol...
- I2C Matrix Keypad An I2C Matrix KeypadThe completed I2C Matrix KeypadIn a previous post this month I introduced my 4×4...
- ESP32-S Development Board, in "Arduino Uno" form factor UPDATE 24/06/2023:This board now has a Hardware Revision 2.0 available. It is the same board but wit...
- W307186ASC94_Gerber_PCB_USB-Ports USB Power Supply ModuleUSB Ports are quite handy to power all our day-to-day electronic devices, but...
- Atmega 328P based PWM controller Card ATMega 328P Based PWM controller CardAs part of my recent ESP-12E I2C Base Board project, I designed...
- W307186ASC71_Gerber_PCB_ESP-Now Remote Today we will look at the remote control unit for the Robotic Toy Car – Part 6.The project is close ...
- W307186ASV69_Gerber_PCB_Robot-Car-MCU-Board Prototype In our last project, we started working on repurposing an old toy car. In this part, Robot Toy Car –...
- W307186ASV62_Gerber_PCB_DUAL-H-Bridge by makeriot2020 on May 27, 2022Many of us have old toys laying around the house, they belong to ou...
- CAN-BUS Breakout Breadboard Compatible CAN-BUS Breakout ModuleWhat is this:Some of us have already used the commonly ...
- RA-02 Breakout with Level converters Breadboard and beginner-friendly RA-02 Breakout ModuleMost Makers and electronics enthusiasts may al...
- ATMEGA328P Module with integrated LoRa and CAN Bus ATMEGA328P Module with integrated LoRa and CAN-BUSINTRODUCTIONIn my quest to perfect my LoRa telemet...
- Sx127x-Ra-02-Test-Module with ATMEGA328P-AU SX127x LoRa/FSK/OOK Prototype Radio BoardI recently had a requirement to do some automation/telemetr...
- USB-ASP Programmer ATMEGA8 Build your own USB-ASP Programmer CloneBymakeriot2020 FEB 21, 2022 Arduino, ASP programmerUsing mor...
- ATTiny1616-LIGHT-Controller-with-CAN_B_PCB_ATTiny1616-LIGHT-Controller-with-C_2024-09-11 Assembly of the ATTiny1616 Can bus controller PCBThe Assembly of the ATTiny1616 Can Bus Controller P...
- ATTiny1616QFN-CAN-Remote-Neopixel-Ligh_PCB_ATTiny1616QFN-CAN-Remote-Neopixel-2024-09-11_2024-09-11 NeoPixel CAN-Bus Module with local controlAs part of my current project to add NeoPixels to the cabi...
-
-
-
-
-
-
3D printed Enclosure Backplate for Riden RD60xx power supplies
154 1 1 -
-