You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MicroPython热敏电阻步进电机温度表故障:单向移动卡死

温度控制步进电机异常循环问题

现象

  • 程序初始运行正常,无大幅温度波动时工作稳定,但会出现持续判定wanted_pos > current_pos,驱动电机一直向上移动的卡死情况
  • 触发场景:程序启动后静置一段时间,或重启后快速改变温度

预期逻辑

  1. 读取热敏电阻温度值TempF,转换为步进电机0-450步的目标位置:wanted_pos = TempF * 450 / 100
  2. 对比wanted_pos与当前位置current_pos,根据差值正负设置方向引脚dir_pin的通断
  3. 计算需要移动的步数并驱动电机
  4. 开机初始化:若变量未赋值,将电机从0移动到初始目标位置,初始化变量后进入主循环

问题代码

from machine import ADC
from machine import Pin
import time
import math
    
off = 0
on = 1
dir_pin = Pin(20, Pin.OUT)  # 步进电机方向引脚 1/0
step_pin = Pin(21, Pin.OUT)  # 步进电机脉冲引脚
adcpin = 26  # 热敏电阻数据引脚
thermistor = ADC(adcpin)
Vin = 3.3  # 系统总线电压
Ro = 10000  # 分压电阻(10k)
delay = 0.006  # 步进延迟时间
# 斯泰因哈特-哈特方程常数
A = 0.001129148
B = 0.000234125
C = 0.0000000876741

def get_current_pos(steps_to_move, last_dir, last_pos):
    print("get current position called")
    if last_dir == off:
        current_pos = last_pos + steps_to_move
        print(current_pos)
    elif last_dir == on:
        current_pos = last_pos - steps_to_move
        print(current_pos)
    else:
        current_pos = last_pos


def get_temp_pos():
    print("get temp position")
    adc = thermistor.read_u16()
    Vout = (3.3/65535)*adc
    # 计算热敏电阻阻值
    try:
        
        Rt = (Vout*Ro) / (Vin - Vout)
        # 斯泰因哈特-哈特方程计算开尔文温度
        TempK = 1 / (A + (B * math.log(Rt)) + C * math.pow(math.log(Rt), 3))

        # 转换为摄氏度和华氏度
        TempC = TempK - 253.15
        global TempF
        TempF = TempC * 1.8 + 32
        if TempF > 100:
            global TempF
            TempF = 100
        elif TempF < 0:
            global TempF
            TempF = 1
        else:
            print("happy range")
            print(TempF)
    except ZeroDivisionError:
        global wanted_pos
        wanted_pos = 0
        
def get_wanted_pos():
    global wanted_pos
    wanted_pos = TempF * 450 / 100
    print("wanted pos")
    print(wanted_pos)
    global current_pos



def get_steps_to_move(wanted_pos, current_pos):
    print("get steps to move")
    if wanted_pos > current_pos:
        global steps_to_move
        steps_to_move = wanted_pos - current_pos
        print(steps_to_move)
    elif wanted_pos < current_pos:
        global steps_to_move
        steps_to_move = current_pos - wanted_pos
        print(steps_to_move)
        print("2")
    elif wanted_pos == current_pos:
        global steps_to_move
        steps_to_move = 0
        print(steps_to_move)
    else:
        pass
        
def move_motor(steps_to_move):
    global last_pos
    last_pos = current_pos
    print("motor call")
    print(TempF)
    for _ in range(steps_to_move): 
        step_pin.on()
        time.sleep(delay)
        step_pin.off()
        time.sleep(delay)
    time.sleep(2)

def define_zero():
    print("define 0")
    get_temp_pos()
    get_wanted_pos()
    global steps_to_move
    steps_to_move = wanted_pos
    global current_pos
    current_pos = wanted_pos
    global last_pos
    last_pos = current_pos
    global last_dir
    last_dir = off
    dir_pin.off()
    move_motor(steps_to_move)
    
    
while True:
    if 'last_dir' in globals():
        get_current_pos(steps_to_move, last_dir, last_pos)
        get_temp_pos()
        get_wanted_pos()
        if wanted_pos > current_pos:
            dir_pin.off()
            last_dir = off
            print("OFF")
        elif wanted_pos < current_pos:
            last_dir = on
            dir_pin.on()
            print("ON")
        else:
            ("same_error")
        get_steps_to_move(wanted_pos, current_pos)
        move_motor(steps_to_move)
    else:
        define_zero()

问题根源与修复

1. 全局变量current_pos未被正确更新

get_current_pos函数内部计算了当前位置,但未声明global current_pos,导致全局变量始终保留初始值,主循环一直认为目标位置大于当前位置,驱动电机持续向上移动。
修复:

def get_current_pos(steps_to_move, last_dir, last_pos):
    global current_pos  # 添加全局声明
    print("get current position called")
    if last_dir == off:
        current_pos = last_pos + steps_to_move
        print(current_pos)
    elif last_dir == on:
        current_pos = last_pos - steps_to_move
        print(current_pos)
    else:
        current_pos = last_pos

2. 温度转换公式错误

开尔文转摄氏度的公式写错为TempC = TempK - 253.15,正确应为TempC = TempK - 273.15,这会导致温度值计算偏差,间接引发位置判断错误。
修复:

TempC = TempK - 273.15

3. last_pos更新时机错误

move_motor函数中在电机移动前就将last_pos设为current_pos,导致last_pos无法正确记录电机移动后的实际位置。
修复:

def move_motor(steps_to_move):
    global last_pos
    print("motor call")
    print(TempF)
    for _ in range(steps_to_move): 
        step_pin.on()
        time.sleep(delay)
        step_pin.off()
        time.sleep(delay)
    last_pos = current_pos  # 移动完成后更新位置
    time.sleep(2)

4. 初始化逻辑中last_pos赋值错误

define_zero中把last_pos设为目标位置current_pos,但初始化是从0移动到目标位置,last_pos应该初始为0。
修复:

def define_zero():
    print("define 0")
    get_temp_pos()
    get_wanted_pos()
    global steps_to_move
    steps_to_move = wanted_pos
    global current_pos
    current_pos = wanted_pos
    global last_pos
    last_pos = 0  # 初始位置设为0
    global last_dir
    last_dir = off
    dir_pin.off()
    move_motor(steps_to_move)

5. 浮点数精度导致的判断误差

wanted_pos是浮点数,current_pos随步数累计会出现精度偏差,直接用==判断相等会失效,需用差值阈值判断。
修复get_steps_to_move:

def get_steps_to_move(wanted_pos, current_pos):
    print("get steps to move")
    diff = abs(wanted_pos - current_pos)
    if diff < 0.5:  # 差值小于半步则不移动
        global steps_to_move
        steps_to_move = 0
        print(steps_to_move)
    elif wanted_pos > current_pos:
        steps_to_move = round(wanted_pos - current_pos)
        print(steps_to_move)
    else:
        steps_to_move = round(current_pos - wanted_pos)
        print(steps_to_move)
        print("2")

内容的提问来源于stack exchange,提问作者Austin Hefley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 13:57:04