ESP32S3——基于MicroPython开发(1)

ESP32S3——基于MicroPython开发

Thonny Python IDE 是款开源软件, 以极简方式设计, 对 MicroPython 的兼容性友善。 而且支持 Windows、 Mac OS、Linux、 树莓

派。 由于开源, 所以软件迭代速度快, 功能日趋成熟。 使用 Thonny 还有一个方便之处, 可直接在该软件中实现程序开发和下载。

import sys
import machine
import time

# 获取并打印 CPU 频率 (单位转换为 MHz)
freq = machine.freq() / 1000000
print(f"Device Info: {sys.platform}\nCPU Freq: {freq} MHz")

count = 0

try:
    while True:
        # 打印当前计数值
        print(f"Hello World! {count}")
        count += 1
        # 延时 1 秒
        time.sleep(1)
except KeyboardInterrupt:
    # 当检测到键盘中断(CTRL+C)时执行此块代码
    print("Exit")

第1章_LED实验

image-20260911091600979image-20260911091726847

# 点亮第一个LED(共阴极)

# 导入Pin模块
from machine import Pin

led = Pin(7, Pin.OUT)     # 构建led对象,GPIO7输出
led.value(1)              # 使IO7输出高电平,点亮LED
 
# led.value(0)              # 使IO7出低电平,熄灭LED

from machine import Pin   # 导入Pin模块
import time               # 导入time模块

led = Pin(7,Pin.OUT)      # 构建led对象,GPIO7输出

# 循环
while True:
    led.value(1)       # 使IO7输出高电平,点亮LED
    time.sleep(0.5)    # 延时0.5秒
    led.value(0)       # 使IO7输出低电平,熄灭LED
    time.sleep(0.5)    # 延时0.5秒

Python中用到延时,可使用time模块,time模块中常用的几个延时函数如下:

image-20260911093513830

第2章_蜂鸣器鸣响

让 ESP32 的 IO 口输出一个 2KHz 频率的脉冲信号控制板载无源蜂鸣器发声:

from machine import Pin   # 导入Pin模块
import time               # 导入time模块

beep = Pin(7,Pin.OUT)     # 定义蜂鸣器控制对象

# 程序入口
if __name__ == "__main__":
    i = 0
    while True:
        i = not i           # 非运算
        beep.value(i)
        time.sleep_us(250)  # 脉冲频率为2kHz

频率为2KHz,则周期为0.5ms,若占空比为50%,则高低电平分别输出时间为0.25ms,即250us,如下图所示:

image-20260911095024876

image-20260911095443165

简单举例:

def hello():
    print("hello")

# 只有直接运行本文件时才会调用hello()
if __name__ == "__main__":
    hello()

  • 直接运行 python test.py → 打印 hello
  • 在另一个文件写 import test → 不会自动打印 hello,只会导入 hello 函数

作用

  • 写模块 / 工具库:模块被导入时不会自动跑测试代码
  • 方便给当前脚本写自测代码,导入给别人用的时候不会乱执行

一句话总结:用来区分:当前脚本是直接运行,还是被当作库导入。

第3章_继电器实验

继电器接线示意图如下所示:

image-20260911095955660

默认情况下,常闭触点和公共触点是导通连接在一起的,当继电器工作后,公共触点和常闭触点就断开,然后常开触点和公共触点导通连接在一起,就行船型开关一样。

COM 为公共触点、 NO 为常开触点、NC 为常闭触点。

# 导入Pin模块
from machine import Pin
import time

# 定义继电器控制对象
relay = Pin(7,Pin.OUT)

# 程序入口
if __name__ == "__main__":

    i = 0
    while True:
        i = not i
        relay.value(i)
        time.sleep(1)

第4章_按键控制实验

image-20260911102259897

# 导入Pin模块
from machine import Pin
import time

# 定义按键控制的对象
key1 = Pin(10,Pin.IN,Pin.PULL_UP)
key2 = Pin(11,Pin.IN,Pin.PULL_UP)
key3 = Pin(12,Pin.IN,Pin.PULL_UP)
key4 = Pin(13,Pin.IN,Pin.PULL_UP)

# 定义LED控制对象
led1 = Pin(1,Pin.OUT)
led2 = Pin(2,Pin.OUT)
led3 = Pin(3,Pin.OUT)
led4 = Pin(4,Pin.OUT)

# 定义按键键值
KEY1_PRESS,KEY2_PRESS,KEY3_PRESS,KEY4_PRESS = 1,2,3,4
key_en = 1

# 按键扫描函数
def key_scan():
    global key_en                                 # 全局变量
    # 如果允许检测key_en == 1,并且任意按键按下
    if key_en == 1 and (key1.value() == 0 or key2.value() == 0 or
                        key3.value() == 0 or key4.value() == 0):
        time.sleep_ms(10)                         # 消抖延时
        key_en = 0                                # 锁住,不在重复触发
        # 判断是哪个按键按下,返回按键编号
        if   key1.value() == 0:
            return KEY1_PRESS
        elif key2.value() == 0:
            return KEY2_PRESS    
        elif key3.value() == 0:
            return KEY3_PRESS
        elif key4.value() == 0:
            return KEY4_PRESS
    # 全部按键松开,恢复使能标记key_en == 1,允许下次检测
    elif key1.value() == 1 and key2.value() == 1 and key3.value() == 1 and key4.value() == 1:
        key_en = 1
    return 0
    
# 程序入口
if __name__ == "__main__":
    key = 0
    i_led1,i_led2,i_led3,i_led4 = 0,0,0,0   # 定义变量,用于LLED状态翻转
    led1.value(i_led1)                      # 初始化LED,熄灭状态
    led2.value(i_led2)
    led3.value(i_led3)
    led4.value(i_led4)
    while True:
        key = key_scan()                    # 按键扫描
        
        if key == KEY1_PRESS:               # K1键按下
            i_led1 = not i_led1
            led1.value(i_led1)
            
        if key == KEY2_PRESS:               # K2键按下
            i_led2 = not i_led2
            led2.value(i_led2)
            
        if key == KEY3_PRESS:               # K3键按下
            i_led3 = not i_led3
            led3.value(i_led3)
            
        if key == KEY4_PRESS:               # K4键按下
            i_led4 = not i_led4
            led4.value(i_led4)

第5章_直流电机实验

image-20260911133834620

from machine import Pin
import time

# 定义直流电机控制对象
dc_motor = Pin(15,Pin.OUT,Pin.PULL_DOWN)


# 程序入口
if __name__ == "__main__":
    dc_motor.value(1)         # 电机开启
    time.sleep(3)
    dc_motor.value(0)         # 电机停止
    print("while···")
try:
    
    while True:
        pass
    
except KeyboardInterrupt:
    # 当检测到键盘中断(CTRL+C)时执行此块代码
    print("Exit")

在配置IO上下拉时,为了初始状态让电机停止,此时配置为下拉,即ULN2003输入为低,输出则为高阻态,电机停止。

在 Python 中, pass 是一个空语句, 为了保持程序结构的完整性。 一般情况下, pass 不做任何事情, 被用做占位符。

第6章_步进电机实验

28BYJ48 步进电机自带减速器, 为五线四相步进电机, 直径为 28mm, 实物如下所示:

image-20260911134344784

28BYJ48 电机内部结构等效图如下所示:

image-20260911134502126

步进电机旋转控制图:

image-20260911134554583

28BYJ48 步进电机旋转驱动方式如下表:

image-20260911134646682

28BYJ48 步进电机主要参数如下所示:

image-20260911134728820

在上图中 28BYJ48 步进电机主要参数中可以看到有一个减速比: 1:64, 步进角为 5.625/64 度, 如果需要转动一圈, 那么需要

360/5.625*64=4096 个脉冲信号。

减速比这个和之前介绍的直流减速电机有点类似, 所以 28BYJ48 步进电机实际上是: 减速齿轮+步进电机组成, 28BYJ48 步进电机减速

齿轮实物图如下所示:

image-20260911134922540

减速齿轮计算方法如下所示:

image-20260911135036894

# 导入Pin模块
from machine import Pin
import time

# 定义按键控制对象
key1 = Pin(10,Pin.IN,Pin.PULL_UP)
key2 = Pin(11,Pin.IN,Pin.PULL_UP)
key3 = Pin(12,Pin.IN,Pin.PULL_UP)
key4 = Pin(13,Pin.IN,Pin.PULL_UP)

# 定义步进电机控制对象
motor_a = Pin(1,Pin.OUT,Pin.PULL_DOWN)
motor_b = Pin(2,Pin.OUT,Pin.PULL_DOWN)
motor_c = Pin(3,Pin.OUT,Pin.PULL_DOWN)
motor_d = Pin(4,Pin.OUT,Pin.PULL_DOWN)

# 定义按键键值
KEY1_PRESS,KEY2_PRESS,KEY3_PRESS,KEY4_PRESS = 1,2,3,4
key_en = 1

# 按键扫描函数
debounce_t = 0
DEB_TIME = 10
def key_scan():
    global key_en, debounce_t
    now = time.ticks_ms()
    if key_en == 1 and (key1.value() == 0 or key2.value() == 0 or
                        key3.value() == 0 or key4.value() == 0):
        if time.ticks_diff(now, debounce_t) > DEB_TIME:
            key_en = 0
            if   key1.value() == 0:
                return KEY1_PRESS
            elif key2.value() == 0:
                return KEY2_PRESS
            elif key3.value() == 0:
                return KEY3_PRESS
            elif key4.value() == 0:
                return KEY4_PRESS
    elif key1.value() == 1 and key2.value() == 1 and key3.value() == 1 and key4.value() == 1:
        debounce_t = time.ticks_ms()
        key_en = 1
    return 0
        
# 步进电机发送脉冲函数 8拍半步驱动
def step_motor_send_pulse(step,fx):
    temp = step
    if fx == 0:
        temp = 7 - step
    if temp == 0:
        motor_a.value(1)
        motor_b.value(0)
        motor_c.value(0)
        motor_d.value(0)
    elif temp == 1:
        motor_a.value(1)
        motor_b.value(1)
        motor_c.value(0)
        motor_d.value(0)
    elif temp == 2:
        motor_a.value(0)
        motor_b.value(1)
        motor_c.value(0)
        motor_d.value(0)
    elif temp == 3:
        motor_a.value(0)
        motor_b.value(1)
        motor_c.value(1)
        motor_d.value(0)
    elif temp == 4:
        motor_a.value(0)
        motor_b.value(0)
        motor_c.value(1)
        motor_d.value(0)
    elif temp == 5:
        motor_a.value(0)
        motor_b.value(0)
        motor_c.value(1)
        motor_d.value(1)
    elif temp == 6:
        motor_a.value(0)
        motor_b.value(0)
        motor_c.value(0)
        motor_d.value(1)
    elif temp == 7:
        motor_a.value(1)
        motor_b.value(0)
        motor_c.value(0)
        motor_d.value(1)       

# 程序入口
if __name__ == "__main__":
    key = 0
    fx1 = 1
    STEP_MAXSPEED = 1
    STEP_MINSPEED = 5
    speed1 = STEP_MAXSPEED
    step1 = 0  
    print("while···")
    try:
        while True:
            key = key_scan()
            if   key == KEY1_PRESS:
                fx1 = not fx1               # K1:换向
            elif key == KEY2_PRESS:
                if speed1 < STEP_MINSPEED:
                    speed1 += 1             # K2:减速,延时变大
            elif key == KEY3_PRESS:
                if speed1 > STEP_MAXSPEED:
                    speed1 -= 1             # K3:加速,延时变小
            elif key == KEY4_PRESS:
                pass                        # 可以在这里扩展功能:启停/固定步数
            
            step_motor_send_pulse(step1,fx1)
            step1 += 1
            if step1 == 8:
                step1 = 0
            time.sleep_ms(speed1)
            
    except KeyboardInterrupt:
        # 当检测到键盘中断(CTRL+C)时执行此块代码
        motor_a.value(0)
        motor_b.value(0)
        motor_c.value(0)
        motor_d.value(0)
        print("Exit, motor power off")

关于非阻塞消抖:

# 简化版
DEB_TIME = 10
now = time.ticks_ms()
if key_en == 1 and  任意按键低电平:
    if time.ticks_diff(now, old_time) > DEB_TIME:
        key_en = 0
        return按键编号
elif 全部按键高电平:
    old_time = time.ticks_ms()
    key_en = 1

逻辑简化版原理:

  • 一旦检测有按键按下,开始计时;
  • 持续 10ms仍然保持按键按下 → 判定有效按键,触发一次;
  • 锁定key_en,不再重复触发;
  • 必须等到所有按键全部松开,重置时间戳,解锁,等待下一次按键。

time.ticks_ms():返回系统开机以来的毫秒计数器

时间差专用计算函数:time.ticks_diff(now, old_time),它自动处理计数器溢出,算正确时间差。

第7章_外部中断实验

image-20260911152132944

from machine import Pin
import time

# 按键IO
key1 = Pin(1,Pin.IN,Pin.PULL_UP)
key2 = Pin(2,Pin.IN,Pin.PULL_UP)
key3 = Pin(4,Pin.IN,Pin.PULL_UP)
key4 = Pin(5,Pin.IN,Pin.PULL_UP)

# LED_Pin13
led1 = Pin(13,Pin.OUT)
led1_state = 0

# 全局变量
key_flag = 0
DEB_MS = 10
last_t = 0

# 中断回调函数,只打标记,不做任何延时、IO动作 
def key1_irq(pin):
    global key_flag
    key_flag = 1

def key2_irq(pin):
    global key_flag
    key_flag = 2

def key3_irq(pin):
    global key_flag
    key_flag = 3

def key4_irq(pin):
    global key_flag
    key_flag = 4

if __name__ == "__main__":
    led1.value(led1_state)
    # 绑定外部中断,下降沿触发
    key1.irq(key1_irq, Pin.IRQ_FALLING)
    key2.irq(key2_irq, Pin.IRQ_FALLING)
    key3.irq(key3_irq, Pin.IRQ_FALLING)
    key4.irq(key4_irq, Pin.IRQ_FALLING)

    while True:
        now = time.ticks_ms()
        if key_flag !=0:
            # 非阻塞消抖
            if time.ticks_diff(now, last_t) > DEB_MS:
                if key_flag == 1 and key1.value() ==0:
                    led1_state = not led1_state
                    led1.value(led1_state)
                elif key_flag ==2 and key2.value() ==0:
                    led1_state = not led1_state
                    led1.value(led1_state)
                elif key_flag ==3 and key3.value() ==0:
                    led1_state = not led1_state
                    led1.value(led1_state)
                elif key_flag ==4 and key4.value() ==0:
                    led1_state = not led1_state
                    led1.value(led1_state)
                last_t = now
                key_flag = 0    #清除标志,等待下次按键


posted @ 2026-09-11 18:37  Q&25  阅读(11)  评论(4)    收藏  举报