ESP32 simulator from Wokwi is free and helps you to learn ESP32 programming. The simulator is online, free and easy to use. We will use micro-python programming. This article is a work in progress ⛏ Feel free to share suggestions in the comments. I will be glad to incorporate it in the article. Let us get started 🛴
A small Introduction to the ESP32 board
ESP32 dev kit pin-out is given above. The official link for ESP32 presents you with the software and hardware details necessary to start your journey with ESP32 hardware. Here there is a link to more information on the ESP32 simulator.
ESP32 MicroPython project 1 - "Hello World" 👋Printing a text is the "Hello World" equivalent program. In this project, you instruct an ESP32 to send a custom message using MicroPython programming. You will send "Hello World
"
Start a new ESP32 MicroPython project on the Wokwi Arduino simulator. Use the new project template to quickly start with a template test.py
project
Here is the basic code for the terminal print example on ESP32
print("Hello, ESP32!")
The project would look like something down below
you can see that the text was printed in the command prompt already!!
Go ahead and create your own "Hello World" examples...
Assignments you can try
- Can you print your name?
- Can you try to find out what is the maximum length of the string you can print using the print command?
Blinking an LED 💡 is the first step one will take in an Arduino project or an ESP32 project. Blinking an LED needs an LED, a series resistor and some connecting wires. You will need a series resistor with an LED so that you can control the current through it.
An ESP32 can always drive the LED directly as long as the current through the LED is below a couple of mA. Let us see the connection diagram first!
Below is the example code here
import time
from machine import Pin
led=Pin(2,Pin.OUT)
while True:
led.value(1)
time.sleep(0.5)
led.value(0)
time.sleep(0.5)
Since
this is the first time we are using Pin class, let us have a quick look at it. below is the snippet from the official MicroPython docs website:
class Pin – control I/O pins
A pin object is used to control I/O pins (also known as GPIO - general-purpose input/output). Pin objects are commonly associated with a physical pin that can drive an output voltage and read input voltages. The pin class has methods to set the mode of the pin (IN, OUT, etc) and methods to get and set the digital logic level. For the analog control of a pin, see the ADC
class.
A pin object is constructed by using an identifier that unambiguously specifies a certain I/O pin. The allowed forms of the identifier and the physical pin that the identifier maps to is port-specific. Possibilities for the identifier are an integer, a string or a tuple with port and pin number.
from machine import Pin
# create an output pin on pin #0
p0 = Pin(0, Pin.OUT)
# set the value low then high
p0.value(0)
p0.value(1)
# create an input pin on pin #2, with a pull up resistor
p2 = Pin(2, Pin.IN, Pin.PULL_UP)
# read and print the pin value
print(p2.value())
# reconfigure pin #0 in input mode with a pull down resistor
p0.init(p0.IN, p0.PULL_DOWN)
# configure an irq callback
p0.irq(lambda p:print(p))
Please follow through this link for complete details of class Pin, the constructors, methods and constants associated with it.
Next, a led object is created as an instance of the machine module Pin class. The parameters are:
- 2, The board pin number which is connected to the LED
- Pin.OUT Pin will be set as Output and can send a logic HIGH or LOW
You can use the LED blink on ESP32 by MicroPython to try it out for yourself. Feel free to customize the ESP32 project the way you would like to. Here is how the simulation looks
Assignments you can try
- Can you print the LED status?
- Change the LED duty cycle to 20%
- Can you create a LED dimming pattern?
- Can you three more LEDs and create a simple Traffic Light pattern?
An HMI for any project is only possible with some ways to give input to the ESP32. It can be a button, a keypad or a touch screen. In this project, you will see how a button can be interfaced to ESP32.
A digital input in the board pin reads a HIGH
or a LOW
based on the signal connected to it. You can detect whether a switch is pressed or released by using a digital button. ESP32 Wokwi simulator makes it easy to work with digital inputs without real hardware.
In this particular example, you will connect a button 🔘 to ESP32 Pin D13 Below you
can see the connection diagram for ESP32 and the button. Let us learn about digital input via a super simple example. What you will need is the hardware connection below.
The code for the above project has the below objective.
- If the button is pressed, the LED will be
ON
- If the button is released, LED will be
OFF
With this setup when the button is pressed, it will connect pin 13 to the ground and read a LOW
signal on the pin. When the button is released the switch is weakly pulled to the ground via a pull-down resistor. Some hardware supports internal pull-ups or pull-downs. I
In this example, when the switch is pressed, pin D13 will be connected to HIGH
(3.3V) and when the switch is not pressed D13 will be connected to the ground (Logic LOW
via the pull-down resistor.
Here is the code for the project
from machine import Pin
from time import sleep
print('Wokwi ESP32 Simulator')
led = Pin(2, Pin.OUT) # D2 number in is Output
push_button = Pin(13, Pin.IN) # D13 number pin is input
while True:
logic_state = push_button.value()
if logic_state == True: # if pressed the push_button
led.value(1) # led will turn ON
else: # if push_button not pressed
led.value(0) # led will turn OFF
As you can see the line
push_button = Pin(13, Pin.IN) # D13 number pin is input
Next, a push_button object is created as an instance of the machine module Pin class. However, notice the parameters are a little bit different when creating this input as compared to creating an output. The parameters are:
- 13, The board pin number
- Pin.IN Pin will be set as input and can read HIGH or LOW
- The third parameter is the constant value machine.Pin.PULL_UP This is not a compulsory setting. This parameter isn't actually required and if it's not specified then the pin will still be an input but it won't have any internal pull-up resistor set.
Let us see the simulation action in progress
Here is the ESP32 LED and button project. Try it out for yourself
Assignments you can try
- Can you connect the button to pin D14?
- Lit the LED when the button is not pressed
- Can you connect two LEDs, which will toggle after every button press?
Loops are very helpful. Loops are another important feature of any programming language. This allows you to cycle your code and repeat functions/assignments etc.
for
loops allow you to control how many times a block of code runs within a range.
x = 0
for y in range(0, 9):
x += 1
print(x)
You can repeat certain instructions for a fixed interval time or until a condition is met. It is a very helpful aspect. The loop function along with the time method can be used to blink the LED a certain number of times. Here is the connection diagram.
Here is the code used in the project
from machine import Pin
from time import sleep
print('Wokwi ESP32 Simulator')
led = Pin(2, Pin.OUT) # D2 number in is Output
for i in range(20):
led.value(1) # led will turn ON
sleep(0.5)
led.value(0) # led will turn OFF
sleep(0.5)
As you can see, the for loop line
for i in range(20):
runs 20 times 😯🏃♀️ and the below command
sleep(0.5);
puts the ESP32 into idle mode for 500 ms of half a second.
Here is the link for the for loop in an ESP32 simulator example for you to play with!
Assignments you can try
- Can you change the number of iterations to 30?
- can you add an if statement and blink the LED only if the loop count is a multiple of 3!
While
loop helps you to repeat certain tasks while a condition is true (pun intended). this can be useful when you are waiting for a temperature to rise to a certain level (then you can turn off the heater, for example)..or it can be a simple waiting task until the set timer expires. Let's see one practical example
a simple example using while loop in action
The project link is here: https://wokwi.com/arduino/projects/319622033357931090
while
loops are similar to for
loops, however, they allow you to run a loop until a specific condition is true/false
. In this case, the loop checks if x
is less than 9
each time the loop passes.
x = 0
while x < 9:
x += 1
print(x)
Assignments you can try
- Can you change the while loop logic so that the LED will blink every 500 ms when the button is pressed?
UART
is a very useful debug/communication platform which enables you to communicate with other Microcontrollers and other MODEM with UART interfaces (such as ZigBee..)
UART data byte will have 8 bits of the data frame, stop bit, start bit as well as parity bits. the length of stop bits and data bits are programmable.
You can create and initialize the UART objects by the following command:
from machine import UART
uart = UART(1, 9600) # init with given baudrate
uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters
The supported parameters (uart.init) for a Pyboard are: Bits should be at 7, 8, or 9. Along with parity= None, only 8 and 9 bits are supported. If parity is enabled, then only 7 and 8 bits are supported.
A UART object acts like a stream object where we use the standard stream method for reading and writing.
uart.read(10) # read 10 characters, returns a bytes object
uart.read() # read all available characters
uart.readline() # read a line
uart.readinto(buf) # read and store into the given buffer
uart.write('abc') # write the 3 characters
helps you to repeat certain tasks while a condition is true (pun intended). this can be useful when you are waiting for a temperature to rise to a certain level (then you can turn off the heater, for example)..or it can be a simple waiting task until the set timer expires. Let's see one practical example.
an example UART ESP32 simulation in action
<under maintenance !!> 🚧🏗👷♀️👷♂️
- debugging during the initial development phase
- to send status messages
- to interact with other peripherals who support UART
- RS485, RS232 interfaces
I2C
is a 2 wire protocol for users to establish communication between devices. At the physical level, it consists of 2 wires: SCL
and SDA
, the clock and data lines respectively.
I2C objects are created attached to a specific bus. They can be initialized when created or initialized later on.
Printing the I2C object gives you information about its configuration.
Both hardware and software I2C implementations exist via the machine.I2C
and machine.SoftI2C
classes. Hardware I2C uses underlying hardware support of the system to perform the reads/writes and is usually efficient and fast but may have restrictions on which pins can be used. Software I2C is implemented by bit-banging and can be used on any pin but is not as efficient. These classes have the same methods available and differ primarily in the way they are constructed.
Example usage:
from machine import I2C
i2c = I2C(freq=400000) # create I2C peripheral at frequency of 400kHz
# depending on the port, extra parameters may be required
# to select the peripheral and/or pins to use
i2c.scan() # scan for peripherals, returning a list of 7-bit addresses
i2c.writeto(42, b'123') # write 3 bytes to peripheral with 7-bit address 42
i2c.readfrom(42, 4) # read 4 bytes from peripheral with 7-bit address 42
i2c.readfrom_mem(42, 8, 3) # read 3 bytes from memory of peripheral 42,
# starting at memory-address 8 in the peripheral
i2c.writeto_mem(42, 2, b'\x10') # write 1 byte to memory of peripheral 42
# starting at address 2 in the peripheral
Let us see one ESP32
MicroPython I2C example. Here is the simulation output.
the code for the above project is here:
from time import sleep_ms, ticks_ms
from machine import I2C, Pin
from i2c_lcd import I2cLcd
AddressOfLcd = 0x27
i2c = I2C(scl=Pin(22), sda=Pin(21), freq=400000) # connect scl to GPIO 22, sda to GPIO 21
lcd = I2cLcd(i2c, AddressOfLcd, 2, 16)
def testLcd(num):
lcd.move_to(3,0)
lcd.putstr('Micropython')
lcd.move_to(0,1)
lcd.putstr("hello " + str(num))
if __name__ == '__main__':
for i in range(100):
testLcd(i)
sleep_ms(200)
In this example, GPIO Pin 21 and 22 are mapped to I2C-SDA and SCL pins respectively. in ESP32, the I2C lines are not fixed to one particular pin. You are free to map the I2C pins to most of the GPIOs.
ESP32 MicroPython project 8 - Read analog values from ADCADC
helps you to read analog values. Everything in nature is analog. Sun brightness, wind speed, water level etc. Hence, ADC is an integral part of most of the tools we see around. You will see how easy it is to read any analog signal value.
Connection diagram
Code for the MicroPython ADC code example - ESP32
print("Hello, ESP32!")
from machine import Pin, ADC #importing Pin and ADC class
from time import sleep #importing sleep class
potentiometer = ADC(Pin(32)) #creating potentiometer object
potentiometer.atten(ADC.ATTN_11DB) #3.3V full range of voltage
while True:
potentiometer_value = potentiometer.read() #reading analog pin
print(potentiometer_value) #printing the ADC value
sleep(0.25)
Live project link: https://wokwi.com/arduino/projects/321564639430181458
On the ESP32 ADC functionality is available on pins 32-39 (ADC block 1) and pins 0, 2, 4, 12-15 and 25-27 (ADC block 2).
Note that the ESP32 uses an internal ADC reference voltage of 1.0v. To read voltages above this value, input attenuation can be applied with the optional atten
keyword argument to the constructor.
I hope, you can now add ADC into your project and explore more features of ESP32.
This is an article in progress. but I would appreciate it if you can leave feedback on how I can make this article better, more useful and easy to understand by the beginners. Thank you!
Support/feedback/suggestions?you have many ways to ask for help, suggest a feature or share your feedback
- Open an issue on GitHub
- Visit Facebook group
- Hop on to Discord Server!
- leave a comment here 👇
-------------------------------------------------------------------------------------------
Comments