EMC/EMI Checklist Before Your Board Goes to Certification
EMC testing is expensive, and failing it is worse than the test fee — it costs you a respin, a
If you're starting with the ESP32, mastering digital GPIO (General Purpose Input/Output) pins is your essential first step toward building any IoT project. This comprehensive guide will take you beyond basic examples to truly understand how to read button presses, control LEDs, and utilize the ESP32's versatile pin configuration for real-world applications.

Every ESP32 project—from simple LED blinkers to complex home automation systems—relies on digital inputs and outputs. Digital pins detect binary states (pressed/released, on/off) and control digital devices. With approximately 34 usable GPIO pins (with limitations), the ESP32 offers tremendous flexibility for connecting sensors, actuators, displays, and communication modules.
Flexible pin assignment: Most pins can be configured as either inputs or outputs
Built-in pull-up/pull-down resistors: Eliminate the need for external resistors in many cases
High drive capability: Can source/sink sufficient current for LEDs and relays
Interrupt capability: Respond instantly to input changes without constant monitoring
Before connecting any components, it's crucial to know which pins are truly available. Not all ESP32 pins behave equally:
GPIOs 6-11: Internally connected to the ESP32's SPI flash memory. Using these can crash your program.
GPIOs 34-39: Input-only pins. Cannot be used as outputs or with internal pull-up/pull-down resistors.
Strapping pins (GPIOs 0, 2, 4, 5, 12, 15): Affect boot behavior—use cautiously during development.
Most other GPIOs (0-5, 12-19, 21-23, 25-27, 32-33) work as both digital inputs and outputs. For beginners, GPIOs 4, 5, 18, and 19 are excellent starting points as they lack special restrictions.
The Arduino IDE provides three essential functions for digital GPIO control:
pinMode(pin, mode) - Pin ConfigurationSets a GPIO as either INPUT or OUTPUT. Always configure pins in your setup() function before using them.
Common mistake: Forgetting to set pin mode, which leads to unpredictable behavior.
digitalWrite(pin, value) - Controlling OutputsSets an output pin to either HIGH (3.3V) or LOW (0V).
// Turn on an LED connected to pin 5 digitalWrite(5, HIGH); // Turn it off digitalWrite(5, LOW);
digitalRead(pin) - Reading InputsReturns HIGH or LOW based on the voltage detected at an input pin.
// Read a button state int buttonState = digitalRead(4);
Let's build on the basic "button controls LED" circuit with enhanced functionality and debugging.
LED: Connect anode (long leg) to GPIO 5 through a 220Ω resistor, cathode to GND
Push button: Connect one terminal to GPIO 4, other terminal to 3.3V
Crucial addition: Add a 10kΩ pull-down resistor between GPIO 4 and GND
This ensures a clean LOW signal when button isn't pressed
Prevents "floating" inputs that randomly toggle between HIGH/LOW
// Complete ESP32 Digital I/O Example with Serial Monitoring // https://RandomNerdTutorials.com/esp32-digital-inputs-outputs-arduino/ // Pin definitions const int BUTTON_PIN = 4; // Pushbutton connected to GPIO 4 const int LED_PIN = 5; // LED connected to GPIO 5 // Variables int lastButtonState = LOW; // Previous button reading int buttonPressCount = 0; // Track number of button presses unsigned long lastDebounceTime = 0; unsigned long debounceDelay = 50; // Debounce time in milliseconds void setup() { Serial.begin(115200); Serial.println("ESP32 Digital I/O Example Initialized"); // Configure pins pinMode(BUTTON_PIN, INPUT); pinMode(LED_PIN, OUTPUT); // Initialize LED state digitalWrite(LED_PIN, LOW); Serial.print("Monitoring button on GPIO "); Serial.println(BUTTON_PIN); } void loop() { // Read current button state int currentButtonState = digitalRead(BUTTON_PIN); // Debounce logic: check if button state has changed if (currentButtonState != lastButtonState) { lastDebounceTime = millis(); } // Only register press after debounce period if ((millis() - lastDebounceTime) > debounceDelay) { // If button state changed to HIGH (pressed) if (currentButtonState == HIGH && lastButtonState == LOW) { buttonPressCount++; Serial.print("Button pressed! Total presses: "); Serial.println(buttonPressCount); // Toggle LED state digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Report LED status if (digitalRead(LED_PIN) == HIGH) { Serial.println("LED turned ON"); } else { Serial.println("LED turned OFF"); } } } // Save current state for next loop comparison lastButtonState = currentButtonState; // Small delay to prevent overwhelming the serial monitor delay(10); }
Debouncing: Mechanical buttons physically "bounce" when pressed, creating multiple rapid state changes. Our debouncing logic waits 50ms after a change before registering it.
Serial debugging: Provides real-time feedback in the Serial Monitor—invaluable for troubleshooting.
Toggle logic: Each button press alternates the LED state rather than requiring constant pressure.
Efficient polling: Uses millis() for timing instead of blocking delay() calls.
For simpler wiring, use the ESP32's built-in pull-up resistors:
// Enable internal pull-up resistor pinMode(BUTTON_PIN, INPUT_PULLUP); // Button logic reverses with INPUT_PULLUP: // Button pressed = LOW (connects to GND) // Button released = HIGH (pulled up to 3.3V)
With INPUT_PULLUP, connect your button between the GPIO pin and GND (not 3.3V).
For immediate response without constant polling:
// Attach interrupt to pin attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonPressed, CHANGE); // Interrupt Service Routine (must be fast!) void buttonPressed() { // Handle button change here }
Warning: Keep ISR code extremely short—avoid Serial.print() or complex operations.
Transform the basic example into a practical smart home component:
// Smart button with press duration detection void loop() { int buttonState = digitalRead(BUTTON_PIN); if (buttonState == HIGH) { // Button is pressed - time the duration unsigned long pressStart = millis(); while (digitalRead(BUTTON_PIN) == HIGH) { // Wait for button release delay(10); } unsigned long pressDuration = millis() - pressStart; // Different actions based on press length if (pressDuration < 50) { // Ignore - likely noise } else if (pressDuration < 500) { Serial.println("Short press - toggle light"); // Toggle light code here } else if (pressDuration < 3000) { Serial.println("Medium press - dim light"); // Dimming function here } else { Serial.println("Long press - factory reset"); // Reset function here } } }
Symptoms: Random HIGH/LOW fluctuations without button press
Solutions:
Always use pull-up or pull-down resistors (internal or external)
Add a 0.1µF capacitor between input pin and GND
Implement software debouncing as shown above
Symptoms: "Failed to connect" errors during upload
Solutions:
Hold the BOOT button when upload begins
Check Tools > Board selection matches your ESP32 model
Try different USB cables (some charge-only cables don't transmit data)
Solutions:
Verify LED orientation (long leg to positive)
Ensure resistor value is appropriate (220-470Ω)
Check you're writing HIGH to the correct pin
Critical note: When WiFi is active, avoid using GPIOs 6-11, 16, 17. For ADC2 pins (GPIOs 0, 2, 4, 12-15, 25-27), you may experience conflicts when using WiFi simultaneously.
Once you've mastered basic digital I/O, explore these related concepts:
Analog Inputs: Read variable voltages with analogRead() for sensors like potentiometers
PWM Output: Simulate analog output with analogWrite() for LED fading, motor control
Touch Sensing: Use ESP32's built-in capacitive touch sensors on designated pins
Multiple Devices: Learn I2C and SPI communication to connect many sensors to few pins
Always initialize pins in setup() before using them in loop()
Include current-limiting resistors for LEDs (220Ω-1kΩ)
Use descriptive variable names (ledPin not pin13)
Implement debouncing for all mechanical switches
Test each component separately before combining complex circuits
Document your pin assignments with comments or diagrams
This digital I/O foundation enables countless ESP32 projects:
Home automation: Light controls, security sensors, smart switches
IoT devices: Button-controlled webhooks, status indicators
Robotics: Limit switches, motor controllers, sensor arrays
Prototyping: User interfaces, debug indicators, mode selectors
Remember: Every complex ESP32 project builds upon these basic digital input/output concepts. Start simple, master the fundamentals, and gradually add complexity.
Need Help? If your circuit isn't working:
Double-check all connections against the schematic
Verify your GPIO numbers match the physical pins
Check the Serial Monitor for debugging messages
Ensure power is connected (USB or external 5V)
Share Your Project! Modified the code for your own use? Created an interesting application? Share your experiences in the comments to help other makers learn from your journey.
Ready to advance? Explore our ESP32 GPIO Reference Guide for complete pin details and special functions, or check out our ESP32 PWM tutorial for motor and LED dimming control.
======================================
3.52 inch e-paper Display e-link red black and white support raspberry pi/STM32 paper screen 360x240 SPI Interface
$18.90 – $27.90Price range: $18.90 through $27.90
DeepX M1 AI Acceleration Module (M.2 Interface) – Low-Power Computing Expansion Card (25 TOPS) for Rockchip RK3588
$208.60
0.96 inch TN screen TFT color LCD display 4 Line SPI interface ST7735S driver chip
$2.90
Radxa 20W PoE+ Module compact for CUBIE A5E
$19.80
4.2 Inch Black White Epaper Display
$11.80
EMC testing is expensive, and failing it is worse than the test fee — it costs you a respin, a
We review a lot of boards — some designed in-house, some by other contractors, some by founders doing their own
When a battery-powered product dies too soon, the instinct is to blame the firmware. Surely there is a sleep mode
A wearable PCB is not just a small PCB. It is a board where every constraint that normally has some
The STM32 family is the workhorse of embedded hardware, and almost every project that uses one starts the same way:
The nRF52840 is one of the most popular BLE and multiprotocol chips in the world, and for good reason: it
No account yet?
Create an Account