I had a need to build a reliable LoRa device, in order to do some testing regarding range etc, for an upcoming project on a friend’s farm. The device needs to be ultra-cheap to manufacture, as well as little power as possible. To achieve this, I decided on using the RA-02 ( From AI Tinker, not sponsored) as well as an ATMEGA328P, which consumes very little current when put to sleep… ( The radio will be on standby the whole time though..)
Building this with a standard Arduino, or another ATMEGA powered development board can be quite messy ( as the picture below shows… )
A standard Arduino will be even worse, as you need level conversion on the SPI pins, due to the fact that the RA-02 is a 3.3v device, with the GPIO, not being 5v tolerant (Yes, this is true, some other posts on Youtube and similar conveniently leave out this very important little caveat… )
This problem thus warranted a dedicated custom PCB, to be designed in stages, and thoroughly tested of course… And while doing that, I needed to design something that was modular and useable.
I came up with the following design, as a stage one prototype:
The PCB is basically an Arduino Nano style PCB ( as far as IO is concerned ), with level conversion on the SPI lines ( SCK, MISO, MOSI, SS) as well as a Lora reset and IRQ pin ( which will be essential to wake up the processor later ).
As the prototype will mostly be used in the lab, with some outdoor tests later, provision was not made for battery charging circuitry. Two LDO regulators, 5v and 3.3v provide power to the ATMEGA328P and RA-02 from a DC input of 7.5 to 12v.
Level conversion is fixed at bi-directional 5v to 3v logic levels.
All unused GPIO’s are broken out onto headers.
Code can be uploaded to the MCU via ICSP or a USB-to-serial converter, as I did not add those on board, to save space and power later.
Control Pins are as follows:
RA-02 Module
ATMEGA328P
SCK
D13
MISO
D12
MOSI
D11
NSS
D10
RESET
D9
IQR(DIO0)
D2 ( Interrupt 0 )
DIO1
Not broken out on stage 1 Prototype
DIO2
Not broken out on stage 1 Prototype
DIO3
Not broken out on stage 1 Prototype
DIO4
Not broken out on stage 1 Prototype
Pin connections between RA-02 and ATMEGA328P
The Schematic diagram are listed below
Software
The board is compatible with the LoRa library from Sandeep Mistry. Other libraries may work as well but were not tested yet.
A very basic test sketch follows below: Note that this sketch does not have any power-saving. It is purely used to do a very basic radio test… More detailed code will be released in later stages of the project ( more on that later )
#include <SPI.h> // include libraries
#include <LoRa.h>
const int csPin = 10; // LoRa radio chip select
const int resetPin = 9; // LoRa radio reset
const int irqPin = 2; // change for your board; must be a hardware interrupt pin
byte msgCount = 0; // count of outgoing messages
int interval = 2000; // interval between sends
long lastSendTime = 0; // time of last packet send
void setup() {
Serial.begin(9600); // initialize serial
while (!Serial);
Serial.println("LoRa Duplex - Set spreading factor");
// override the default CS, reset, and IRQ pins (optional)
LoRa.setPins(csPin, resetPin, irqPin); // set CS, reset, IRQ pin
if (!LoRa.begin(433E6)) { // initialize ratio at 433 MHz
Serial.println("LoRa init failed. Check your connections.");
while (true); // if failed, do nothing
}
LoRa.setSpreadingFactor(8); // ranges from 6-12,default 7 see API docs
Serial.println("LoRa init succeeded.");
}
void loop() {
if (millis() - lastSendTime > interval) {
String message = "LoRa TEST"; // send a message
message += msgCount;
sendMessage(message);
Serial.println("Sending " + message);
lastSendTime = millis(); // timestamp the message
interval = random(2000) + 1000; // 2-3 seconds
msgCount++;
}
// parse for a packet, and call onReceive with the result:
onReceive(LoRa.parsePacket());
}
void sendMessage(String outgoing) {
LoRa.beginPacket(); // start packet
LoRa.print(outgoing); // add payload
LoRa.endPacket(); // finish packet and send it
msgCount++; // increment message ID
}
void onReceive(int packetSize) {
if (packetSize == 0) return; // if there's no packet, return
// read packet header bytes:
String incoming = "";
while (LoRa.available()) {
incoming += (char)LoRa.read();
}
Serial.println("Message: " + incoming);
Serial.println("RSSI: " + String(LoRa.packetRssi()));
Serial.println("Snr: " + String(LoRa.packetSnr()));
Serial.println();
}
Future Plans
Future plans for this project include the following: – Integration of a LiPo battery charging module, with a boost converter, to enable the device to run on battery power. – Integration with an ESP32 or similar, to build a simple GATEWAY device – CAN-BUS controller integration, to allow for adding multiple sensors to one radio module – IO card, with galvanically isolated inputs, as well as Relay outputs, for remote control and monitoring applications.
The PCB can be ordered, or the design files downloaded ( a free download ) from my Projects page at PCBWay soon…
This PCB was manufactured at PCBWAY. The Gerber files and BOM, as well as all the schematics, will soon be available as a shared project on their website. If you would like to have PCBWAY manufacture one of your own, designs, or even this particular PCB, you need to do the following… 1) Click on this link 2) Create an account if you have not already got one of your own. If you use the link above, you will also instantly receive a $5USD coupon, which you can use on your first or any other order later. (Disclaimer: I will earn a small referral fee from PCBWay. This referral fee will not affect the cost of your order, nor will you pay any part thereof.) 3) Once you have gone to their website, and created an account, or login with your existing account,
4) Click on PCB Instant Quote
5) If you do not have any very special requirements for your PCB, click on Quick-order PCB
6) Click on Add Gerber File, and select your Gerber file(s) from your computer. Most of your PCB details will now be automatically selected, leaving you to only select the solder mask and silk-screen colour, as well as to remove the order number or not. You can of course fine-tune everything exactly as you want as well.
7) You can also select whether you want an SMD stencil, or have the board assembled after manufacturing. Please note that the assembly service, as well as the cost of your components, ARE NOT included in the initial quoted price. ( The quote will update depending on what options you select ).
8) When you are happy with the options that you have selected, you can click on the Save to Cart Button. From here on, you can go to the top of the screen, click on Cart, make any payment(s) or use any coupons that you have in your account.
Then just sit back and wait for your new PCB to be delivered to your door via the shipping company that you have selected during checkout.
Using more ATMEGA based MCU’s in my recent projects, and not using ready-made Arduino boards for any of them, it became necessary to invest in a dedicated ASP programmer to flash the MCU’s. Huge delays on electronics components, with confirmed orders being mysteriously cancelled due to sourcing issues, and the high cost of “original OEM ASP programmers”, send me on a search for a DIY style programmer, like the old “NOPPP” ( NO PARTS PIC Programmer) in the good old days…
Personal computers have changed a lot, and while ATMEGA chips are not PIC’s, I did feel that it could be done. Given the fact that you could also use an Arduino UNO as an ISP, and doing a little more digging, I finally found a very attractive alternative…
Thomas Fischl, on his website,https://www.fischl.de/usbasp, has an open-source hardware project, that seemed to be exactly what I needed. His device is capable of programming 5v devices, at various speeds, including a super slow one. He has also written firmware for the device, and although the last update was in 2011, It still seems to be working well, or at least as far as I can see…
I did however decide to add my own twist to the design and build in a logic level converter, to be able to program 3.3v devices as well…
The modified schematic is below:
I chose to do my own PCB layout, to incorporate the changes listed earlier, namely the logic level conversion from 5v to 3v, as well as adding a 3.3v LDO voltage regulator to provide 3.3v to the target in case it is required.
The PCB is still in transit from the factory, and thus I will update this article later with pictures of the actual device.
Firmware can be flashed using any ASP programmer, Arduino as ISP as well, but with the caveat that you have to use AVRDude from the command line… More on that in the follow-up post… ( I would like to show actual screenshots of the process, and not theory.. ). The links to the firmware are available on https://www.fischl.de/usbasp, courtesy of Thomas Fischl, whom I would like to thank for making this open-source hardware project available freely, as well as for writing and maintaining the firmware.
The PCB can be ordered, or the design files downloaded ( a free download ) from my Projects page at PCBWay soon…
This PCB was manufactured at PCBWAY. The Gerber files and BOM, as well as all the schematics, will soon be available as a shared project on their website. If you would like to have PCBWAY manufacture one of your own, designs, or even this particular PCB, you need to do the following… 1) Click on this link 2) Create an account if you have not already got one of your own. If you use the link above, you will also instantly receive a $5USD coupon, which you can use on your first or any other order later. (Disclaimer: I will earn a small referral fee from PCBWay. This referral fee will not affect the cost of your order, nor will you pay any part thereof.) 3) Once you have gone to their website, and created an account, or login with your existing account,
4) Click on PCB Instant Quote
5) If you do not have any very special requirements for your PCB, click on Quick-order PCB
6) Click on Add Gerber File, and select your Gerber file(s) from your computer. Most of your PCB details will now be automatically selected, leaving you to only select the solder mask and silk-screen colour, as well as to remove the order number or not. You can of course fine-tune everything exactly as you want as well.
7) You can also select whether you want an SMD stencil, or have the board assembled after manufacturing. Please note that the assembly service, as well as the cost of your components, ARE NOT included in the initial quoted price. ( The quote will update depending on what options you select ).
8) When you are happy with the options that you have selected, you can click on the Save to Cart Button. From here on, you can go to the top of the screen, click on Cart, make any payment(s) or use any coupons that you have in your account.
Then just sit back and wait for your new PCB to be delivered to your door via the shipping company that you have selected during checkout.
Desk or floor-standing fans are one of those appliances that will be present in almost every home or office. Some of the newer ones may already have remote control of some sort, while the older models won’t. It is however quite easy to do a retro-fitted controller to most of them, and at the same time, give them some (limited) intelligence.
Your typical oscillating fan does not have a lot of intelligence built-in. They normally consist of an electrical motor, with three separate windings, of varying inductance ( meaning the number of turns in the coil of wire will change the magnetic field generated, thereby changing the speed of the electric motor).
These windings have one common side, where all three of them are connected together, and the other three are separated. Normally the live wire from your mains supply (220v AC in my case) will go to this common connection. The neutral wire will go to the common of a four-position mechanical switch, with each winding going to one of positions 2,3 and 4 ( This results in a 3-speed configuration, with the first switch being off). It is also VERY important to note that this mechanical switch is hardware interlocked, meaning that ONLY one switch can be on at any given time… This is to ensure that electricity can only flow through one winding at a time. If you were to send electricity through multiple windings at the same time, the motor will still work, but not for very long…
In order to automate an oscillating fan, we would thus need a way to switch the separate windings on and off, while preventing other windings from getting power at the same time. I chose to do this with SPST relays, as a proof of concept, and plan to design it with DPDT relays at a later stage to implement a proper hardware interlock, in addition to the software interlock implemented in the control software ( more on that later)
My requirements for the device are the following: 1) Must operate from mains power, using the existing power cord of the fan. 2) Must allow for local operation of the fan using the existing control buttons. 3) Must be able to update firmware OTA, and have WiFi connectivity for control via Home Assistant or MQTT 4) Must be capable of adding support for ESP Now protocol at a later stage 5) The fan must not have any visible modifications on the outside
Taking all of my requirements into consideration, I have designed the following PCB to take care of my needs. As I do not require a lot of GPIO for this ( only 3 outputs, and 3 inputs ), I have decided to use an ESP8266-12E module from Espressif ( manufactured by AITinker, not sponsored by either company). This module is relatively cheap and has more than enough flash memory, RAM, as well as GPIO available.
As we can see, the circuit is minimal, with optical isolation on the relay drivers, a programming header, and a 3-way input for the mechanical switch.
As seen in the picture above, the wiring is quite simple, with the neutral wire looped to the common terminal of each relay (I had only green mains rated cable available, will replace it later with a proper white cable to keep to wiring standards). Black is live, with one wire going to the mains socket, and the other to the common of the motor coil windings. Light blue, yellow and white ( connected to the N/O terminal of the relays) corresponds to speeds 1, 2 and 3 of the fan.
At the top of the board, 3 wires go to the mechanical switch and a fourth to DC ground. (Note that there is no AC voltage on any of the switches. )
The PCB is mounted in the base of the fan while taking care to ensure that no AC cables are near the DC components. The ESP8266 chip is oriented to the side ( logo side of PCB ) to prevent interference to the WiFi signal. The mechanical switch is mounted into its original position, and its wires are routed away from any AC carrying wires to prevent interference.
It is important to note here that the firmware for the PCB was uploaded before assembly. You should NOT attempt serial uploading while the device is connected to mains power under any circumstances. ( While I have taken every precaution to ensure that AC and DC components of the circuit are separated from each other, it is just common sense to not try to upload firmware with mains connected)
Uploading firmware:
Initial uploading of firmware can be performed by connecting a USB-to-serial adapter to the UPLOAD port and providing 5v and ground from the USB-to-serial adapter. The flash button is held down, and the board is reset, after which you can proceed with uploading, alternatively, you can also connect the DTR and RTS lines from the serial adapter to automatically reset the board and enter flash mode as needed. ( If your adapter supports this of course).
ESPHome configuration
The YAML configuration for ESPHome is listed below:
This PCB was manufactured at PCBWAY. The Gerber files and BOM, as well as all the schematics, will soon be available as a shared project on their website. If you would like to have PCBWAY manufacture one of your own, designs, or even this particular PCB, you need to do the following… 1) Click on this link 2) Create an account if you have not already got one of your own. If you use the link above, you will also instantly receive a $5USD coupon, which you can use on your first or any other order later. (Disclaimer: I will earn a small referral fee from PCBWay. This referral fee will not affect the cost of your order, nor will you pay any part thereof.) 3) Once you have gone to their website, and created an account, or login with your existing account,
4) Click on PCB Instant Quote
5) If you do not have any very special requirements for your PCB, click on Quick-order PCB
6) Click on Add Gerber File, and select your Gerber file(s) from your computer. Most of your PCB details will now be automatically selected, leaving you to only select the solder mask and silk-screen colour, as well as to remove the order number or not. You can of course fine-tune everything exactly as you want as well.
7) You can also select whether you want an SMD stencil, or have the board assembled after manufacturing. Please note that the assembly service, as well as the cost of your components, ARE NOT included in the initial quoted price. ( The quote will update depending on what options you select ).
8) When you are happy with the options that you have selected, you can click on the Save to Cart Button. From here on, you can go to the top of the screen, click on Cart, make any payment(s) or use any coupons that you have in your account.
Then just sit back and wait for your new PCB to be delivered to your door via the shipping company that you have selected during checkout.
Why did I do this? Of all the various development boards in my electronics lab, surely the most versatile, but most neglected must be the STM32 Blue Pill. Not that there is anything wrong with it, It is a very very nice board, but unfortunately, there are a few issues ( mostly personal ) that make it not jump out at me for use in a new project.
Of these, and quite similar to the Arduino Nano, and original Raspberry Pi Pico is the fact that it was designed to be mostly used on a breadboard, issues with using the USB port, wrong components installed at the factories, and needing magnification to read port numbers, made me decide to solve it in my own way.
It is also not possible to use it (the original Blue-Pill) with any of the ready-made shields for the Arduino Nano, due to different pin-outs etc. Thus requiring a mess of wires and more modules on a breadboard, or lying free on the bench, to add sensors and other devices to this particular development board…
It can be argued that its small size does make it attractive, with which I definitely do not disagree, but unlike the bigger STM32 development boards with a lot of included peripherals, or the Arduino Ecosystem, where it is possible to develop your hardware prototypes on an Arduino Uno, using various shields, and then move on to a custom PCB later, the blue pill’s development cycle seems to be very much tied to the use of a breadboard and/or modules connected with jumper wires etc…
My idea was thus to take some inspiration from the bigger STM32 Nucleo and Discovery type platforms, add very detailed, and readable pin numbers, and peripheral descriptions, as well as lay a foundation onto which I can in future design stackable shields to expand the functionality of the device.
In order to make it easier for Makers and Hobby Electronics Enthusiasts, the new PCB was designed with 0805 SMD components. These are still quite easy to solder by hand, and usually do not require the use of any special equipment (That most beginners just starting out with the hobby won’t necessarily own or have access to by default). All of this was done with the hope that more people will start using this form factor, as well as to stimulate the development of shields and add-on cards to truly bring the blue pill to the same level regarding ease-of-use that the Arduino Ecosystem currently occupies.
What changes did I make?
The schematic diagram was not changed at all. All ports and pin numbers are 100% compatible with the original Blue Pill. Components sizes were changed from 0402 to 0805. I also made sure that the USB port would be functional, and would not require any modifications to be performed to make it useable (unlike some of the blue pill PCB’s available in Asia, which ships with a wrong value resistor at R10.
The PCB form factor has been changed to be the same size as the Arduino Uno, but with two rows of 20-pin 2.54mm headers. A more powerful 3.3v LDO regulator and additional smoothing capacitors were added. The main changes are to the silkscreen, where the pin numbering was enlarged to be more easily readable, and detailed labelling of the various possible peripherals were added. The board is also a single layer PCB, whereas the original was a double layer PCB, due to its small size.
Where and when can you get one?
The PCB is currently in production at PCBWay. When I have completed all testing of the PCB, it will be available as a PCBWay shared project, which means that you can order your own, or freely download the Manufacturing files to produce your own if you so choose. You can also contact me directly.
I plan to have completed all testing and to make available the manufacturing files, by the end of February 2022. Please be patient.
This PCB was manufactured at PCBWAY. The Gerber files and BOM, as well as all the schematics, will soon be available as a shared project on their website. If you would like to have PCBWAY manufacture one of your own, designs, or even this particular PCB, you need to do the following… 1) Click on this link 2) Create an account if you have not already got one of your own. If you use the link above, you will also instantly receive a $5USD coupon, which you can use on your first or any other order later. (Disclaimer: I will earn a small referral fee from PCBWay. This referral fee will not affect the cost of your order, nor will you pay any part thereof.) 3) Once you have gone to their website, and created an account, or login with your existing account,
4) Click on PCB Instant Quote
5) If you do not have any very special requirements for your PCB, click on Quick-order PCB
6) Click on Add Gerber File, and select your Gerber file(s) from your computer. Most of your PCB details will now be automatically selected, leaving you to only select the solder mask and silk-screen colour, as well as to remove the order number or not. You can of course fine-tune everything exactly as you want as well.
7) You can also select whether you want an SMD stencil, or have the board assembled after manufacturing. Please note that the assembly service, as well as the cost of your components, ARE NOT included in the initial quoted price. ( The quote will update depending on what options you select ).
8) When you are happy with the options that you have selected, you can click on the Save to Cart Button. From here on, you can go to the top of the screen, click on Cart, make any payment(s) or use any coupons that you have in your account.
Then just sit back and wait for your new PCB to be delivered to your door via the shipping company that you have selected during checkout.
After quite a few experiments, and playing with a lot of ideas, we have finally produced and tested an almost final prototype for the MCU-8266-12E IoT Controller Port Extender Card. While the baseboard already has quite a lot of free GPIO pins for additional sensors and devices, It did however have quite a few issues, namely a lack of sufficient Power outputs, difficulty access to the I2C bus, as well as only 2 relay outputs. Granted that you do have access to unused pins on the PCF8574 Port Extender, We nonetheless decided that an add-on card would definitely make sense to allow this device to really be more useable.
While looking at various ideas for this card, the most flexible seemed to be the APE Protocol device as documented in ESPHome. They used a standard Arduino board for that, but we decided that, after testing it with an Arduino Nano, since it seems to work well, let us just design a dedicated PCB. It also looks much better as well 🙂
Some Features (Aside from being a fully functional Arduino clone as well)
1). Dedicated LDO Regulators for 5v and 3.3v (800mA each), with jumpers to switch them on or off (receive power only from the IoT Motherboard). 2.) Dedicated Logic Level Converter on the I2C Bus ( This is sort of very much needed 🙂 The Atmega 328P-AU is running at 5v on this device, to enable it to run at 16Mhz.. and the ESP8266 on the Motherboard is a 3.3v device..
There are also 3x 3.3V I2C Headers, complete with 3.3v and Ground, as well as a single 5v I2C header 3). 8 Analog Inputs ( While practically you can only use 6 of these if you use I2C ) 4). Voltage Divider provided on A0 to measure VIN ( to be safe, we calculated the resistors for 22v) 5). 100R current limiting resistor on A1 and A2, to measure 5v and 3.3v as well… Analog inputs A0, A1 and A2 can be switched back to normal operation by changing the jumper at J2,J3 or J4 from On to Off. 6). 12 Digital Inputs/Outputs (14 if you use D0 and D1 as well), as well as a Jumper to remove the LED on D13. 7). Full access to the PCF8574 and ESP8266 Pins from the motherboard below.
Pictures of the PCB
Side by side MCU-8266-12E (left) 8266-12E-Port Extender (right)
Side by side MCU-8266-12E (left) 8266-12E-Port Extender (right)
Side by side MCU-8266-12E (left) 8266-12E-Port Extender (right) [ with unpopulated PCB at bottom]
Blank PCB 8266-12E-Port Extender
Blank PCB MCU-8266-12E IoT Controller
Top view 8266-12E PE
8266-12E-PE side view { from bottom)
Right side view – 8266-12E-PE
Left side view – 8266-12E-PE
Stacked on-top-of MCU-8266-12E
Stacked – Top Side view
Stacked – Right side view
Stacked – Left side view
Pictures of the PCB, alone and with the MCU-8266-12E IoT controller
Circuit Diagram
ATMega328P-AU Circuit diagram with LDO Regulators, headers and supporting circuitry.Analog measuring circuitry, level converters and supporting circuitry and headers
Uploading Code to the ATMega328P
Uploading code to the device requires the use of either an ISCP programmer ( Arduino as ISP works well ) or in the case of a pre-boot loaded chip, a USB-to-Serial converter. We did not find it necessary to add a dedicated USB-to-Serial converter onto the PCB. It is quite easy enough to do any flashing with the tools mentioned above.
Make sure that the PCB is not stacked when doing this. ( This will prevent excessive current use of other components when you supply 5v to the PE card.
Procedure to upload using ICSP
During assembly, you are required to solder a single 90-degree bend pin header on the bottom side of the PCB, in the same hole as the board side edge of the RESET push-button. This will serve as the RESET Pin for the ISCP. Other connections are as follows:
H2 Header <- > ICSP Programmer MOSI (E11~) – MOSI ( or Pin 11 on Arduino as ISP ) MISO (E12 ) – MISO ( or Pin 12 on Arduino as ISP ) SCK (E13) – D13 (or Pin 13 on Arduino as ISP ) RESET – D10 (or Pin 10 on Arduino as ISP )
5v and Ground from Arduino as ISP or ISCP Programmer to any 5v and ground pin on the PE Card
Please note the description above for assembly of the RESET pin header
Procedure to upload using USB-to-Serial converter
H1 Header
E0/Rx <- to Tx of USB-to-Serial converter E1/Tx -> to Rx of USB-to-Serial converter
H2 Header
DTR <-> to DTR of USB-to-Serial converter [ This connection is needed for successful uploading. Don’t leave it out ]
5v and Ground from the USB-to-Serial converter to any 5v and ground pin on the PE Card
Testing with ESPHome APE protocol and the MCU-8266-12E IoT controller
The following Arduino Sketch needs to be uploaded to the device. It will allow the device to function as a custom I2C device. Feel free to change the I2C address in the sketch as you choose, but remember to use the same address in your ESPHome YAML configuration file
The following C header file needs to be uploaded to your Home Assistant ESPHome folder.
// Must disable logging if using logging in main.cpp or in other custom components for the
// __c causes a section type conflict with __c thingy
// you can enable logging and use it if you enable this in logger:
/*
logger:
level: DEBUG
esp8266_store_log_strings_in_flash: False
*/
//#define APE_LOGGING
// take advantage of LOG_ defines to decide which code to include
#ifdef LOG_BINARY_OUTPUT
#define APE_BINARY_OUTPUT
#endif
#ifdef LOG_BINARY_SENSOR
#define APE_BINARY_SENSOR
#endif
#ifdef LOG_SENSOR
#define APE_SENSOR
#endif
static const char *TAGape = "ape";
#define APE_CMD_DIGITAL_READ 0
#define APE_CMD_WRITE_ANALOG 2
#define APE_CMD_WRITE_DIGITAL_HIGH 3
#define APE_CMD_WRITE_DIGITAL_LOW 4
#define APE_CMD_SETUP_PIN_OUTPUT 5
#define APE_CMD_SETUP_PIN_INPUT_PULLUP 6
#define APE_CMD_SETUP_PIN_INPUT 7
// 8 analog registers.. A0 to A7
// A4 and A5 not supported due to I2C
#define CMD_ANALOG_READ_A0 0b1000 // 0x8
// ....
#define CMD_ANALOG_READ_A7 0b1111 // 0xF
#define CMD_SETUP_ANALOG_INTERNAL 0x10
#define CMD_SETUP_ANALOG_DEFAULT 0x11
#define get_ape(constructor) static_cast<ArduinoPortExpander *>(constructor.get_component(0))
#define ape_binary_output(ape, pin) get_ape(ape)->get_binary_output(pin)
#define ape_binary_sensor(ape, pin) get_ape(ape)->get_binary_sensor(pin)
#define ape_analog_input(ape, pin) get_ape(ape)->get_analog_input(pin)
class ArduinoPortExpander;
using namespace esphome;
#ifdef APE_BINARY_OUTPUT
class ApeBinaryOutput : public output::BinaryOutput
{
public:
ApeBinaryOutput(ArduinoPortExpander *parent, uint8_t pin)
{
this->parent_ = parent;
this->pin_ = pin;
}
void write_state(bool state) override;
uint8_t get_pin() { return this->pin_; }
protected:
ArduinoPortExpander *parent_;
uint8_t pin_;
// Pins are setup as output after the state is written, Arduino has no open drain outputs, after setting an output it will either sink or source thus activating outputs writen to false during a flick.
bool setup_{true};
bool state_{false};
friend class ArduinoPortExpander;
};
#endif
#ifdef APE_BINARY_SENSOR
class ApeBinarySensor : public binary_sensor::BinarySensor
{
public:
ApeBinarySensor(ArduinoPortExpander *parent, uint8_t pin)
{
this->pin_ = pin;
}
uint8_t get_pin() { return this->pin_; }
protected:
uint8_t pin_;
};
#endif
#ifdef APE_SENSOR
class ApeAnalogInput : public sensor::Sensor
{
public:
ApeAnalogInput(ArduinoPortExpander *parent, uint8_t pin)
{
this->pin_ = pin;
}
uint8_t get_pin() { return this->pin_; }
protected:
uint8_t pin_;
};
#endif
class ArduinoPortExpander : public Component, public I2CDevice
{
public:
ArduinoPortExpander(I2CBus *bus, uint8_t address, bool vref_default = false)
{
set_i2c_address(address);
set_i2c_bus(bus);
this->vref_default_ = vref_default;
}
void setup() override
{
#ifdef APE_LOGGING
ESP_LOGCONFIG(TAGape, "Setting up ArduinoPortExpander at %#02x ...", address_);
#endif
/* We cannot setup as usual as arduino boots later than esp8266
Poll i2c bus for our Arduino for a n seconds instead of failing fast,
also this is important as pin setup (INPUT_PULLUP, OUTPUT it's done once)
*/
this->configure_timeout_ = millis() + 5000;
}
void loop() override
{
if (millis() < this->configure_timeout_)
{
bool try_configure = millis() % 100 > 50;
if (try_configure == this->configure_)
return;
this->configure_ = try_configure;
if (ERROR_OK == this->read_register(APE_CMD_DIGITAL_READ, const_cast<uint8_t *>(this->read_buffer_), 3))
{
#ifdef APE_LOGGING
ESP_LOGCONFIG(TAGape, "ArduinoPortExpander found at %#02x", address_);
#endif
delay(10);
if (this->vref_default_)
{
this->write_register(CMD_SETUP_ANALOG_DEFAULT, nullptr, 0); // 0: unused
}
// Config success
this->configure_timeout_ = 0;
this->status_clear_error();
#ifdef APE_BINARY_SENSOR
for (ApeBinarySensor *pin : this->input_pins_)
{
App.feed_wdt();
uint8_t pinNo = pin->get_pin();
#ifdef APE_LOGGING
ESP_LOGCONFIG(TAGape, "Setup input pin %d", pinNo);
#endif
this->write_register(APE_CMD_SETUP_PIN_INPUT_PULLUP, &pinNo, 1);
delay(20);
}
#endif
#ifdef APE_BINARY_OUTPUT
for (ApeBinaryOutput *output : this->output_pins_)
{
if (!output->setup_)
{ // this output has a valid value already
this->write_state(output->pin_, output->state_, true);
App.feed_wdt();
delay(20);
}
}
#endif
#ifdef APE_SENSOR
for (ApeAnalogInput *sensor : this->analog_pins_)
{
App.feed_wdt();
uint8_t pinNo = sensor->get_pin();
#ifdef APE_LOGGING
ESP_LOGCONFIG(TAGape, "Setup analog input pin %d", pinNo);
#endif
this->write_register(APE_CMD_SETUP_PIN_INPUT, &pinNo, 1);
delay(20);
}
#endif
return;
}
// Still not answering
return;
}
if (this->configure_timeout_ != 0 && millis() > this->configure_timeout_)
{
#ifdef APE_LOGGING
ESP_LOGE(TAGape, "ArduinoPortExpander NOT found at %#02x", address_);
#endif
this->mark_failed();
return;
}
#ifdef APE_BINARY_SENSOR
if (ERROR_OK != this->read_register(APE_CMD_DIGITAL_READ, const_cast<uint8_t *>(this->read_buffer_), 3))
{
#ifdef APE_LOGGING
ESP_LOGE(TAGape, "Error reading. Reconfiguring pending.");
#endif
this->status_set_error();
this->configure_timeout_ = millis() + 5000;
return;
}
for (ApeBinarySensor *pin : this->input_pins_)
{
uint8_t pinNo = pin->get_pin();
uint8_t bit = pinNo % 8;
uint8_t value = pinNo < 8 ? this->read_buffer_[0] : pinNo < 16 ? this->read_buffer_[1] : this->read_buffer_[2];
bool ret = value & (1 << bit);
if (this->initial_state_)
pin->publish_initial_state(ret);
else
pin->publish_state(ret);
}
#endif
#ifdef APE_SENSOR
for (ApeAnalogInput *pin : this->analog_pins_)
{
uint8_t pinNo = pin->get_pin();
pin->publish_state(analogRead(pinNo));
}
#endif
this->initial_state_ = false;
}
#ifdef APE_SENSOR
uint16_t analogRead(uint8_t pin)
{
bool ok = (ERROR_OK == this->read_register((uint8_t)(CMD_ANALOG_READ_A0 + pin), const_cast<uint8_t *>(this->read_buffer_), 2));
#ifdef APE_LOGGING
ESP_LOGVV(TAGape, "analog read pin: %d ok: %d byte0: %d byte1: %d", pin, ok, this->read_buffer_[0], this->read_buffer_[1]);
#endif
uint16_t value = this->read_buffer_[0] | ((uint16_t)this->read_buffer_[1] << 8);
return value;
}
#endif
#ifdef APE_BINARY_OUTPUT
output::BinaryOutput *get_binary_output(uint8_t pin)
{
ApeBinaryOutput *output = new ApeBinaryOutput(this, pin);
output_pins_.push_back(output);
return output;
}
#endif
#ifdef APE_BINARY_SENSOR
binary_sensor::BinarySensor *get_binary_sensor(uint8_t pin)
{
ApeBinarySensor *binarySensor = new ApeBinarySensor(this, pin);
input_pins_.push_back(binarySensor);
return binarySensor;
}
#endif
#ifdef APE_SENSOR
sensor::Sensor *get_analog_input(uint8_t pin)
{
ApeAnalogInput *input = new ApeAnalogInput(this, pin);
analog_pins_.push_back(input);
return input;
}
#endif
void write_state(uint8_t pin, bool state, bool setup = false)
{
if (this->configure_timeout_ != 0)
return;
#ifdef APE_LOGGING
ESP_LOGD(TAGape, "Writing %d to pin %d", state, pin);
#endif
this->write_register(state ? APE_CMD_WRITE_DIGITAL_HIGH : APE_CMD_WRITE_DIGITAL_LOW, &pin, 1);
if (setup)
{
App.feed_wdt();
delay(20);
#ifdef APE_LOGGING
ESP_LOGI(TAGape, "Setup output pin %d", pin);
#endif
this->write_register(APE_CMD_SETUP_PIN_OUTPUT, &pin, 1);
}
}
protected:
bool configure_{true};
bool initial_state_{true};
uint8_t read_buffer_[3]{0, 0, 0};
unsigned long configure_timeout_{5000};
bool vref_default_{false};
#ifdef APE_BINARY_OUTPUT
std::vector<ApeBinaryOutput *> output_pins_;
#endif
#ifdef APE_BINARY_SENSOR
std::vector<ApeBinarySensor *> input_pins_;
#endif
#ifdef APE_SENSOR
std::vector<ApeAnalogInput *> analog_pins_;
#endif
};
#ifdef APE_BINARY_OUTPUT
void ApeBinaryOutput::write_state(bool state)
{
this->state_ = state;
this->parent_->write_state(this->pin_, state, this->setup_);
this->setup_ = false;
}
#endif
The file should be named “arduino_port_expander.h”
Make the following changes to your ESPHome YAML configuration file for the MCU-8266-12E device
esphome:
name: mcu-8266-12e-01
platform: ESP8266
board: nodemcuv2
includes:
- arduino_port_expander.h
# Note the include file - This loads the APE Header
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
password: "<your password will be different - dont change it>"
wifi:
ssid: <your ssid>
password: <your password>
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "MCU-8266-Hotspot"
password: "password"
captive_portal:
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
time:
- platform: sntp
id: ha_time
timezone: "Etc/GMT+7"
status_led:
pin:
number: GPIO16
inverted: true
#Define the APE as a custom component, taking care to ensure that:
#1). The I2C Bust ID is the same as the one you have defined in the I2C: Section
#2). The address of the APE is the same as the one you set in the sketch
custom_component:
- id: ape
lambda: |-
auto ape_component = new ArduinoPortExpander(i2c_bus_a, 0x08,true);
return {ape_component};
sensor:
- platform: custom
lambda: |-
return {ape_analog_input(ape, 0), // 1 = A1
ape_analog_input(ape, 1),
ape_analog_input(ape, 2)};
#We define 3 analog inputs (A0,A1,A2) to monitor voltages on the card
#Note that you MUST define them in the sensors section below as well AND
#THAT THEY MUST BE IN THE SAME SEQUENCE THAT YOU DEFINED THEM IN ABOVE HERE
#
#ALSO NOTE THAT YOU CAN "NOT" use A4 and A5, as they are used for I2C !
#
# As an example, of adding another 3 analog inputs, your definition above will change to:
#
# return {ape_analog_input(ape, 0),
# ape_analog_input(ape, 1),
# ape_analog_input(ape, 2),
# ape_analog_input(ape, 3),
# ape_analog_input(ape, 6),
# ape_analog_input(ape, 7)};
#
#
# Now define the sensors connected to these analogs below:
sensors:
- name: "PE Card VIN"
id: analog_a0
device_class: "voltage"
unit_of_measurement: "v"
accuracy_decimals: 2
filters:
- lambda: return x * (22.00/1023.0);
- throttle: 60s
# We use a lambda to scale the value of VIN - Our Voltage divider was designed around 22 volt
# thus we need 22 volt here in the calculation as well to make it accurate
#
- name: "PE Card 5v"
id: analog_a1
device_class: "voltage"
unit_of_measurement: "v"
accuracy_decimals: 2
filters:
- lambda: return x * (5.02/1023.0);
- throttle: 60s
- name: "PE Card 3v"
id: analog_a2
device_class: "voltage"
unit_of_measurement: "v"
accuracy_decimals: 2
filters:
- lambda: return x * (5.02/1023.0);
- throttle: 60s
# The ATMega328P 's Analog Reference is set to 5v internally, thus we need to also scale the
# 3v input with a maximum of 5v ...
# In case you enabled the other 3 Analog Inputs above, you need to add the following
#
# - name: "Analog 3"
# id: analog_a3
# filters:
# - throttle: 60s
# - name: "Analog 6"
# id: analog_a6
# filters:
# - throttle: 60s
# - name: "Analog 7"
# id: analog_a7
# filters:
# - throttle: 60s
#
#
- platform: adc
pin: VCC
name: "ESP8266 Chip Voltage"
id: mcu_voltage
unit_of_measurement: "V"
device_class: "voltage"
accuracy_decimals: 2
update_interval: 60s
- platform: wifi_signal
name: "WiFi Signal Sensor"
id: wifi_strength
device_class: "signal_strength"
unit_of_measurement: "dBm"
update_interval: 240s
#Digital outputs function the same
output:
- platform: custom
type: binary
lambda: |-
return {ape_binary_output(ape, 2),
ape_binary_output(ape, 3),
ape_binary_output(ape, 4),
ape_binary_output(ape, 5),
ape_binary_output(ape, 6),
ape_binary_output(ape, 7)};
outputs:
- id: ape_output_p2
inverted: false
- id: ape_output_p3
inverted: false
- id: ape_output_p4
inverted: false
- id: ape_output_p5
inverted: false
- id: ape_output_p6
inverted: false
- id: ape_output_p7
inverted: false
- 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
- 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"
This PCB was manufactured at PCBWAY. The Gerber files and BOM, as well as all the schematics, will soon be available as a shared project on their website. If you would like to have PCBWAY manufacture one of your own, designs, or even this particular PCB, you need to do the following… 1) Click on this link 2) Create an account if you have not already got one of your own. If you use the link above, you will also instantly receive a $5USD coupon, which you can use on your first or any other order later. (Disclaimer: I will earn a small referral fee from PCBWay. This referral fee will not affect the cost of your order, nor will you pay any part thereof.) 3) Once you have gone to their website, and created an account, or login with your existing account,
4) Click on PCB Instant Quote
5) If you do not have any very special requirements for your PCB, click on Quick-order PCB
6) Click on Add Gerber File, and select your Gerber file(s) from your computer. Most of your PCB details will now be automatically selected, leaving you to only select the solder mask and silk-screen colour, as well as to remove the order number or not. You can of course fine-tune everything exactly as you want as well.
7) You can also select whether you want an SMD stencil, or have the board assembled after manufacturing. Please note that the assembly service, as well as the cost of your components, ARE NOT included in the initial quoted price. ( The quote will update depending on what options you select ).
8) When you are happy with the options that you have selected, you can click on the Save to Cart Button. From here on, you can go to the top of the screen, click on Cart, make any payment(s) or use any coupons that you have in your account.
Then just sit back and wait for your new PCB to be delivered to your door via the shipping company that you have selected during checkout.
Cytron Maker Pi RP2040 features the first microcontroller designed by Raspberry Pi – RP2040, embedded on a robot controller board. This board comes with a dual-channel DC motor driver, 4 servo motor ports and 7 Grove I/O connectors, ready for your next DIY robot/motion control project. Now you can build a robot while trying out the new RP2040 chip.
The DC motor driver on board is able to control 2x brushed DC motors or 1x bipolar/unipolar stepper motor rated from 3.6V to 6V, providing up to 1A current per channel continuously. The built-in Quick Test buttons and motor output LEDs allow a functional test of the motor driver in a quick and convenient way, without the need of writing any code. Vmotor for both DC and servo motors depends on the input voltage supplied to the board.
Maker Pi RP2040 features all the goodness of Cytron’s Maker series products. It too has lots of LEDs useful for troubleshooting (& visual effects), is able to make quite some noise with the onboard piezo buzzer and comes with push buttons ready to detect your touch.
There are three ways to supply power to the Maker Pi RP2040 – via USB (5V) socket, with a single cell LiPo/Li-Ion battery or through the VIN (3.6-6V) terminals. However, only one power source is needed to power up both controller board and motors at a time. Power supply from all these power sources can all be controlled with the power on/off switch onboard.
Cytron Maker Pi RP2040 is basically the Raspberry Pi Pico + Maker series’ goodness + Robot controller & other useful features. Therefore this board is compatible with the existing Pico ecosystem. Software, firmware, libraries and resources that are developed for Pico should work seamlessly with Cytron Maker Pi RP2040 too.
CircuitPython is preloaded on the Maker Pi RP2040 and it runs a simple demo program right out of the box. Connect it to your computer via USB micro cable and turn it on, you will be greeted by a melody tune and LEDs running light. Press GP20 and GP21 push buttons to toggle the LEDs on/off while controlling any DC and servo motors connected to it to move and stop. With this demo code, you get to test the board the moment you receive it!
While connected to your computer, a new CIRCUITPY drive appears. Explore and edit the demo code (code.py & lib folder) with any code editor you like, save any changes to the drive and you shall see it in action in no time. That’s why we embrace CircuitPython – it’s very easy to get started. Wish to use other programming languages? Sure, you are free to use MicroPython and C/C++ for Pico/RP2040. For those of you who love the Arduino ecosystem, please take a look at this official news by Arduino and also the unofficial Pico Arduino Core by Earle F. Philhower.
In August of 2021, MakerIoT2020 released the MCU-8266-12E IoT Controller PCB, (part 1 is available here in case you missed that). Shortly after that, we started working on an expansion add-on card, that would work with the APE (Arduino Port Expander) protocol in ESPHome.
While I could have used a standard Arduino board for this, and in fact, I have done so during many of the testing stages, I decided to design a custom PCB specifically for this task, in order to achieve two specific things…
1). The standard Arduino Board comes in either a 5v logic or 3v logic device. While this is perfect for many projects, it is still sometimes required to use a logic level converter with some sensors and devices. LORA is a good example of that. As I really dislike using a breadboard, due to their inherent unreliable connections and the ever-present mess of wires going everywhere, I wanted an Arduino or ATMEGA328 based device that already has a level converter built-in.
As I could not find anything like that for sale, I decided to build my own, as you will see shortly.
2). I wanted to start moving away from using the Arduino IDE as much as possible. While the Arduino IDE is great for most tasks, It does lack in a few areas. I thus want to slowly ease myself back into using AVR C, and that requires a board that can be flashed via ICSP. ( yes, yes, you can flash an Arduino with ICSP as well. ) In the case of the planned expansion card, it would basically be a device that is flashed once and then left alone. Serial flashing would be quite unnecessary on there anyway.
The other reason, still part of point 2, is that it seems like everyone else is having all sorts of problems with fuses on the ATMega328 on custom boards etc… I wanted to see if that is really the case or not…
The PCB should also be useable as a standard “Arduino” type device to assist in prototyping and development.
ATMega328P Custom PCB – as a prototype add-on card to the MCU-8266-12E IoT controller
a Quick description of the PCB:
Standard Arduino type headers and pins are provided, with pin labels as for the Arduino Nano. This gives us:
ATMega 328P MCU running at 16Mhz 12 Digital IO (D2 to D13) [ 14 if we use D1 and D2 as well ] 8 Analog Inputs (A0 to A7) [ A4 and A5 are used for I2C ] ICSP header for uploading code USB Port with CH340G for Arduino style serial flashing [This will be removed on the next version] A Dedicated LDO 3.3v Voltage regulator, with a selectable input source (5v from USB, or directly from VIN – for high current use applications – MAX of 800mA)
An 8 Channel Bi-Directional Logic Level Converter, for now, the converter is fixed at bi-directional 3v to 5v conversion. Additional 5v (x4), 3v (x4) and Ground pins (x8), as well as 2 general use bus connections (G1, G2) which I added for use with I2C
Led’s are provided on 5v, 3v, Serial Rx, Tx, as well as on pin D13.
Dimensions: 86mm x 51mm
Assembly – During Reflow on a hotplate.During Reflow
Manufacturing the PCB
This PCB was manufactured at PCBWAY. The Gerber files and BOM, as well as all the schematics, will soon be available as a shared project on their website. If you would like to have PCBWAY manufacture one of your own, designs, or even this particular PCB, you need to do the following… 1) Click on this link 2) Create an account if you have not already got one of your own. If you use the link above, you will also instantly receive a $5USD coupon, which you can use on your first or any other order later. (Disclaimer: I will earn a small referral fee from PCBWay. This referral fee will not affect the cost of your order, nor will you pay any part thereof.) 3) Once you have gone to their website, and created an account, or login with your existing account,
4) Click on PCB Instant Quote
5) If you do not have any very special requirements for your PCB, click on Quick-order PCB
6) Click on Add Gerber File, and select your Gerber file(s) from your computer. Most of your PCB details will now be automatically selected, leaving you to only select the solder mask and silk-screen colour, as well as to remove the order number or not. You can of course fine-tune everything exactly as you want as well.
7) You can also select whether you want an SMD stencil, or have the board assembled after manufacturing. Please note that the assembly service, as well as the cost of your components, ARE NOT included in the initial quoted price. ( The quote will update depending on what options you select ).
8) When you are happy with the options that you have selected, you can click on the Save to Cart Button. From here on, you can go to the top of the screen, click on Cart, make any payment(s) or use any coupons that you have in your account.
Then just sit back and wait for your new PCB to be delivered to your door via the shipping company that you have selected during checkout.
Conclusion
In conclusion, the PCB works quite well, with no issues with flashing the ATMEGA328P with an ICSP programmer from the Arduino IDE, as well as via USB from the Arduino IDE.
The level converter works as expected, successfully translating bidirectional signals on I2C and SPI to and from 3v and 5v devices.
In the next stage, we will focus on the stock APE protocol sketch, as provided by ESPHome, and then, once that is working perfectly, modify it to suit our needs.
By being a part of Makrverse, you are joining a community of Makers. Makrs are the tech enthusiasts who cannot wait to have their hands on the newest inventions, the early adopters, the innovators. Makrverse is the place for everyone who wants to be a part of a making universe.
MakerIoT2020 was recently contacted by the creators of this exciting new startup. The platform aims to connect Makers and Tech Enthusiasts, thereby solving the need to get hold of the latest gadgets directly from their inventors.
With the initial prototyping of my IoT Controller now completed, and software performing as expected, I have started with the development of an add-on shield. The base device offers 2 built-in relays, and access to another 6 IO Ports on the PCF8574, as well as all the GPIO on the ESP-12E. This is all good and well and suits my initial purposes well, but
I do however now see a need to add more sensors to the device, as well as find an elegant way to power it directly from mains power, while not having lots of wires going anywhere.
So the next steps will be:
Design an add-on-shield to provide me with the following: – Analog inputs. The ESP-12E has only one, and that will be very limiting in some situations. -Digital Inputs and Outputs While there are still unused GPIO ports on the existing board, native to the ESP-12E, having the ability to connect additional devices and sensors will definitely be a good option to have in future. -Some sort of Display Small OLED I2C displays are cheap and easy to use. I can also go full colour with an SPI display…
From here on, I have to decide on how and what. I can go the discreet chip route, by using dedicated I2C chips that provide all these functions, or I can add a secondary micro-controller to the shield, which would provide more flexibility, but can also add complexity to the final design…
Please follow along and join me on the next part of this design journey. I can not promise anything yet, but I do guarantee that it will be exciting…
Welcome to Part 3 of this build. If you are new to this series, Part1 and Part2 can be found by clicking on the respective links. Today, we will look at the completed PCB for our IoT Controller. Full disclosure, There are some issues, ranging from components that have still (15 days after being ordered, not been delivered), as well as 3 minor errors on the PCB ( That is entirely my fault ). We will look at how I have overcome the problems to still end up with a functionals PCB. Please note that the errors in the PCB Artwork have BEEN CORRECTED and that the version for public download does not contain any errors. You can thus order it with confidence.
During the design phase, I have forgotten to add a ground to the 5v regulator, and its supporting smoothing capacitors. These components were not initially included in my design, but, while added in later after I decided that since I will be designing the PCB to operate from many different voltage inputs, a reliable 5v source that is not dependent on USB power should be added… The components were added to the schematic, and I forgot to add the ground. It went undetected on the PCB design, as the Ground plane is a copper area…
In the picture above, you can see that I have temporarily fixed it with two wire links from the ground of C1, to the grounds of C10 and C11 respectively. These grounds connect back to U2.
C1 is another issue. Originally designed as a 100uf Electrolytic capacitor, I had to settle for a 10uf Tantalum. The reason being that the ordered capacitors are still floating in logistics space… with no definite ETA.
Error on I2C labelling, as well as I2C Pins at IC2
The following error was not so easy to spot. It gave me quite a headache to find. As I normally use netlabels on all the pins of any IC that I use, I have correctly labelled ESP12-E GPIO5 as SCL and GPIO4 as SDA. These netlabels were then transferred onto the PFC8574’s pins but in reverse! Note to self: Always re-read the pinout in the datasheet! To make matters worse, I flipped the SCL and SDA labels on the pin header…
How to fix: I am fortunate that the ESP12-E, like all other ESP Modules, does not have fixed I2C pins. If this was an Atmega based project, the boards would have been useless if tracks could not be cut and reconnected! On the ESP12-E, I2C is however software allocated to any desired GPIO pin. It was thus easily fixed by just swapping the two pins in software.
The third problem encountered is another logistics issue. This is in the process of being resolved, but, as you will soon see, is not actually a problem at all…
I have added support for an onboard USB to Serial converter, via a CH340G chip. The chip requires a 12Mhz resonator or crystal. My dear supplier accidentally sent me an 8 Mhz version. I have thus decided to depopulate the entire USB to Serial circuit, leaving just the USB Port and protection diode on the board. (To allow for powering via USB).
This does mean that programming the board becomes a little more complicated, connecting an external USB to Serial Adapter, and pressing and holding the flash button while pressing and releasing reset for each upload, followed by a manual reset afterwards. This is a pain, but, as I will be using these boards with ESPHome, only required once. All future uploads will be OTA anyway, and the correct components can be retrofitted when they arrive at a later stage.
Powering on the PCB
The PCB was first powered on with an external USB to serial converter and using the Arduino IDE, a simple sketch testing the I2C addressing of the chip, as well as the functioning of all onboard relays and LEDs.
The board was then flashed with ESPHome, using the procedure described in Part 1. I then proceeded to measure the current required by the board, to make sure that it is as designed.
Current Requirements Powered from 9V to 12V DC via the DC Barrel Connector
Standby, Wifi Connected to Home Assistant, All relays and LEDs off 75mA All relays energised, status LEDs all on 255mA
Integrating and Testing with EspHome and Home Assistant
The configuration for ESPHome was updated and uploaded to the device OTA. I decided to add a monitor for the VCC input of the ESP12-E, a remote Restart button, and an external DHT11 Temperature and Humidity sensor. The updated code is available below
esphome:
name: iot-controller-8266-01
platform: ESP8266
board: nodemcuv2
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
password: "2f8a73f47f1893f3f7baa391c4d0ba96"
wifi:
ssid: "<your ssid>"
password: "<your password>"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Iot-Controller-8266-01"
password: "y4aaH7vMITsC"
captive_portal:
#--- DO NOT COPY ANYTHING ABOVE THIS LINE ---
# when using this, you need to reassign the status LED to another GPIO
#deep_sleep:
# run_duration: 5min
# sleep_duration: 2min
i2c:
sda: GPIO5
scl: GPIO4
scan: true
id: i2c_bus_a
pcf8574:
- id: 'pcf8574_hub'
address: 0x22
pcf8575: false
status_led:
pin:
number: GPIO16
inverted: true
# Reassign this LED to another GPIO when using deep sleep mode !
sensor:
# Monitor VCC on the ESP12-E
- platform: adc
pin: VCC
name: "Device Input Voltage"
unit_of_measurement: "V"
# Monitor the WiFi Signal Strength at the device
- platform: wifi_signal
name: "WiFi Signal Sensor"
unit_of_measurement: "dBm"
update_interval: 240s
# Add Temperature and Humidity Sensor
- platform: dht
pin: GPIO2
temperature:
name: "Room Temperature"
unit_of_measurement: "°C"
icon: "mdi:temperature"
device_class: "temperature"
state_class: "measurement"
accuracy_decimals: 2
humidity:
name: "Room Humidity"
unit_of_measurement: "%"
icon: "mdi:water-percent"
device_class: "humidity"
state_class: "measurement"
accuracy_decimals: 2
update_interval: 60s
# Outputs to control relays and led's
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
# Monitor the two local control pushbuttons on the device
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
# Allow control from inside Home Assistant
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
# Add a remote Reboot switch
- platform: restart
name: "Reboot Me"
After uploading this configuration, Home Assistant was configured to reflect the changes.
Home Assistant showing the IoT Controller status ( EE Lab Area ) as well as Admin stats (Master Control Panel)
I have decided to split the different status and control outputs from the device into two cards, One in the EE Lab Area, which will later be moved into the actual room(s) where the device will be deployed, as well as on a Master Control Panel. From here, I can reboot individual devices, see their voltages and WiFi Status
Tasmota
As promised before, I did test the device with Tasmota. I had to do a custom compile to get support for the PCF8574. Performance was however VERY poor. ESPHome is snappy and quick, even in local mode. Tasmota seemed to have at least a one-second delay on doing anything. I thus abandoned it, and won’t be making use of it in this project anymore. The flexibility of ESPHome to do what I want, how I want it, is definitely missing in Tasmota. Hopefully, that will change in the future?
Order this PCB for yourself
You can order this PCB from PCBWay as a shared Project, by clicking here. New users will get a $5 USD coupon for use with their first order if they follow the link below to sign up for an account.
I would also like to thank Wendy at PCBWay for once again being a star. The project went smoothly and was very well produced. Make sure to consider using PCBWay for your next PCB order.
Conclusion and further steps
I am in the process of building and assembling another 2 of these devices. I have also ordered and received PolyCarbonate enclosures to mount them in. As this is an ongoing project, I still plan to add I2C temperature measurement chips to each, to measure the temperature inside the enclosure. An Air quality sensor, as well as a CO2 sensor, is also planned, with a possible Display Shield to provide test output locally at the device. This display, at the moment at least, is planned as an I2C Oled or similar. There are also plans to do an option to directly power the unit from 220V AC via an additional base-board for now, or a complete redesign, incorporating everything on one board. Thank you for following along, I hope that you found it educational and entertaining. Please consider joining us on Patreon. We are in the process of creating exclusive content for that platform, as well as for http://144.126.248.244. Most of the content will also remain free for all as usual.