Random Nerd Tutorials

MicroPython with ESP32 and ESP8266: Interacting with GPIOs


In this article we’re going to take a look on how to interact with the ESP32 and ESP8266 GPIOs using MicroPython. We’ll show you how to read digital and analog inputs, how to control digital outputs and how to generate PWM signals.


To program the ESP32 and ESP8266 with MicroPython, we use uPyCraft IDE as a programming environment. Follow the next tutorials to install uPyCraft IDE and flash MicroPython firmware on your board:

If this is your first time dealing with MicroPython you may find these next tutorials useful:

Project Overview

With this tutorial you’ll learn how to control the ESP32 or ESP8266 GPIOs with MicroPython:

  • Read digital inputs;
  • Control digital outputs;
  • Read analog inputs;
  • Generate PWM signals.

We’ll build a simple example that works as follows:

  • Read the state of a pushbutton and set the LED state accordingly – when you press the pushbutton the LED lights up.

  • Read the voltage from a potentiometer and dim an LED accordingly to the shaft’s position of the potentiometer.


The circuit for this project involves wiring two LEDs, a pushbutton, and a potentiometer. Here’s a list of all the parts needed to build the circuit:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

ESP32 – Schematic

Follow the next schematic diagram if you’re using an ESP32:

Note: the ESP32 supports analog reading in several GPIOs: 0, 2, 4, 12, 13, 14, 15, 25, 26, 27 32, 33, 34, 35, 36, and 39.

Recommended reading: ESP32 Pinout Reference: Which GPIO pins should you use?

ESP8266 – Schematic

Follow the next schematic diagram if you’re using an ESP8266:

Note: the ESP8266 only supports analog reading in pin ADC0 (A0).


Copy the following code to the main.py file in the uPyCraft IDE.

Note: analog reading works differently in ESP32 and ESP8266. The code works right away in ESP32. To use with ESP8266, you have to uncomment and comment the lines described in the MicroPython script.

How the code works

Continue reading to learn on how the code works.

Importing Libraries

To interact with the GPIOs you need to import the machine module that contains classes to interact with the GPIOs. Import the Pin class to interact with the pins, the ADC class to read analog value, and the PWM class to generate PWM signals.

from machine import Pin, ADC, PWM

Import the sleep() method from the time module. The sleep() method allows you to add delays to the code.

from time import sleep

Instantiating Pins

After importing all the necessary modules, instantiate a Pin object called led on GPIO 2 that is an OUTPUT.

led = Pin(2, Pin.OUT)

The Pin object accepts the following attributes in the following order:

Pin(Pin number, pin mode, pull, value)
  • Pin number refers to the GPIO we want to control;
  • Pin mode can be input (IN), output (OUT) or open-drain (OPEN_DRAIN);
  • The pull argument is used if we want to activate a pull up or pull down internal resistor (PULL_UP, or PULL_DOWN);
  • The value corresponds to the GPIO state (if is is on or off): it can be 0 or 1 (True or False).  Setting 1 means the GPIO is on. If we don’t pass any parameter, its state is 0 by default (that’s what we’ll do in this example).

After instantiating the led object, you need another instance of the Pin class for the pushbutton. The pushbutton is connected to GPIO 15 and it’s set an inpu. So, it looks as follows:

button = Pin(15, Pin.IN)

Instantiating ADC

In the ESP32, to create an ADC object for the potentiometer on GPIO 34:

pot = ADC(Pin(34))

If you’re using an ESP8266, it only supports ADC on ADC0 (A0) pin. To instantiate an ADC object with the ESP8266:

pot = ADC(0)

The following line applies just to the ESP32. It defines that we want to be able to read voltage in full range. This means we want to read voltage from 0 to 3.3 V.


The next line means we want readings with 10 bit resolution (from 0 to 1023)


The width() method accepts other parameters to set other resolutions:

  • WIDTH_9BIT: range 0 to 511
  • WIDTH_10BIT: range 0 to 1023
  • WIDTH_11BIT: range 0 to 2047
  • WIDTH_12BIT: range 0 to 4095

Note: if you don’t set the resolution it will be 12-bit resolution by default on the ESP32.

Instantiating PWM

Then, create a PWM object called led_pwm on GPIO 4 with 5000 Hz.

led_pwm = PWM(Pin(4), 5000)

To create a PWM object, you need to pass as parameters: pin, signal’s frequency, and duty cycle.

The frequency can be a value between 0 and 78125. A frequency of 5000 Hz for an LED works just fine.

The duty cycle can be a value between 0 and 1023. In which 1023 corresponds to 100% duty cycle (full brightness), and 0 corresponds to 0% duty cycle (unlit LED).

We’ll just set the duty in the while loop, so we don’t need to pass the duty cycle parameter at the moment. If you don’t set the duty cycle when instantiating the PWM object, it will be 0 by default.

Getting the GPIO state

Then, we have a while loop that is always True. This is similar to the loop() function in the Arduino IDE.

We start by getting the button state and save it in the button_state variable. To get the pin state use the value() method as follows:

button_state = button.value()

This returns 1 or 0 depending on whether the button is pressed or not.

Setting the GPIO state

To set the pin state, use the value(state) method in the Pin object. In this case we’re setting the button_state variable as an argument. This way the LED turns on when we press the pushbutton:


Reading analog inputs

To read an analog input, use the read() method on an ADC object (in this case the ADC object is called pot).

pot_value = pot.read()

Controlling duty cycle

To control the duty cycle, use the duty() method on the PWM object (led_pwm). The duty() method accepts a value between 0 and 1023 (in which 0 corresponds to 0% duty cycle, and 1023 to 100% duty cycle). So, pass as argument the pot_value (that varies between 0 and 1023). This way you change the duty cycle by rotating the potentiometer.


Testing the Code

Upload the main.py file to your ESP32 or ESP8266. For that, open uPyCraft IDE and copy the code provided to the main.py file. Go to Tools > Serial and select the serial port. Select your board in Tools > Board.

Then, upload the code to the ESP32 or ESP8266 by pressing the Download and Run button.

Note: to get you familiar with uPyCraft IDE youn can read the following tutorial – Getting Started with MicroPython on ESP32 and ESP8266

After uploading the code, press the ESP32/ESP8266 on-board EN/RST button to run the new script.

Now, test your setup. The LED should light up when you press the pushbutton.

The LED brightness changes when you rotate the potentiometer.

Wrapping Up

This simple example showed you how to read digital and analog inputs, control digital outputs and generate PWM signals.

We hope you’ve found this article about how to control ESP32 and ESP8266 GPIOs with MicroPython useful. We’ll be adding more tutorials about MicroPython very soon. So, stay tuned and subscribe the RNT blog to get access to our free resources!

We have other articles about ESP32 and ESP8266 you may also like:

Thanks for reading.

Learn ESP32 with Arduino IDE

This our complete guide to program the ESP32 with Arduino IDE, including projects, tips, and tricks! The registrations are open, so SIGN UP NOW »

Leave a Comment:

Add Your Reply

⏰ Registrations are open ⏰
Sign up for "Learn ESP32 with Arduino IDE" Course