Community project

C Th Thi T K Pcb Theo Y

ESP32
Photo of C Th Thi T K Pcb Theo Y
Generated with AI

hung le

Published September 19, 2026

This ESP32-based control panel integrates a 4x4 matrix keypad, 16x2 LCD display, and RS485 communication on a single PCB. The keypad input is managed through an I2C expander, the display connects via I2C backpack, and RS485 enables networked communication with external devices. The design includes proper level translation between 5V and 3.3V logic domains and a regulated power supply.

This guide provides a complete wiring diagram, bill of materials, and step-by-step assembly instructions for building the PCB in KiCad. Included firmware demonstrates keypad scanning with debouncing, LCD output, and RS485 transmission, giving makers a fully functional starting point for industrial control, data entry, or remote monitoring applications.

Wiring diagram

Gather all the parts

QtyComponent
1

PCF8574T I2C Keypad Expander

PCF8574T, SOIC-16; A0–A2 = GND, address 0x20

IC mở rộng tám chân để quét bàn phím 4×4 qua hai dây I2C.

1

4x4 Matrix Keypad

4×4, 8-pin ribbon

A 16-button (4 rows × 4 columns) membrane matrix keypad that uses 8 digital I/O lines (4 row + 4 column) to scan all keys. No dedicated power rail is required — rows and columns are driven directly by GPIO. Compatible with the Arduino Keypad library.

1

LCD1602 with I2C Backpack

16×2, address 0x27

Màn hình LCD 16 ký tự × 2 dòng đặt ở mặt trước vỏ và nối với bo bằng dây bus bốn lõi.

1

PCA9306 I2C Level Translator

PCA9306DCUR, VSSOP-8

Mạch dịch mức hai chiều, giữ đường I2C của ESP-07 ở 3,3 V trong khi LCD ngoài vỏ dùng 5 V.

1

MAX3485 RS485 Transceiver

MAX3485ESA+, SOIC-8

The 3.3 V chip that safely changes ESP serial signals into long-distance RS485 cable signals.

1

TPS62162 3.3 V buck regulator

TPS62162DSGR, WSON-8; 1 A buck

Bộ nguồn xung 3,3 V hiệu suất cao cấp dòng ổn định cho ESP-07 và các mạch logic.

1

5V Power Input Terminal

2-pin, 5.08 mm

Đầu nối hai chân nhận nguồn DC 5 V ổn định từ nguồn ngoài của hệ thống.

1

RS485 Terminal Block

3-pin, 5.08 mm

Đầu nối ba chân để đưa A, B và mass tham chiếu của RS485 ra ngoài vỏ.

1

8-pin Keypad Header

1×8, 2.54 mm

Đầu cắm 2,54 mm tám chân nhận trực tiếp cáp bẹ tiêu chuẩn của bàn phím màng 4×4.

1

4-pin LCD Bus Header

1×4, 2.54 mm

Đầu nối bốn chân ở mép bo để nối LCD1602 I2C trong vỏ bằng dây bus.

1

6-pin UART Programming Header

1×6, 2.54 mm

The maintenance connector for a 3.3 V USB-to-UART adapter and automatic firmware loading.

1

Reset Tactile Switch

6×6 mm tactile

Nút nhấn bảo trì kéo chân reset của ESP xuống mass để khởi động lại.

1

Flash Tactile Switch

6×6 mm tactile

Nút nhấn bảo trì kéo GPIO0 xuống mass để vào chế độ nạp firmware.

1

10 kΩ GPIO0 pull-up resistor

10 kΩ, 1%, 0603

A resistor that keeps GPIO0 high so the ESP-07 starts normally until the FLASH button is pressed.

1

10 kΩ GPIO2 pull-up resistor

10 kΩ, 1%, 0603

A resistor that keeps GPIO2 high during ESP-07 startup.

1

10 kΩ GPIO15 pull-down resistor

10 kΩ, 1%, 0603

A resistor that keeps GPIO15 low during ESP-07 startup.

1

4.7 kΩ I2C SDA pull-up resistor

4.7 kΩ, 1%, 0603

A resistor that holds the shared I2C data line at a safe 3.3 V level.

1

4.7 kΩ I2C SCL pull-up resistor

4.7 kΩ, 1%, 0603

A resistor that holds the shared I2C clock line at a safe 3.3 V level.

1

RS485 termination resistor

120 Ω, 1%, 0805; fit through solder jumper SJ1

A 120 ohm resistor fitted only when this board is at the end of the RS485 cable.

4

100 nF ceramic decoupling capacitors

100 nF, X7R, 0603

Four small capacitors placed beside the IC power pins to absorb electrical noise.

2

10 µF ceramic bulk capacitors

10 µF, X7R, 0805

Two capacitors that steady the 5 V input and 3.3 V rail when Wi-Fi transmission draws a short current surge.

1

10 kΩ EN pull-up resistor

10 kΩ, 1%, 0603

A resistor that enables the ESP-07 whenever the board has power.

1

10 kΩ reset pull-up resistor

10 kΩ, 1%, 0603

A resistor that keeps the ESP-07 reset pin high during normal use.

1

MMBT3904 auto-flash transistor

MMBT3904, SOT-23

A small transistor that lets the programming adapter pull GPIO0 low for automatic firmware loading.

1

MMBT3904 auto-reset transistor

MMBT3904, SOT-23

A small transistor that lets the programming adapter reset the ESP-07 automatically.

1

10 kΩ DTR base resistor

10 kΩ, 1%, 0603

A resistor that limits current from the programming adapter DTR line into the auto-flash transistor.

1

10 kΩ RTS base resistor

10 kΩ, 1%, 0603

A resistor that limits current from the programming adapter RTS line into the auto-reset transistor.

1

100 nF reset filter capacitor

100 nF, X7R, 0603

A capacitor that filters brief noise pulses from the reset line.

1

Resettable input fuse

1206L050, hold 0.50 A

Cầu chì tự phục hồi ngắt dòng khi nguồn vào bị chập hoặc đấu lỗi để bảo vệ bo mạch.

1

5 V input TVS diode

SMBJ5.0A, SMB

Diode dập xung bảo vệ đường 5 V khỏi xung điện áp ngắn từ dây nguồn bên ngoài.

1

RS485 surge protection diode array

SM712, SOIC-8

Mảng diode bảo vệ hai dây RS485 khỏi tĩnh điện và xung điện đi vào từ cáp dài.

1

LCD-side I2C pull-up resistor network

2× 4.7 kΩ, 1%, 0603

Hai điện trở kéo SDA và SCL phía LCD lên 5 V để bus qua dây ngoài có mức tín hiệu rõ ràng.

1

Buck regulator power inductor

2.2 µH, shielded, ≥1.5 A, 5×5 mm

Cuộn cảm công suất làm việc cùng nguồn xung để tạo ra đường 3,3 V ổn định, ít nóng hơn mạch ổn áp tuyến tính.

1

Buck regulator input capacitor

10 µF, 10 V, X7R, 0805

Tụ gốm đặt sát chân vào nguồn xung để hấp thụ xung dòng và giữ đường 5 V ổn định.

1

Buck regulator output capacitor

22 µF, 6.3 V, X7R, 0805

Tụ gốm đặt sát đầu ra nguồn xung để đường 3,3 V không sụt khi ESP-07 phát Wi-Fi.

Assemble it in 6 steps

1. Đặt khung bo hai lớp trong KiCad

Tạo board outline đúng 69,0 mm × 25,0 mm trên Edge.Cuts; dùng FR-4 hai lớp, dày 1,6 mm, đồng 1 oz và HASL chì hoặc ENIG. Dành khoảng 8 mm đầu bo cho ESP-07 và đầu U.FL anten ngoài: không đổ đồng, không đi track, không đặt via hay linh kiện dưới hoặc ngay trước vùng anten của module.

  • Ghi rõ mã board và revision trên F.SilkS, ví dụ QUEUE-ESP07-R1.
  • Đặt hai lỗ bắt vít M2 nếu vỏ còn đủ chỗ; giữ lỗ vít ngoài vùng anten và ngoài đường RS485.
  • Đồng hoặc đường mạch sát anten làm Wi-Fi yếu và khó đoán, dù mạch vẫn có thể khởi động bình thường.

2. Vẽ khối nguồn 5 V và 3,3 V

Nối đầu vào +5V qua cầu chì tự phục hồi vào net +5V_PROT; TVS 5 V nối từ +5V_PROT xuống GND. Đặt tụ đầu vào 10 µF sát chân VIN/GND của TPS62162. Nối chân SW của TPS62162 đến cuộn cảm 2,2 µH bằng đường thật ngắn; đầu kia cuộn cảm là net +3V3, có tụ 22 µF sát GND. TPS62162DSGR là bản 3,3 V cố định; nối FB xuống AGND theo khuyến nghị datasheet hoặc để hở theo datasheet, không tự thêm cầu phân áp. Kéo EN lên VIN để nguồn luôn bật.

  • Dùng trace nguồn 5 V và 3,3 V rộng ít nhất 0,5 mm; đoạn VIN–IC–GND–tụ đầu vào cần ngắn nhất có thể.
  • Tạo một vùng GND gần như kín mặt đáy; khâu via GND quanh khối buck nhưng không tạo vòng đồng dưới vùng anten.
  • Không kéo đường SW dài hoặc chạy dưới ESP-07, keypad hay I2C — xung chuyển mạch của buck có thể gây nhiễu.

3. Vẽ ESP-07, boot và cổng nạp

Đặt ESP-07 sát cạnh board, đầu nối U.FL hướng ra cạnh vỏ dễ gắn anten ngoài. Kéo EN, RST, GPIO0 và GPIO2 lên +3V3 bằng 10 kΩ; kéo GPIO15 xuống GND bằng 10 kΩ. RESET là nút nối RST xuống GND; FLASH là nút nối GPIO0 xuống GND. Header bảo trì theo thứ tự DTR, RXD, TXD, 3V3, RTS, GND; RXD header nối TXD/GPIO1 của ESP và TXD header nối RXD/GPIO3. Hai MMBT3904 kéo GPIO0 và RST xuống GND theo DTR/RTS qua điện trở base 10 kΩ.

  • Đặt tụ 100 nF và tụ khối 10 µF gần chân cấp nguồn ESP-07.
  • Đặt RESET và FLASH sát mép bo để chạm được khi bo đã nằm trong vỏ.
  • Chỉ dùng USB-to-UART mức logic 3,3 V; mức 5 V tại RXD hoặc GPIO có thể hỏng ESP-07.

4. Vẽ keypad và bus LCD ngoài

Nối GPIO4/SDA và GPIO5/SCL với PCF8574T, mỗi đường có điện trở kéo lên 4,7 kΩ về +3V3. Đặt A0, A1, A2 của PCF8574T xuống GND để địa chỉ keypad là 0x20. Nối P0–P7 lần lượt đến header keypad R1, R2, R3, R4, C1, C2, C3, C4. PCA9306 có VREF1 = +3V3, VREF2 = +5V, GND chung và EN kéo lên +3V3; phía LCD của SDA/SCL được kéo lên +5V bằng 4,7 kΩ. Header LCD ghi rõ GND, +5V, SDA, SCL.

  • Đặt đầu keypad và LCD sát mép bo theo hướng dây đi vào vỏ để không bị gập cáp.
  • Dùng cáp LCD ngắn; với cáp dài, chọn cáp có các dây GND xen kẽ hoặc giảm tốc độ I2C trong firmware.
  • Không nối trực tiếp SDA/SCL 5 V từ LCD vào GPIO4/GPIO5; bộ PCA9306 là lớp bảo vệ bắt buộc.

5. Vẽ RS485 có bảo vệ

Nối TXD/GPIO1 đến DI, RXD/GPIO3 đến RO của MAX3485; chập DE và RE rồi nối GPIO12. Đặt SM712 sát terminal A/B, sau đó đi A/B tới MAX3485 dạng cặp song song ngắn. Dùng jumper hàn SJ1 nối điện trở 120 Ω giữa A và B để chỉ đóng khi board ở đầu tuyến RS485. Đưa A, B và GND ra terminal ba chân.

  • Ghi A, B, GND thật lớn trên silkscreen; thiết bị RS485 khác hãng đôi khi đổi tên A/B, nên kiểm tra thực tế khi nghiệm thu.
  • Đặt terminal RS485 ở mép đối diện vùng anten và tách khỏi khối buck.
  • Chỉ hàn SJ1 ở một trong hai đầu vật lý của tuyến dây RS485; đóng ở mọi nút làm tín hiệu yếu đi.

6. Kiểm tra trước khi xuất bộ hồ sơ sản xuất

Trong KiCad chạy ERC cho schematic và DRC cho PCB; tạo Net Class nguồn tối thiểu 0,5 mm, tín hiệu thông thường 0,20–0,25 mm theo khả năng xưởng. Xuất Gerber, Excellon drill, BOM, pick-and-place, PDF schematic và drawing ghi stackup hai lớp. Trước khi lắp hàng loạt, lắp 3 đến 5 board pilot rồi đo +3V3, nạp firmware và thử keypad, LCD, Wi-Fi và RS485.

  • Thêm test point cho +5V_PROT, +3V3, GND, RST, GPIO0, TXD, RXD, SDA và SCL.
  • Với nhà máy, gửi cả file .kicad_sch/.kicad_pcb nguồn, không chỉ Gerber, để dễ đối chiếu revision.
  • Đừng đưa board vào sản xuất hàng loạt chỉ vì ERC không báo lỗi: phải đo điện áp 3,3 V và thử nạp/khởi động trên board pilot trước.

Review all connections

1. Connections between "power_input" and "ESP32"

Functionpower_inputESP32
groundGNDGND
power+5VResettable input fuse INEXT

2. Connections between "regulator_3v3" and "ESP32"

Functionregulator_3v3ESP32
powerVIN5V
groundGNDGND
powerSWBuck regulator power inductor SWEXT
powerVOUT3V3

3. Connections between "keypad_expander" and "ESP32"

Functionkeypad_expanderESP32
powerVCC3V3
groundGNDGND
digitalP08-pin Keypad Header R1EXT
digitalP18-pin Keypad Header R2EXT
digitalP28-pin Keypad Header R3EXT
digitalP38-pin Keypad Header R4EXT
digitalP48-pin Keypad Header C1EXT
digitalP58-pin Keypad Header C2EXT
digitalP68-pin Keypad Header C3EXT
digitalP78-pin Keypad Header C4EXT
i2cSDAPCA9306 I2C Level Translator SDA1EXT
i2cSCLPCA9306 I2C Level Translator SCL1EXT

4. Connections between "keypad_header" and "ESP32"

Functionkeypad_headerESP32
digitalR14x4 Matrix Keypad R1EXT
digitalR24x4 Matrix Keypad R2EXT
digitalR34x4 Matrix Keypad R3EXT
digitalR44x4 Matrix Keypad R4EXT
digitalC14x4 Matrix Keypad C1EXT
digitalC24x4 Matrix Keypad C2EXT
digitalC34x4 Matrix Keypad C3EXT
digitalC44x4 Matrix Keypad C4EXT

5. Connections between "lcd1602_i2c" and "ESP32"

Functionlcd1602_i2cESP32
powerVCC5V
groundGNDGND
i2cSDA4-pin LCD Bus Header SDAEXT
i2cSCL4-pin LCD Bus Header SCLEXT

6. Connections between "lcd_header" and "ESP32"

Functionlcd_headerESP32
groundGNDGND
power+5V5V

7. Connections between "i2c_level_translator" and "ESP32"

Functioni2c_level_translatorESP32
powerVREF13V3
powerVREF25V
groundGNDGND
i2cSDA1GPIO 4
i2cSCL1GPIO 5
i2cSDA24-pin LCD Bus Header SDAEXT
i2cSCL24-pin LCD Bus Header SCLEXT

8. Connections between "rs485" and "ESP32"

Functionrs485ESP32
powerVCC3V3
groundGNDGND
digitalDEGPIO 12
uartDI6-pin UART Programming Header RXDEXT
uartRO6-pin UART Programming Header TXDEXT
digitalREMAX3485 RS485 Transceiver DEEXT
dataARS485 Terminal Block AEXT
dataBRS485 Terminal Block BEXT

9. Connections between "rs485_terminal" and "ESP32"

Functionrs485_terminalESP32
groundGNDGND

10. Connections between "uart_header" and "ESP32"

Functionuart_headerESP32
dataDTR10 kΩ DTR base resistor AEXT
uartRXDGPIO 1
uartTXDGPIO 3
power3V33V3
dataRTS10 kΩ RTS base resistor AEXT
groundGNDGND

11. Connections between "reset_button" and "ESP32"

Functionreset_buttonESP32
groundGNDGND

12. Connections between "flash_button" and "ESP32"

Functionflash_buttonESP32
groundGNDGND

13. Connections between "r_gpio0_pullup" and "ESP32"

Functionr_gpio0_pullupESP32
powerA3V3
digitalBMMBT3904 auto-flash transistor CEXT

14. Connections between "r_gpio2_pullup" and "ESP32"

Functionr_gpio2_pullupESP32
powerA3V3
digitalBGPIO 2

15. Connections between "r_gpio15_pulldown" and "ESP32"

Functionr_gpio15_pulldownESP32
digitalAGPIO 15
groundBGND

16. Connections between "r_i2c_sda" and "ESP32"

Functionr_i2c_sdaESP32
powerA3V3
i2cBPCF8574T I2C Keypad Expander SDAEXT

17. Connections between "r_i2c_scl" and "ESP32"

Functionr_i2c_sclESP32
powerA3V3
i2cBPCF8574T I2C Keypad Expander SCLEXT

18. Connections between "rs485_termination" and "ESP32"

Functionrs485_terminationESP32
dataARS485 Terminal Block AEXT
dataBRS485 Terminal Block BEXT

19. Connections between "decoupling_100nf" and "ESP32"

Functiondecoupling_100nfESP32
powerVCC3V3
groundGNDGND

20. Connections between "bulk_caps" and "ESP32"

Functionbulk_capsESP32
powerVCC3V3
groundGNDGND

21. Connections between "r_en_pullup" and "ESP32"

Functionr_en_pullupESP32
powerA3V3
digitalBGPIO 16

22. Connections between "r_rst_pullup" and "ESP32"

Functionr_rst_pullupESP32
powerA3V3
digitalBMMBT3904 auto-reset transistor CEXT

23. Connections between "q_flash_auto" and "ESP32"

Functionq_flash_autoESP32
digitalB10 kΩ DTR base resistor BEXT
groundEGND
digitalCFlash Tactile Switch GPIO0EXT

24. Connections between "q_reset_auto" and "ESP32"

Functionq_reset_autoESP32
digitalB10 kΩ RTS base resistor BEXT
groundEGND
digitalC100 nF reset filter capacitor RSTEXT

25. Connections between "rst_cap" and "ESP32"

Functionrst_capESP32
groundGNDGND
digitalRSTReset Tactile Switch RSTEXT

26. Connections between "input_fuse" and "ESP32"

Functioninput_fuseESP32
powerOUTTPS62162 3.3 V buck regulator VINEXT

27. Connections between "input_tvs" and "ESP32"

Functioninput_tvsESP32
powerKResettable input fuse OUTEXT
groundAGND

28. Connections between "buck_inductor" and "ESP32"

Functionbuck_inductorESP32
powerVOUT3V3

29. Connections between "buck_input_cap" and "ESP32"

Functionbuck_input_capESP32
powerVINResettable input fuse OUTEXT
groundGNDGND

30. Connections between "buck_output_cap" and "ESP32"

Functionbuck_output_capESP32
powerVOUT3V3
groundGNDGND

31. Connections between "rs485_tvs" and "ESP32"

Functionrs485_tvsESP32
dataARS485 Terminal Block AEXT
dataBRS485 Terminal Block BEXT
groundGNDGND

32. Connections between "i2c_lcd_pullups" and "ESP32"

Functioni2c_lcd_pullupsESP32
powerVCC5V
i2cSDA4-pin LCD Bus Header SDAEXT
i2cSCL4-pin LCD Bus Header SCLEXT

Deploy the firmware

#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>


// Forward declarations
void pcfWrite(uint8_t value);
uint8_t pcfRead();
char scanKeypad();
void showKey(char key);
void sendKeyToRs485(char key);
void handleAcceptedKey(char key);

constexpr uint8_t I2C_SDA_PIN = 4;
constexpr uint8_t I2C_SCL_PIN = 5;
constexpr uint8_t RS485_DIR_PIN = 12;
constexpr uint8_t KEYPAD_PCF8574_ADDRESS = 0x20;
constexpr uint8_t LCD_I2C_ADDRESS = 0x27;
constexpr unsigned long DEBOUNCE_MS = 35;

LiquidCrystal_I2C lcd(LCD_I2C_ADDRESS, 16, 2);

const char KEYMAP[4][4] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

char lastRawKey = '\0';
char acceptedKey = '\0';
unsigned long rawKeyChangedAt = 0;

void pcfWrite(uint8_t value) {
  Wire.beginTransmission(KEYPAD_PCF8574_ADDRESS);
  Wire.write(value);
  Wire.endTransmission();
}

uint8_t pcfRead() {
  Wire.requestFrom(static_cast<int>(KEYPAD_PCF8574_ADDRESS), 1);
  return Wire.available() ? static_cast<uint8_t>(Wire.read()) : 0xFF;
}

char scanKeypad() {
  for (uint8_t row = 0; row < 4; ++row) {
    // P0..P3 are rows. One row is driven low; P4..P7 remain released as inputs.
    uint8_t rowPattern = static_cast<uint8_t>(0xF0 | (0x0F & ~(1U << row)));
    pcfWrite(rowPattern);
    delayMicroseconds(80);
    uint8_t sample = pcfRead();

    for (uint8_t column = 0; column < 4; ++column) {
      if ((sample & (1U << (column + 4))) == 0) {
        pcfWrite(0xFF);
        return KEYMAP[row][column];
      }
    }
  }
  pcfWrite(0xFF);
  return '\0';
}

void showKey(char key) {
  lcd.setCursor(0, 1);
  lcd.print("Key: ");
  lcd.print(key);
  lcd.print("          ");
}

void sendKeyToRs485(char key) {
  digitalWrite(RS485_DIR_PIN, HIGH);
  delayMicroseconds(20);
  Serial.print("KEY,");
  Serial.println(key);
  Serial.flush();
  delayMicroseconds(20);
  digitalWrite(RS485_DIR_PIN, LOW);
}

void handleAcceptedKey(char key) {
  showKey(key);
  sendKeyToRs485(key);
}

void setup() {
  pinMode(RS485_DIR_PIN, OUTPUT);
  digitalWrite(RS485_DIR_PIN, LOW);  // Receive mode after power-up.

  Serial.begin(9600);
  Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
  Wire.setClock(100000);
  pcfWrite(0xFF);

  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Queue terminal");
  lcd.setCursor(0, 1);
  lcd.print("Ready           ");
}

void loop() {
  char rawKey = scanKeypad();
  unsigned long now = millis();

  if (rawKey != lastRawKey) {
    lastRawKey = rawKey;
    rawKeyChangedAt = now;
  }

  if ((now - rawKeyChangedAt) >= DEBOUNCE_MS && rawKey != acceptedKey) {
    acceptedKey = rawKey;
    if (acceptedKey != '\0') {
      handleAcceptedKey(acceptedKey);
    }
  }
}

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik