When we are working on a prototype, we always need access to pushbuttons, encoders and even displays to test our ideas in the real world. This Multi-Purpose IO Card was designed to help me do just that…
What is on the PCB?
This PCB was designed with my particular work style in mind. I use a lot of I2C devices, IO Expanders, Displays and sensors. It would thus make sense to have I2C on the PCB, to control an OLED display, as well as a PCF8574 IO expander, that is used to drive a 4×4 Matrix Keypad. Two Rotary encoders, as well as another 4 standard push buttons completes the PCB…
The features, summarised is as follows:
1x Matrix Keypad (4×4) Controlled via an PCF8574 IO expander with selectable addressing. 1x SSD1306 OLED I2C Display 4x Momentary pushbuttons, configured to be used with internal pullups – i.e pushing the button pulls the GPIO LOW 2x Rotary Encoders, with integrated Pushbutton, also configured as Active LOW
The board has all of the connectors and jumpers on the back, making it possible to mount it to an enclosure as a control panel.
I have also provided an additional I2C header to make it possible to add additional devices to the I2C bus easily
The PCB in Detail
PCB Top
Starting from left to right, we have two push-buttons, an OLED display, with two rotary encoders below the display, and another two momentary push buttons. On the Right, we have a 4×4 matrix keypad, and various pin headers for connection to a microcontroller of your choice.
On the back, we have the PCF8574 IO expander for the Matric keypad, addressing Jumpers for the IO expander, as well as the two pin headers for connections to and from a microcontroller…
The Pinouts of these are as follows: Horizontal 15 pin 2.54mm connector SDA I2C Data SCA I2C Clock
RE2-D Rotary Encoder 2 Push Button RE2-B Rotary Encoder 2 Pin B RE2-A Rotary Encoder 2 Pin A
RE1-D Rotary Encoder 1 Push Button RE1-B Rotary Encoder 1 Pin B RE1-A Rotary Encoder 1 Pin A
GND VCC 3.3v to 5v DC
The Expansion header extends the I2C Bus, as well as proved access to the interrupt pin on the PCF8574. VCC and GND are also provided.
The Schematic
Manufacturing the PCB
I choose PCBWay for my PCB manufacturing. Why? What makes them different from the rest?
PCBWay‘s business goal is to be the most professional PCB manufacturer for prototyping and low-volume production work in the world. With more than a decade in the business, they are committed to meeting the needs of their customers from different industries in terms of quality, delivery, cost-effectiveness and any other demanding requests. As one of the most experienced PCB manufacturers and SMT Assemblers in China, they pride themselves to be our (the Makers) best business partners, as well as good friends in every aspect of our PCB manufacturing needs. They strive to make our R&D work easy and hassle-free.
How do they do that?
PCBWay is NOT a broker. That means that they do all manufacturing and assembly themselves, cutting out all the middlemen, and saving us money.
PCBWay’s online quoting system gives a very detailed and accurate picture of all costs upfront, including components and assembly costs. This saves a lot of time and hassle.
PCBWay gives you one-on-one customer support, that answers you in 5 minutes ( from the Website chat ), or by email within a few hours ( from your personal account manager). Issues are really resolved very quickly, not that there are many anyway, but, as we are all human, it is nice to know that when a gremlin rears its head, you have someone to talk to that will do his/her best to resolve your issue as soon as possible.
The assembly of this PCB was relatively easy, as it contains only a single SMD component. I do however have to alert you to a certain caveat…
On the PCB, the I2C OLED display pinout is, from left to right,
VCC GND SDC SDA
I have however come across similar displays that swap the GND and VCC pins… and some that even have SCL and SDA swapped…
It is thus quite important that you check your display BEFORE soldering it to this PCB…
Addressing the PCF8574 is also quite easy, with the jumper towards the top is a high, and towards the bottom is a low… They are marked A2 A1 A0 and thus, counting in binary, all low will be 0x20h and all high will be ox27h
Also, note that there are NO I2C Pullup resistors on the board. My microcontroller PCB’s usually have these already, and most I2C Sensors, including the OLED Display that we use, already include as well… You should thus check what you have on your own hardware, as it is quite impossible to cater for every situation… In a future version, I may add selectable pullup resistors onto this board as well…
Coding and Firmware
The possible uses of this board is quite broad, and the code possibilities are thus also quite extensive. Since I mainly use ESPHome or the Arduino IDE with most of my projects, I wont be including any specialised code here. I think it is enough to say that almost all of the available PCF8574 Matrix Keypad libraries available for the Arduino IDE will fork with this board…
The pinouts are important, and thus :
Row 0 – P0 Row 1 – P1 Row 2 – P2 Row 4 – P3
Col 0 – P7 Col 1 – P6 Col 2 – P5 Col 3 – P4
As far as ESPHome goes, you will need to 1) Add an I2c bus for your device 2)Add a PCF8574 component 3)Add a Matrix Keypad component, and refer the rows and columns to the pins on the PCF8574 – See below for an example of how I have done that in a previous project.
#I2C bus
i2c:
sda: 4
scl: 5
scan: true
id: I2C_Bus
#
# In my case, SDA is on GPIO4 and SCL is on GPIO5
# This is similar to the standard configuration on a NodeMCU v2 Dev board
#
#
# The next step is to configure the actual IO Expander, which in my case is located
# at address 0x27
#
#PCF8574
pcf8574:
- id: 'pcf8574_hub'
address: 0x27
pcf8575: false
#
# Now we can add the actual keypad interface to the YAML file
# Take note of the difference from the ESP32 file above.
#
#
#KEYPAD
matrix_keypad:
id: mykeypad
rows:
- pin:
pcf8574: pcf8574_hub
# Use pin number 0
number: 0
# In the ESP32 file, we wHereould specify a pin directly like:
#
# -pin: 17
#
# That approach will not work for us.
# The reason for that is that we have to redirect the GPIO to a
# physical pin on the PCF8574 IO expander.
#
# That is done with the following syntax
#
# - pin:
#pcf8574: pcf8574_hub -- This is the ID of the PCF8574 device -
#number: 0 -- The actual pin number
- pin:
pcf8574: pcf8574_hub
# Use pin number 0
number: 1
- pin:
pcf8574: pcf8574_hub
# Use pin number 0
number: 2
- pin:
pcf8574: pcf8574_hub
# Use pin number 0
number: 3
columns:
- pin:
pcf8574: pcf8574_hub
# Use pin number 0
number: 7
- pin:
pcf8574: pcf8574_hub
# Use pin number 0
number: 6
- pin:
pcf8574: pcf8574_hub
# Use pin number 0
number: 5
- pin:
pcf8574: pcf8574_hub
# Use pin number 0
number: 4
keys: "123A456B789C*0#D"
has_diodes: false
The Rotary encoders and momentary push-buttons can be handled in the same manner, using standard libraries in the Arduino IDE, or a rotary encoder component in ESPHome…
The OLED display would also be handled as above, with a DISPLAY component in ESPHome…
Summary and next steps
The next steps, for me at least, would be to design and CNC cut a suitable enclosure for the IO panel/Control panel in order to make it easier to use…
The panel was designed to be a tool to aid me while designing, and part of my never-ending battle getting rid of breadboards.
It does its job well, at least so far, and works as I have intended it to.
In a previous post this month I introduced my 4×4 matrix keypad. That keypad was designed to be directly interfaced to a microcontroller’s GPIO pins or alternatively to an IO expander chip like the PCF8574. That design, while working very well had the problem of requiring 8 GPIO pins to function correctly.
GPIO pins on a microcontroller can be considered very precious resources, and it should then be logical to assume that we should find a way to use these GPIO pins in a more conservative way, to allow us to interface more peripherals.
I solved this problem by integrating the keypad with an IO Expander on the same PCB. That will allow us to get away with using only 2 GPIO pins, and also open up the option of adding more keypads to the I2C bus, in the event that we need that many keys for a particular project.
The Schematic
I2C 4×4 Matrix Keypad Schematic
Looking closely at the schematic, we can see that it is exactly the same basic keypad circuit that I used in the initial design. The only difference is that in this design, I have integrated a PCF8574 directly onto the PCB.
Some additional features include selectable I2C Pullup resistors ( usually my microcontroller development boards already include those) that can be activated with a jumper when needed. There are also a set of address selection jumpers, making it possible to stack keypads together into a bigger keyboard if you require something like that. Note that, in this version of the hardware, I did not include headers for stacking.
The keypad can be powered by a DC power source of 3.3v to 5v.
The PCB
I2C Keypad PCB
3D Render of the I2C Keypad
The PCB is a double-layer board of 68.8mm x 50.8mm. Male header pins provide access to the connections as well as address and pullup resistor jumpers. In my build, I have mounted these male headers on the back of the PCB. That makes it possible to mount the Keypad in an enclosure without having the jumpers “stick out” and get in the way.
The top layer of the I2C Keypad PCBBottom Layer
Manufacturing
I choose PCBWay for my PCB manufacturing. This month, PCBWay is also celebrating its 9th anniversary, and that means that there are quite a lot of very special offers available.
Why? What makes them different from the rest?
PCBWay‘s business goal is to be the most professional PCB manufacturer for prototyping and low-volume production work in the world. With more than a decade in the business, they are committed to meeting the needs of their customers from different industries in terms of quality, delivery, cost-effectiveness and any other demanding requests. As one of the most experienced PCB manufacturers and SMT Assemblers in China, they pride themselves to be our (the Makers) best business partners, as well as good friends in every aspect of our PCB manufacturing needs. They strive to make our R&D work easy and hassle-free.
How do they do that?
PCBWay is NOT a broker. That means that they do all manufacturing and assembly themselves, cutting out all the middlemen, and saving us money.
PCBWay’s online quoting system gives a very detailed and accurate picture of all costs upfront, including components and assembly costs. This saves a lot of time and hassle.
PCBWay gives you one-on-one customer support, that answers you in 5 minutes ( from the Website chat ), or by email within a few hours ( from your personal account manager). Issues are really resolved very quickly, not that there are many anyway, but, as we are all human, it is nice to know that when a gremlin rears its head, you have someone to talk to that will do his/her best to resolve your issue as soon as possible.
The assembly of this PCB was quite easy and quick. A stencil is not required. All SMD components are 0805 or bigger. It would thus be quite easy to solder them all by hand with a fine-tipped soldering iron.
I have however used soldering paste and hot air to reflow the components, as it is the fastest, in my opinion, and definitely looks neater than hand soldering.
After placing SMD components onto solder paste – ready for reflow solderingAfter Reflow soldering with Hot Air
The board is now ready to solder the switches and header pins in place. As already mentioned above, I chose to assemble the headers on the back of the PCB to prevent them from interfering with any enclosure that I may later use with the keypad.
Final AssemblyNote that I assembled the headers onto the back of the PCB.
Testing and Coding
Testing the keypad consisted of a few steps, the first of which was ensuring that there were no short circuits, as well as that all the momentary switches worked. This was done with a multimeter in continuity as well as diode mode, with probes alternatively on each column and row in turn, while pressing the buttons.
The next stage was testing the I2C IO Expander. This was done with a simple I2C Scanning sketch on an Arduino Uno. It did not do a lot, but, I could see that the PCF8574 is responding to its address and that the pullup resistors work when enabled. This test was repeated with my own ESP8266 and ESP32 boards, this time with pullup resistors disabled, as these boards already have them onboard.
Coding came next, and it was another case of perspectives. It seems like all commercial keypads do not have diodes. This affects the way that they work with a given library. It seems that software developers and hardware developers have different understandings of what a row and a column is.
This meant that, due to the fact that I have diodes on each switch, and the way that the library work – which pins are pulled high and which are set as inputs -, I had to swap around my rows and columns in the software to get everything to work. On a keypad with the diodes replaced with 0-ohm links, that was not needed.
A short test sketch follows below:
Note that with was run on an ESP8266-12E, therefore the Wire.begin() function was changed to Wire.begin(4,5); in order to use GPIO 4 and GPIO 5 for I2C
Another point to note is that the keypad Layout will seem strange. Remember that this is due to the diodes in series on each switch. That forces us to swap around the Rows and the Columns in the software, resulting in a mirrored and rotated left representation of the keypad. It looks funny, but believe me, it actually still works perfectly.
#include <Wire.h>
#include "Keypad.h"
#include <Keypad_I2C.h>
const byte n_rows = 4;
const byte n_cols = 4;
char keys[n_rows][n_cols] = {
{'1', '4', '7', '*'},
{'2', '5', '8', '0'},
{'3', '6', '9', '#'},
{'A', 'B', 'C', 'D'}};
byte rowPins[n_rows] = {4, 5, 6, 7};
byte colPins[n_cols] = {0, 1, 2, 3};
Keypad_I2C myKeypad = Keypad_I2C(makeKeymap(keys), rowPins, colPins, n_rows, n_cols, 0x20);
String swOnState(KeyState kpadState)
{
switch (kpadState)
{
case IDLE:
return "IDLE";
break;
case PRESSED:
return "PRESSED";
break;
case HOLD:
return "HOLD";
break;
case RELEASED:
return "RELEASED";
break;
} // end switch-case
return "";
} // end switch on state function
void setup()
{
// This will be called by App.setup()
Serial.begin(115200);
while (!Serial)
{ /*wait*/
}
Serial.println("Press any key...");
Wire.begin(4,5);
myKeypad.begin(makeKeymap(keys));
}
char myKeyp = NO_KEY;
KeyState myKSp = IDLE;
auto myHold = false;
void loop()
{
char myKey = myKeypad.getKey();
KeyState myKS = myKeypad.getState();
if (myKSp != myKS && myKS != IDLE)
{
Serial.print("myKS: ");
Serial.println(swOnState(myKS));
myKSp = myKS;
if (myKey != NULL)
myKeyp = myKey;
String r;
r = myKeyp;
Serial.println("myKey: " + String(r));
if (myKS == HOLD)
myHold = true;
if (myKS == RELEASED)
{
if (myHold)
r = r + "+";
Serial.println(r.c_str());
myHold = false;
}
Serial.println(swOnState(myKS));
myKey == NULL;
myKS = IDLE;
}
}
Conclusion
This project once again delivered what I set out to achieve. It has some quirks, but nothing serious. Everything works as expected, both in the Arduino IDE/platform IO realm, as well as in ESPHome. It is worth noting that in ESPHome, we do not need to swap the rows and columns to use the Keypad component. Do remember to leave the has_diodes flag to false though…
Last month I spent quite a lot of time on expansion modules for use with the ESP-12E I2C Base Card. While the system worked exceptionally well as a prototyping and firmware testing platform ( as originally intended ), I immediately saw that the physical size of everything ( base board, with the cards) would be a problem inside any enclosure, when used with a real-world project.
At the same time, I have an ongoing need to design and manufacture a device for a friend, that will have very limited space inside the enclosure due to other essential components.
I have thus decided to combine the functionality of two of the IO Expander cards into a more compact design, on a single PCB ( Which I plan to use to power and control an Air Assist blower on my desktop CNC/Laser cutter, as well as function as a next step prototype for my other project.
The PCB
Let us take a quick look at the PCB.
Starting from the top left, we have the Blower/Fan Header. This supplies 12v DC to the Blower/Fan motor, as well as the PWM signal to control the speed. ( Level converted up from 5v DC to 12V, and then reduced to 3.3v ) This may seem strange.
Let me explain for some more clarity… The PWM input on the Blower/Fan is internally pulled HIGH to 12v ( by the motor driver circuitry – I can not change that, as it is a commercial unit.) The datasheet however calls for a 0v to 3.3v PWM signal to control the speed.
There is also a further input from the fan, which is a pulsed speed indicator (Fan RPM). This signal is 5v.
Next to that header, is a UART Header, with Rx, Tx and DTR signals, with a ground. I do no longer add USB-to-UART chips to my designs because they are not used a lot, take up unnecessary space, and I tend to program with ICSP anyway.
On the right of that, (Red/Blue/Yellow Header) are 5v, Gnd and 6 Analog inputs(A0-A3, A6,A7) [A4 and A5 being used for I2C]
The ICSP programming header is below that, with a jumper to select PCF8574 interrupt on Pin D2 or not
This is followed by 6 GPIO (P2-P7) from the IO Expander, and additional GPIO (D10, D11, D12, D13) , as well as (D7,D8,D9) [To be used with a Rotary Encoder]
Another 6way Ground header, as well as the 12v input (red), follows.
Finally, we have J1 and J2, which will switch 12v through BSS138 Mosfets to control static speed 12v cooling Fans (Only one of these is PWM capable)
The 2 Relays are optically isolated from the controller and mains isolation cutouts are provided to further keep DC and AC voltages well away from each other. [ they really don’t play well together, don’t they ?]
This wraps up the quick PCB description.
Schematic
The Schematic is below, along with a download link ( zip format, with PNG image files)
I use stencils with almost all of my SMD assembly. It saves a lot of time, makes for even solder paste application, and prevents the mess associated with applying solder paste with a syringe, or even worse a skewer-stick or something similar. They do cost extra though, but I find it well worthwhile in comparison to the mess and time that they save.
Manufacturing
Over the past eight years, PCBWay has continuously upgraded their MANUFACTURING plants and equipment to meet higher quality requirements, and now THEY also provide OEM services to build your products from ideas to mass production and access to the market.
The PCB for this project has been manufactured at PCBWay. Please consider supporting them if you would like your own copy of this PCB, or if you have any PCB of your own that you need to have manufactured.
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 $5 USD 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.
The I2C IO Card for ESP-12E I2C Base Card is another expander card for the ESP-12E I2C Base Card Project. This PCB is an address-selectable I2C module with two relays and six (6) GPIO pins, all driven from a single PCF8574 running at 3v. The relays are optically isolated, and generous mains isolation cutouts were provided to reduce the possibility of mains voltage tracking. A jumper to enable/disable the i2c pullup-resistors is also provided on the PCB.
The relays are powered from a single LDO regulator, accepting 12v DC from the 2x20pin female header on the bottom of the card. 3.3v and ground should also be applied to the card at the 2x20pin header.
It is worth mentioning that this circuit does not contain level converting circuitry and that the i2c bus thus runs at 3.3v to be compatible with ESP chips.
It is possible to use the card with other processors if the appropriate level converters are used on the i2c bus.
The Schematic
Manufacturing the PCB
Over the past eight years, PCBWay has continuously upgraded their MANUFACTURING plants and equipment to meet higher quality requirements, and now THEY also provide OEM services to build your products from ideas to mass production and access to the market.
The PCB for this project has been manufactured at PCBWay. Please consider supporting them if you would like your own copy of this PCB, or if you have any PCB of your own that you need to have manufactured.
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 $5 USD 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.
As part of my recent ESP-12E I2C Base Board project, I designed an ATMega 328P Based PWM controller card, that can be used as an add-on card with the existing project, or standalone as a custom Arduino Nano compatible development board.
What is on the PCB?
The PWM controller card contains standard Arduino Nano circuitry running at 16MHz, without the USB to Serial converter, as well as a 3v to 5v level converter on the I2C port ( A4 and A5 ), as well as another 12v to 5v level converter, with a build in resistor-divider circuit, used to drive a 12v blower with 3.3v PWM control circuitry.
All analog inputs are broken out to make attaching additional sensors easier.
All the other unused GPIO pins are also broken out, either directly to headers on the PCB (D6~,D7,D8,D9~), D11,D12,D12 (ISCP Header) and D3 ( Marked RPM on the Fan Header)
Most of these pins are also additionally broken out onto the 2x20p female header at the bottom of the card ( See schematic for more details)
The board is designed to be powered from 12v DC (via the VIN pins on the 2x20p header) which is internally regulated down to 5v via an LDO voltage regulator.
External 3.3v should also be supplied to the 2x20Pin header to enable the I2C level converters on the same header. I2C is not directly broken out onto the PCB in this version of the PCB.
A reset button, and power led, as well as the standard led on D13 is also provided.
Manufacturing the PCB
Over the past eight years, PCBWay has continuously upgraded their MANUFACTURING plants and equipment to meet higher quality requirements, and now THEY also provide OEM services to build your products from ideas to mass production and access to the market.
The PCB for this project has been manufactured at PCBWay. Please consider supporting them if you would like your own copy of this PCB, or if you have any PCB of your own that you need to have manufactured.
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 $5 USD 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.
As a follow-up on the ESP-12E Card, today we will look at the prototype base card that this was designed to slot into – The ESP-12E I2c Base Card.
Initial Features ( To be expanded in future versions )
4 x 40Pin Expansion slots, with access to 12v, 3.3v and Gnd on each slot. 2 x “IRQ” pins per slot ( serviced by a single PCF8574 ) I2C bus access on each slot (3.3v ) UART Header Reset and Flash Header GPIO Header ( Direct access to the ESP-12E GPIO Pins ) Analog Input Header (a Single input – A0, as per ESP-12E limitation) Buck Converter Power Supply Module, capable of up to 2A of current
Over the past eight years, PCBWay has continuously upgraded their MANUFACTURING plants and equipment to meet higher quality requirements, and now THEY also provide OEM services to build your products from ideas to mass production and access to the market.
The PCB for this project has been manufactured at PCBWay. Please consider supporting them if you would like your own copy of this PCB, or if you have any PCB of your own that you need to have manufactured.
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 $5 USD 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.
In this, part 3 of the “Giving new Life to an Old Toy Car” series, we will be adding some flashing lights to the toy car project. This will ultimately serve two purposes, with the most obvious being to give some life and excitement to the project ( as the final user will be a young boy of 7, the visual aspect is important). The second purpose is more obscured, and mostly only useable to programmers and coders, or those that will debug the project… The flashing lights will function as status indicators, at startup, as well as during the normal operation of the toy. Obviously, the diagnostic nature should be well obscured so as to not distract from the visual aspects.
A short test of the display unit, disguised as a “police-style” flasher unit
The flasher unit is made up of an extremely simple circuit, with only a PCF8574 IO expander, bypass capacitors, some LED lights, and current limiting resistors.
The bottom layer of the flasher unit, shows the Io expander, bypass capacitors, and current limiting resistors.The top layer is designed to be as clean as possible, with only LEDs and some labeling
Schematic
Schematic
The schematic is straightforward, with no surprises, consisting only of a few components, like the PCB8574, bypass capacitors, current limiting resistors, and of course the LEDs. It is also important to remember that I plan to use this entire robot car to teach a young boy to program microprocessors. I believe that visual is best, thus, all the lights 🙂
Coding
As this is still a project in quite a lot of development stages, I will not publish my exact code at this moment. You can however look forward to the future conclusion post, which will contain all my code at that stage. For now, however, we need to keep in mind that the PCF8574 is an I2C port expander, with an 8-bit IO port.
It is thus possible to do something simple like the below:
#include <Wire.h>
void setup() {
wire.begin();
wire.beginTransmission(0x20);
wire.write(0b11111111); // All LEDS off
// our circuit is sinking current into the io expander
wire.endTransmission();
delay(1000); // delay for illustration purposes, production code will use
// non blocking code
wire.beginTransmission(0x20);
wire.write(0b10100101); // All blue LED on
// our circuit is sinking current into the io expander
wire.endTransmission();
delay(1000);
}
void loop() {
}
Obviously, this is just a very quick example and is meant to just test functionality. Your own application will ultimately determine the exact code that you would need.
Manufacturing the PCB
The PCB for this project is currently on its way from China, after having been manufactured at PCBWay. Please consider supporting them if you would like your own copy of this PCB, or if you have any PCB of your own that you need to be manufactured.
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.
I2C port extenders or expanders are extremely useful devices, and I use quite a lot of them in my projects. My go-to device is definitely the PCF8574, mainly because it is sort of “breadboard friendly”. The MCP23017, with the existing breakouts available locally, are not. I have thus decided to design my own version of a breadboard friendly MCP23017 breakout board.
The Breakout Module PCB and its features
A breadboard friendly MCP23017 breakout board – Fronta breadboard friendly MCP23017 breakout board – Back
While this was definitely one of my easier projects, It still took a bit of time to get it just right and add some essential components and features directly onto the PCB.
The main features of this breakout: – DIP12 Layout – with all pins broken out, address pins to jumper headers… – Proper decoupling capacitors, as close as possible to the MCP23017 chip. I had to make use of the back layer of the PCB to do this, not exactly ideal, but with proper power and ground planes, and nice thick tracks, I believe they will be just fine.
– Address selector jumpers – The breakouts that are available locally, do not have these. – Breadboard friendly layout – 33.020mm x 20.320mm [board size], with 15.240mm vertical spacing between the rows of pins, ensures that you can easily fit it onto your breadboard, while still having space to add jumper wires to the pins. Horizontal pin spacing is standard 2.45mm.
The Schematic
The schematic is plain and simple. A few points to note though: – The address selection header, as well as the io pin headers are not shown on the schematic. – I2C pullup resistors are set at 1k but can be replaced with more suitable values as required in your circuit
The PCB for this project is currently on its way from China, after having been manufactured at PCBWay. Please consider supporting them if you would like your own copy of this PCB, or if you have any PCB of your own that you need to be manufactured.
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.
Sometimes we need extra Inputs or Outputs on a device, or for use with a project. To implement it properly we also need a lot of additional electronic components to properly isolate these inputs and outputs, with the signals they switch, from our own project, because, let us be real, electronics and electrical devices in the real world do not all work with Arduino or ESP32/ESP8266 save voltages ( 5v and 3.3v ).
I will also tell you about a very special deal to get PCBs of your own made for only one (1) USD ( Including shipping with DHL )! No, I am not joking, and I am not crazy either… More on that later in the post…
It is thus extremely important to have a module that can effectively interface with inputs of 5.5v up to 32v DC ( optically Isolated up to 3000v ), and relay outputs, also optically isolated at 3000v. ( Note that the optical isolation voltage does not mean you can input that voltage level into the chip! It means that it can isolate the electronics on the safe side of the isolator from a voltage spike of up to that voltage!).
I also love using I2C, as it allows me to add modules onto an existing data bus while using only 2 GPIO lines on the MCU!
The module I am presenting to you today was designed to be operated from 5v DC. That includes the I2C data lines (SDA and SCL). If you need to interface to a 3.3v microprocessor, like an ESP32 or ESP8266, or even the new RP2040 or an STM32, you need to use a logic level converter.
The PCB uses the popular PCF8574 8 channel IO expander, which is extremely easy to use, and where you can connect up to 8 devices in a chain ( 16 if you use the PCF8574AT variant as well.. Meaning eight of each variant) This surely adds up to quite a lot of IO lines at a cost of only 2 GPIO on your MCU!
The Circuit diagram is below, and I will discuss each part briefly.
Schematic – Page 1
This is the Galvanic Isolated Input schematic. Each input operates at a voltage of 5.5v to 32v DC. Complete Galvanic Isolation between the Module and the remote input is in effect. Please note that you have to supply a remote ground from the device that provides the input. DO NOT connect the PCB Module ground to an isolated ground pin. This may still work but renders the galvanic Isolation for that input completely useless.
Relay Driver Schematic
This is the Relay driver schematic. Each relay output is driven through an optocoupler, as well as a transistor. Although this arrangement does not provide complete galvanic Isolation of the relay coil, it does protect your MCU from any voltage spikes caused by back-emf when the relay is de-energised. The Relay contacts themselves, being magnetically actuated by the coil, are in themselves Galvanically Isolated from the rest of the PCB.
I2C Control Schematic
Finally, we have the I2C IO Expander schematic, with a 5v LDO regulator, capable of providing up to 600mA of current to the PCB. The PCF8574 Chip’s address is selectable with DipSwitch SW1 so that you can use multiple PCBs at the same time if you should choose to do so. The only note on that is that you should not connect the 5v lines of each individual PCB together. You should also only connect the GND and SDA, SCL lines back to the MCU.
Raw PCB Layout
Earlier on in the post, I promised to tell you about a very special deal…
Well, here it is, as well as some details about the sponsor of this very exciting deal…
PCBPartner.com is owned and operated by Kinji Group, which was established in 1997. We have over 20 years of experience in PCB manufacturing, PCB design, component manufacturing and distribution, PCB assembly and PCB cam software development.
While Kinji Group has 3 PCB factories in China, we have also developed strategic partnerships with more than 15 other factories around Asia. We, therefore, have a large group of specialists in PCB manufacturing, quality control, technical support and part sourcing to support your innovative ideas and products.
Our over 500 employees are spread across 8 branches in Mainland China (Shenzhen, Dongguan, Shanghai, Wuxi, Chengdu, Xiamen), Hong Kong SAR, and Taiwan. And we’re still growing!
We’re confident once you try us out, we’ll become your PCB Partner. And if not? Well, you’ll have scored some free PCB! So why not take us for a spin, you’ve got nothing to lose.
We, MakerIoT2020.com, have decided to give it a go and send this particular PCB to PCBPartner.com for manufacturing. So far, while we are still waiting to receive the PCB, ( Weekends happen 🙂 ), We are very happy with the ease of use of the online ordering system provided.
We would also like to point out that this special order will only be available until the end of March 2022, as well as that there are a few conditions:
Promotion ends March 31st 2022 Each new customer can enjoy free PCB on their first order This promotion applies to 1-2 layers of FR4 PCB, up to 100x100mm, 10pcs, with Green Solder Mask 4 layer of FR4 PCB, up to 50x50mm, 10pcs, with Green Solder Mask 1 layer Aluminum PCB, up to 100x100mm, 10pcs This PCB promotion cannot be used with other discounts or other promotional activities
For a full list of conditions, and countries that may participate in this offer, please click on the link here
Let us have a look at the entire ordering process..
Once you click on the PCBPartner.com link, you will be taken to their website, where you should sign up, which is free and easy… We used our Google.com account details and were ready to order in seconds…
FR4 PBC Quote Form – Before uploading your Gerber Files
Enter the specific details for the manufacturing of your PCB, and upload your Gerber files.
After uploading your Gerber Files.
Continue selecting options for your PCB order… Make sure to select DHL shipping, to take advantage of the special 1USD option, and click on the ADD to Cart Button…
Quote added to your shopping cart.
You will now get a message that your enquiry has been submitted successfully.
Click on the “Under review” button, to see your quote status… In my case, it took about 5 minutes for the review to pass, and be able to checkout and pay for the order…
PCB order under review
Once the review has passed, you will see a pending payment,
Payment Pending
You may now click on the “Proceed to Payment” option
Add your shipping address, and choose your payment option.
At this moment in time, only two payment options are supported, Paypal ( as well as Debit and Credit cards) and Direct Bank Transfer. I believe more options will be made available in future.. Checkout with Paypal
In my case, I chose Paypal and paid by Debit card.
Enter your card detailsAfter Payment.
After payment was made successfully, you can also check on the status of your order…
Review your order status
You can also review your order at any stage before or after payment, as well as get progress reports of the manufacturing process.
PCB Order Status.
In conclusion, I would like to say that it was quite easy to order and make payment. The Website is easy to use, and everything is clear and easy to understand. The PCB was well manufactured and seems to be quite good quality
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 🙂
The beginning of the APE (Arduino Port Extender) Device. MCU-8266-12E with Arduino Nano (left) and MCU-8266-12E with the newly designed APE Card (right)
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.