ESP32 HMI 4.3-inch MicroPython Tutorial¶
Overview¶
The example tutorial demonstrate how to create a UI and how to control the LED on and off by the buttons on the screen.
In this tutorial, we will show you how to design the UI with SquareLine Studio, and show you how to upload the code with Thonny IDE.
Hardware Preparation¶
CrowPanel ESP32 4.3'' HMI | Crowtail-LED | Crowtail Cable |
---|---|---|
Design UI file with SquareLine Studio¶
Get Started with SquareLine Studio¶
Please click the card below to learn how to download the SquareLine Studio, and how to export the demo UI file.
Design UI file with SquareLine Studio¶
Let's start learning how to create our own UI after getting an initial understanding of SquareLine Studio.
-
Open the SquareLine Studio and create a project. Select "Desktop"->"Micropython for Unix and other platform".
-
Set the name of the project, set the screen resolution to 480*272, set the color depth to 16bit, and keep other default settings. After setting, click CREATE to create the project.
- 16-bit color depth: can represent 65,536 colors through RGB 5:6:5 sub-pixel representation, that is, each RGB channel occupies 5 bits and 1 bit (a total of 16 bits) to represent colors.
-
After creation, enter the following interface with a blank background.
-
In the "Assets" area, click "ADD FILE TO ASSETS" to add custom images or icons.
Please click to download the custom images used in this tutorial.
-
Add background.
Click "Image" to add the image widgets.
Find "Inspector"->"STYLE SETTING", click to expand "STYLE(MAIN)", then click the 2nd "Background". Check the "Bg Image" and select a background picture.
Adjust the position of the image.
Note: Because it requires a large amount of memory when running in Thonny IDE, the UI background resolution of this tutorial is small and not full screen, so it is necessary to modify the background to the same color as the image.
-
Add Button widget to control the LED.
Click "Button" in the "Widgets" area, and "Button1" will be added to the current Screen.
The position and size of the label can be adjusted by dragging the mouse. You can also directly enter numbers in the Inspector→BUTTON→Transform to adjust.
Add an identification symbol to the button. The button in this tutorial controls the LED switch, so you only need to mark the button "on" and "off". You can add LABEL widgets or add a background images to the button. This tutorial will demonstrate how to add a background image to a button.
Click the Button1, then find Inspector->STYLE SETTINGS ->STYLE(MAIN) ->Background, and select the image.
Add a Button2 for "OFF".
Set the status of the button to identify different states.
In "Inspector"->"STYLE SETTINGS"->"STATE", set display white background color by DEFAULT and red when on the PRESSED state.
-
Add events to buttons.
Note: Because the button controls the on and off of the LED, we can add any event here to generate the code framework for the button event when exporting the UI file. We will modify the code of the button event to control the LED latter.
Select the button and click "ADD EVENT".
Select "released" as the trigger condition, select a trigger event in "Action". It will be modified in the generated program to achieve the LED control function.
Complete the event. Here I choose to change the screen, and the screen to be switched is Screen1.
Make the same settings for the "OFF" button.
-
Export UI files.
Click "File" -> "Project Settings" and make settings for the exported file.
Set the export path of the file (set the path according to your own file).
Fill in lvgl.h in LVGL Include Path. Check "Flat export(exports all files to one folder )".
Then click "APPLY CHANGES".
Export UI files. The exported files will be in the path we set earlier.
The UI file export is completed. Next we're going to learn about the main program and learn how to upload the code to the board with Thonny IDE.
Build the Project with Thonny IDE¶
Download Thonny IDE¶
-
Go to the website https://thonny.org/ and download the corresponding software version (here we take the Windows version as an example)
-
Double-click the downloaded exe file to install the software.
Upload firmware¶
-
Connect the CrowPanel ESP32 HMI with your computer.
-
Open Thonny IDE and click "Tools"->"Options"->"Interpreter".
-
Select "MicroPython(ESP32)" for interpreter.
-
Select the corresponding serial port(or Try to detect port automatically).
-
Click "Install or update MicroPython (esptool)"
-
Click the icon with 3 lines, and click "select local MicroPython image...".Select the "firmware-4.3-A.bin" and install.
-
Waiting for downloading...
Edit the code¶
Please click to download the code file and libraries.
#Make by Elecrow
#Web:www.elecrow.com
import lvgl as lv
import lv_utils
import tft_config
from xpt import Touch
from machine import SPI, Pin
import time
import fs_driver
import ui_images
WIDTH = 480
HEIGHT = 272
pin38 = Pin(38, Pin.OUT)
pin38.value(0)
# tft drvier
tft = tft_config.config()
# touch drvier
spi = SPI(2, baudrate=1000000)
spi.init(sck=Pin(12), mosi=Pin(11), miso=Pin(13))
cs = Pin(0, mode=Pin.OUT, value=1)
int_pin = Pin(36)
xpt = Touch(spi, cs=cs, int_pin=int_pin)
xmin = 96
xmax = 1951
ymin = 175
ymax = 1908
orientation = 0
xpt.calibrate(xmin, xmax, ymin, ymax, 480, 272, orientation)
lv.init()
if not lv_utils.event_loop.is_running():
event_loop=lv_utils.event_loop()
print(event_loop.is_running())
# create a display 0 buffer
disp_buf0 = lv.disp_draw_buf_t()
buf1_0 = bytearray(WIDTH * 10)
disp_buf0.init(buf1_0, None, len(buf1_0) // lv.color_t.__SIZE__)
# register display driver
disp_drv = lv.disp_drv_t()
disp_drv.init()
disp_drv.draw_buf = disp_buf0
disp_drv.flush_cb = tft.flush
disp_drv.hor_res = WIDTH
disp_drv.ver_res = HEIGHT
# disp_drv.user_data = {"swap": 0}
disp0 = disp_drv.register()
lv.disp_t.set_default(disp0)
# touch driver init
indev_drv = lv.indev_drv_t()
indev_drv.init()
indev_drv.disp = disp0
indev_drv.type = lv.INDEV_TYPE.POINTER
indev_drv.read_cb = xpt.read
indev = indev_drv.register()
dispp = lv.disp_get_default()
theme = lv.theme_default_init(dispp, lv.palette_main(lv.PALETTE.BLUE), lv.palette_main(lv.PALETTE.RED), False, lv.font_default())
dispp.set_theme(theme)
def SetFlag( obj, flag, value):
if (value):
obj.add_flag(flag)
else:
obj.clear_flag(flag)
return
_ui_comp_table = {}
_ui_comp_prev = None
_ui_name_prev = None
_ui_child_prev = None
_ui_comp_table.clear()
def _ui_comp_del_event(e):
target = e.get_target()
_ui_comp_table[id(target)].remove()
def ui_comp_get_child(comp, child_name):
return _ui_comp_table[id(comp)][child_name]
def ui_comp_get_root_from_child(child, compname):
for component in _ui_comp_table:
if _ui_comp_table[component]["_CompName"]==compname:
for part in _ui_comp_table[component]:
if id(_ui_comp_table[component][part]) == id(child):
return _ui_comp_table[component]
return None
def SetBarProperty(target, id, val):
if id == 'Value_with_anim': target.set_value(val, lv.ANIM.ON)
if id == 'Value': target.set_value(val, lv.ANIM.OFF)
return
def SetPanelProperty(target, id, val):
if id == 'Position_X': target.set_x(val)
if id == 'Position_Y': target.set_y(val)
if id == 'Width': target.set_width(val)
if id == 'Height': target.set_height(val)
return
def SetDropdownProperty(target, id, val):
if id == 'Selected':
target.set_selected(val)
return
def SetImageProperty(target, id, val, val2):
if id == 'Image': target.set_src(val)
if id == 'Angle': target.set_angle(val2)
if id == 'Zoom': target.set_zoom(val2)
return
def SetLabelProperty(target, id, val):
if id == 'Text': target.set_text(val)
return
def SetRollerProperty(target, id, val):
if id == 'Selected':
target.set_selected(val, lv.ANIM.OFF)
if id == 'Selected_with_anim':
target.set_selected(val, lv.ANIM.ON)
return
def SetSliderProperty(target, id, val):
if id == 'Value_with_anim': target.set_value(val, lv.ANIM.ON)
if id == 'Value': target.set_value(val, lv.ANIM.OFF)
return
def ChangeScreen( src, fademode, speed, delay):
lv.scr_load_anim(src, fademode, speed, delay, False)
return
def DeleteScreen(src):
return
def IncrementArc( trg, val):
trg.set_value(trg.get_value()+val)
lv.event_send(trg,lv.EVENT.VALUE_CHANGED, None)
return
def IncrementBar( trg, val, anim):
trg.set_value(trg.get_value()+val,anim)
return
def IncrementSlider( trg, val, anim):
trg.set_value(trg.get_value()+val,anim)
lv.event_send(trg,lv.EVENT.VALUE_CHANGED, None)
return
def KeyboardSetTarget( keyboard, textarea):
keyboard.set_textarea(textarea)
return
def ModifyFlag( obj, flag, value):
if (value=="TOGGLE"):
if ( obj.has_flag(flag) ):
obj.clear_flag(flag)
else:
obj.add_flag(flag)
return
if (value=="ADD"):
obj.add_flag(flag)
else:
obj.clear_flag(flag)
return
def ModifyState( obj, state, value):
if (value=="TOGGLE"):
if ( obj.has_state(state) ):
obj.clear_state(state)
else:
obj.add_state(state)
return
if (value=="ADD"):
obj.add_state(state)
else:
obj.clear_state(state)
return
def set_opacity(obj, v):
obj.set_style_opa(v, lv.STATE.DEFAULT|lv.PART.MAIN)
return
def SetTextValueArc( trg, src, prefix, postfix):
trg.set_text(prefix+str(src.get_value())+postfix)
return
def SetTextValueSlider( trg, src, prefix, postfix):
trg.set_text(prefix+str(src.get_value())+postfix)
return
def SetTextValueChecked( trg, src, txton, txtoff):
if src.has_state(lv.STATE.CHECKED):
trg.set_text(txton)
else:
trg.set_text(txtoff)
return
def StepSpinbox( trg, val):
if val==1 : trg.increment()
if val==-1 : trg.decrement()
lv.event_send(trg,lv.EVENT.VALUE_CHANGED, None)
return
# COMPONENTS
# COMPONENT Button2
def ui_Button2_create(comp_parent):
cui_Button2 = lv.btn(comp_parent)
cui_Button2.set_width(100)
cui_Button2.set_height(50)
cui_Button2.set_x(4)
cui_Button2.set_y(32)
cui_Button2.set_align( lv.ALIGN.CENTER)
SetFlag(cui_Button2, lv.obj.FLAG.SCROLLABLE, False)
SetFlag(cui_Button2, lv.obj.FLAG.SCROLL_ON_FOCUS, True)
_ui_comp_table[id(cui_Button2)]= {"Button2" : cui_Button2, "_CompName" : "Button2"}
return cui_Button2
ui____initial_actions0 = lv.obj()
def Button1_eventhandler(event_struct):
event = event_struct.code
if event == lv.EVENT.CLICKED and True:
pin38.value(1)
return
def Button2_eventhandler(event_struct):
event = event_struct.code
if event == lv.EVENT.CLICKED and True:
pin38.value(0)
return
ui_Screen1 = lv.obj()
SetFlag(ui_Screen1, lv.obj.FLAG.SCROLLABLE, False)
ui_Screen1.set_style_bg_color(lv.color_hex(0xF6E6DE), lv.PART.MAIN | lv.STATE.DEFAULT )
ui_Screen1.set_style_bg_opa(255, lv.PART.MAIN| lv.STATE.DEFAULT )
ui_Button1 = lv.btn(ui_Screen1)
ui_Button1.set_width(80)
ui_Button1.set_height(79)
ui_Button1.set_x(-80)
ui_Button1.set_y(0)
ui_Button1.set_align( lv.ALIGN.CENTER)
SetFlag(ui_Button1, lv.obj.FLAG.SCROLLABLE, False)
SetFlag(ui_Button1, lv.obj.FLAG.SCROLL_ON_FOCUS, True)
ui_Button1.set_style_bg_color(lv.color_hex(0xFFFFFF), lv.PART.MAIN | lv.STATE.DEFAULT )
ui_Button1.set_style_bg_opa(255, lv.PART.MAIN| lv.STATE.DEFAULT )
ui_Button1.set_style_bg_img_src( ui_images.ui_img_on_png, lv.PART.MAIN | lv.STATE.DEFAULT )
ui_Button1.set_style_bg_color(lv.color_hex(0xF20D0D), lv.PART.MAIN | lv.STATE.PRESSED )
ui_Button1.set_style_bg_opa(255, lv.PART.MAIN| lv.STATE.PRESSED )
ui_Button1.add_event_cb(Button1_eventhandler, lv.EVENT.ALL, None)
ui_Button2 = lv.btn(ui_Screen1)
ui_Button2.set_width(80)
ui_Button2.set_height(79)
ui_Button2.set_x(76)
ui_Button2.set_y(0)
ui_Button2.set_align( lv.ALIGN.CENTER)
SetFlag(ui_Button2, lv.obj.FLAG.SCROLLABLE, False)
SetFlag(ui_Button2, lv.obj.FLAG.SCROLL_ON_FOCUS, True)
ui_Button2.set_style_bg_color(lv.color_hex(0xFCFBFB), lv.PART.MAIN | lv.STATE.DEFAULT )
ui_Button2.set_style_bg_opa(255, lv.PART.MAIN| lv.STATE.DEFAULT )
ui_Button2.set_style_bg_img_src( ui_images.ui_img_off_png, lv.PART.MAIN | lv.STATE.DEFAULT )
ui_Button2.set_style_bg_color(lv.color_hex(0x7B7979), lv.PART.MAIN | lv.STATE.PRESSED )
ui_Button2.set_style_bg_opa(255, lv.PART.MAIN| lv.STATE.PRESSED )
ui_Button2.add_event_cb(Button2_eventhandler, lv.EVENT.ALL, None)
ui_Image1 = lv.img(ui_Screen1)
ui_Image1.set_src(ui_images.ui_img_background_png)
ui_Image1.set_width(lv.SIZE.CONTENT) # 1
ui_Image1.set_height(lv.SIZE.CONTENT) # 1
ui_Image1.set_x(0)
ui_Image1.set_y(-99)
ui_Image1.set_align( lv.ALIGN.CENTER)
SetFlag(ui_Image1, lv.obj.FLAG.ADV_HITTEST, True)
SetFlag(ui_Image1, lv.obj.FLAG.SCROLLABLE, False)
lv.scr_load(ui_Screen1)
Code Explanation¶
Libraries imported in this example¶
import lvgl as lv
import lv_utils
import tft_config
from xpt import Touch
from machine import SPI, Pin
import time
import fs_driver
import ui_images
-
lvgl: This is an open-source embedded graphics library used to create cross platform GUI. LVGL is written in C, but provides bindings for multiple languages, including Python. It supports multiple display types and input devices, making it ideal for touch screen applications on microcontrollers.
-
lv_utils: This library may be an auxiliary library for LVGL, providing additional utilities or functions to help developers use LVGL more easily. Specific functions may include simplified API calls, universal configuration functions, etc.
-
tft_config: This library may be used to configure TFT (Thin Film Transistor) displays. In embedded systems, TFT displays are commonly used to display graphical interfaces.The
tft_config
library may contain functions for initializing the display, setting resolution, color depth, and other configurations. -
xpt: This library may refer to an abbreviation for X-Power Technology, a company that provides touch controllers. The 'Touch' class here may be used to initialize and control touch screens, allowing users to interact with GUI through touch.
-
machine : This is a standard library for MicroPython used for interacting with hardware devices. It provides methods for accessing and controlling hardware interfaces such as GPIO (General Purpose Input/Output) pins, SPI (Serial Peripheral Interface) bus, I2C (Integrated Circuit Bus) of microcontrollers.
-
time: This is the standard library in Python used for time related operations, such as pausing program execution (sleep function), retrieving the current time, etc.
-
fs_deriver: This library may refer to a file system driver used to manage file systems on microcontrollers. It may include functions such as reading and writing files, directory operations, etc.
-
ui_images: This library may be used to manage image resources in the user interface. It may include functions such as loading images into memory and displaying images on the GUI.
Basic Definition¶
Set up the GPIO38 for LED.
Screen and touch driver initialization¶
# Define the width and height of the LCD display
WIDTH = 480
HEIGHT = 272
# tft drvier
tft = tft_config.config()
# touch drvier
# Initialize SPI bus for touch driver communication
spi = SPI(2, baudrate=1000000)
spi.init(sck=Pin(12), mosi=Pin(11), miso=Pin(13))# Initialize SPI bus, set clock, data send and receive pins
cs = Pin(0, mode=Pin.OUT, value=1)# Set the chip selection pin to a high initial state
int_pin = Pin(36)# Set touch interrupt pin
xpt = Touch(spi, cs=cs, int_pin=int_pin)# Initialize touch driver, input SPI bus, chip selection, and interrupt pins
# Calibrate the touch screen, set the screen coordinate range and actual display resolution
xmin = 96
xmax = 1951
ymin = 175
ymax = 1908
orientation = 0 # Screen orientation
xpt.calibrate(xmin, xmax, ymin, ymax, 480, 272, orientation)
# Initialize LVGL graphics library
lv.init()
# Check if the event loop is running, if not, create one
if not lv_utils.event_loop.is_running():
event_loop = lv_utils.event_loop() # Create an event loop object
print(event_loop.is_running())
# Create display buffer
disp_buf0 = lv.disp_draw_buf_t() # Create display driver buffer object
buf1_0 = bytearray(WIDTH * 10) # Allocate buffer memory
disp_buf0.init(buf1_0, None, len(buf1_0) // lv.color_t.__SIZE__) # Initialize buffer
# Register display driver
disp_drv = lv.disp_drv_t() # Create display driver object
disp_drv.init() # Initialize display driver
disp_drv.draw_buf = disp_buf0 # Set display buffer
disp_drv.flush_cb = tft.flush # Set a refresh callback function to refresh the displayed content
disp_drv.hor_res = WIDTH # Set horizontal resolution
disp_drv.ver_res = HEIGHT # Set vertical resolution
# disp_drv.user_data = {"swap": 0} # Optional: Set user data, such as swapping color channels
disp0 = disp_drv.register() # Register display driver
lv.disp_t.set_default(disp0) # Set default display driver
# Initialize touch input device driver
indev_drv = lv.indev_drv_t() # Create input device driver object
indev_drv.init() # Initialize input device driver
indev_drv.disp = disp0 # Associate display driver
indev_drv.type = lv.INDEV_TYPE.POINTER # Set the input device type to pointer
indev_drv.read_cb = xpt.read # Set callback function for reading touch data
indev = indev_drv.register() # Register input device driver
UI code¶
This part copies the code of ui.py generated by Squareline Studio. We need to modify the part that control the button.
Modify from
to
def Button1_eventhandler(event_struct):
event = event_struct.code
if event == lv.EVENT.CLICKED and True:
pin38.value(1)
return
def Button2_eventhandler(event_struct):
event = event_struct.code
if event == lv.EVENT.CLICKED and True:
pin38.value(0)
return
Upload the code¶
Please click to download the code file and libraries.
Upload the libraries¶
ui_image.py
-
In the upper left corner of the thonny, enter the path where ui_image.py is located, right-click ui_image.py, and click Upload to/
-
ui_image.py is added to MicroPython device successfully.
Upload the code¶
Click the "run" icon.
Successfully uploaded.
GPIO Examples¶
Please click to download the code files.
Example 1 Turn on/off the LED in a loop¶
Connect an LED module to the D port(pin38) of ESP32 4.3'' HMI, and upload the following code. The LED will turn on and off in a loop.
#Make by Elecrow
#Web:www.elecrow.com
import time
from machine import Pin
pin38 = Pin(38, Pin.OUT)
while True:
pin38.value(1)
time.sleep(0.5)
pin38.value(0)
time.sleep(0.5)
Example 2 Show dial plate on the screen¶
Upload the following code to the module, there will be a dial plate show on the screen.
#Make by Elecrow
#Web:www.elecrow.com
import lvgl as lv
import lv_utils
import tft_config
from xpt import Touch
from machine import SPI, Pin
import time
import fs_driver
WIDTH = 480
HEIGHT = 272
# tft drvier
tft = tft_config.config()
# touch drvier
spi = SPI(2, baudrate=1000000)
spi.init(sck=Pin(12), mosi=Pin(11), miso=Pin(13))
cs = Pin(0, mode=Pin.OUT, value=1)
int_pin = Pin(36)
xpt = Touch(spi, cs=cs, int_pin=int_pin)
xmin = 96
xmax = 1951
ymin = 175
ymax = 1908
orientation = 0
xpt.calibrate(xmin, xmax, ymin, ymax, 480, 272, orientation)
lv.init()
if not lv_utils.event_loop.is_running():
event_loop=lv_utils.event_loop()
print(event_loop.is_running())
# create a display 0 buffer
disp_buf0 = lv.disp_draw_buf_t()
buf1_0 = bytearray(WIDTH * 10)
disp_buf0.init(buf1_0, None, len(buf1_0) // lv.color_t.__SIZE__)
# register display driver
disp_drv = lv.disp_drv_t()
disp_drv.init()
disp_drv.draw_buf = disp_buf0
disp_drv.flush_cb = tft.flush
disp_drv.hor_res = WIDTH
disp_drv.ver_res = HEIGHT
# disp_drv.user_data = {"swap": 0}
disp0 = disp_drv.register()
lv.disp_t.set_default(disp0)
# touch driver init
indev_drv = lv.indev_drv_t()
indev_drv.init()
indev_drv.disp = disp0
indev_drv.type = lv.INDEV_TYPE.POINTER
indev_drv.read_cb = xpt.read
indev = indev_drv.register()
# 1. Create a display screen. Will need to display the component added to the screen to display
scr = lv.obj() # scr====> screen
fs_drv = lv.fs_drv_t()
fs_driver.fs_register(fs_drv, 'S')
scr = lv.scr_act()
scr.clean()
# 2. Encapsulate the component to display
class MyWidget():
def __init__(self, scr):
# 1. Create the dashboard object
self.meter = lv.meter(scr)
self.meter.center()
self.meter.set_size(200, 200) # width: 200 height: 200
# 2. To create calibration object
scale = self.meter.add_scale()
self.meter.set_scale_ticks(scale, 51, 2, 10, lv.palette_main(lv.PALETTE.GREY))
self.meter.set_scale_major_ticks(scale, 10, 4, 15, lv.color_black(), 20)
# 3. Add warning scale line
blue_arc = self.meter.add_arc(scale, 2, lv.palette_main(lv.PALETTE.BLUE), 0)
self.meter.set_indicator_start_value(blue_arc, 0)
self.meter.set_indicator_end_value(blue_arc, 20)
blue_arc_scale = self.meter.add_scale_lines(scale, lv.palette_main(lv.PALETTE.BLUE), lv.palette_main(lv.PALETTE.BLUE), False, 0)
self.meter.set_indicator_start_value(blue_arc_scale, 0)
self.meter.set_indicator_end_value(blue_arc_scale, 20)
red_arc = self.meter.add_arc(scale, 2, lv.palette_main(lv.PALETTE.RED), 0)
self.meter.set_indicator_start_value(red_arc, 80)
self.meter.set_indicator_end_value(red_arc, 100)
red_arc_scale = self.meter.add_scale_lines(scale, lv.palette_main(lv.PALETTE.RED), lv.palette_main(lv.PALETTE.RED), False, 0)
self.meter.set_indicator_start_value(red_arc_scale, 80)
self.meter.set_indicator_end_value(red_arc_scale, 100)
# 4. meter needle
self.indic = self.meter.add_needle_line(scale, 4, lv.palette_main(lv.PALETTE.GREY), -10)
# 5. Creating animated objects
a = lv.anim_t()
a.init()
a.set_var(self.indic)
a.set_values(0, 100)
a.set_time(2000)
a.set_repeat_delay(100)
a.set_playback_time(500)
a.set_playback_delay(100)
a.set_repeat_count(lv.ANIM_REPEAT.INFINITE)
a.set_custom_exec_cb(self.set_value)
lv.anim_t.start(a)
def set_value(self, anmi_obj, value):
"""Animation callbacks"""
self.meter.set_indicator_value(self.indic, value)
# 3. Create the component to display
MyWidget(scr)
# 4. Displays the contents of the screen object
lv.scr_load(scr)
# ------------------------------ Guard dog to restart ESP32 equipment --start------------------------
try:
from machine import WDT
wdt = WDT(timeout=1000) # enable it with a timeout of 2s
print("Hint: Press Ctrl+C to end the program")
while True:
wdt.feed()
time.sleep(0.9)
except KeyboardInterrupt as ret:
print("The program stopped running, ESP32 has restarted...")
tft.deinit()
time.sleep(10)
# ------------------------------ Guard dog to restart ESP32 equipment --stop-------------------------
Example 3 Connect WiFi¶
Upload the following code to ESP32 HMI(note to modify the WiFi ssid and password to yours)
import network
import time
def connect():
ssid = 'yanfa_software'
password = 'yanfa-123456'
wlan = network.WLAN(network.STA_IF) # Create a WLAN object in station mode
wlan.active(True) # Activate the network interface
wlan.connect(ssid, password) # Connect to the specified WiFi network
while not wlan.isconnected(): # Wait for the connection to be established
print('Waiting for connection...')
time.sleep(1)
print('Connected on {ip}'.format(ip=wlan.ifconfig()[0])) # Print the IP address
connect()
Running result:
Example 4 Playing music¶
Connect a speaker to the ESP32 HMI. Upload the following code.
import os
import math
import struct
from machine import I2S
from machine import Pin
def make_tone(rate, bits, frequency):
# create a buffer containing the pure tone samples
samples_per_cycle = rate // frequency
sample_size_in_bytes = bits // 8
samples = bytearray(samples_per_cycle * sample_size_in_bytes)
volume_reduction_factor = 32
range = pow(2, bits) // 2 // volume_reduction_factor
if bits == 16:
format = "<h"
else: # assume 32 bits
format = "<l"
for i in range(samples_per_cycle):
sample = range + int((range - 1) * math.sin(2 * math.pi * i / samples_per_cycle))
struct.pack_into(format, samples, i * sample_size_in_bytes, sample)
return samples
if os.uname().machine.count("PYBv1"):
# ======= I2S CONFIGURATION =======
SCK_PIN = "Y6"
WS_PIN = "Y5"
SD_PIN = "Y8"
I2S_ID = 2
BUFFER_LENGTH_IN_BYTES = 2000
# ======= I2S CONFIGURATION =======
elif os.uname().machine.count("PYBD"):
import pyb
pyb.Pin("EN_3V3").on() # provide 3.3V on 3V3 output pin
# ======= I2S CONFIGURATION =======
SCK_PIN = "Y6"
WS_PIN = "Y5"
SD_PIN = "Y8"
I2S_ID = 2
BUFFER_LENGTH_IN_BYTES = 2000
# ======= I2S CONFIGURATION =======
elif os.uname().machine.count("ESP32"):
# ======= I2S CONFIGURATION =======
SCK_PIN = 35
WS_PIN = 19
SD_PIN = 20
I2S_ID = 0
BUFFER_LENGTH_IN_BYTES = 2000
# ======= I2S CONFIGURATION =======
elif os.uname().machine.count("Raspberry"):
# ======= I2S CONFIGURATION =======
SCK_PIN = 16
WS_PIN = 17
SD_PIN = 18
I2S_ID = 0
BUFFER_LENGTH_IN_BYTES = 1000
# ======= I2S CONFIGURATION =======
elif os.uname().machine.count("MIMXRT"):
# ======= I2S CONFIGURATION =======
SCK_PIN = 4
WS_PIN = 3
SD_PIN = 2
I2S_ID = 2
BUFFER_LENGTH_IN_BYTES = 2000
# ======= I2S CONFIGURATION =======
else:
print("Warning: program not tested with this board")
# ======= AUDIO CONFIGURATION =======
TONE_FREQUENCY_IN_HZ = 440
SAMPLE_SIZE_IN_BITS = 16
FORMAT = I2S.MONO # only MONO supported in this example
SAMPLE_RATE_IN_HZ = 22_050
# ======= AUDIO CONFIGURATION =======
audio_out = I2S(
I2S_ID,
sck=Pin(SCK_PIN),
ws=Pin(WS_PIN),
sd=Pin(SD_PIN),
mode=I2S.TX,
bits=SAMPLE_SIZE_IN_BITS,
format=FORMAT,
rate=SAMPLE_RATE_IN_HZ,
ibuf=BUFFER_LENGTH_IN_BYTES,
)
samples = make_tone(SAMPLE_RATE_IN_HZ, SAMPLE_SIZE_IN_BITS, TONE_FREQUENCY_IN_HZ)
# continuously write tone sample buffer to an I2S DAC
print("========== START PLAYBACK ==========")
try:
while True:
num_written = audio_out.write(samples)
except (KeyboardInterrupt, Exception) as e:
print("caught exception {} {}".format(type(e).__name__, e))
# cleanup
audio_out.deinit()
print("Done")
For more demo of the i2s speaker please refer to: https://github.com/miketeachman/micropython-i2s-examples
Example 5 Initialize UART port¶
Upload the following code
import machine
import time
# Initialize UART
uart = machine.UART(1, baudrate=115200, tx=17, rx=18)
def send_data(data):
uart.write(data) # Send data via UART
print("Sent:", data)
def receive_data():
if uart.any(): # Check for readable data
data = uart.read() # retrieve data
print("Received:", data)
return data
return None
# Example: Sending and Receiving Data
send_data('Hello, UART!\n')
while True:
received = receive_data()
if received:
# do something about it
pass
time.sleep(1)
Running result: