这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【静音步进电机控制实践过程帖】网页上位机设计

共2条 1/1 1 跳转至

【静音步进电机控制实践过程帖】网页上位机设计

工程师
2026-05-12 13:13:49     打赏

【静音步进电机控制实践过程帖】网页上位机设计

本文介绍了 TMC2209 步进电机驱动板结合树莓派Pico实现串口控制,进一步设计Web网页上位机实现步进电机的可视化UI界面控制的项目设计,包括硬件连接、串口指令控制、网页上位机设计等。

项目介绍

  • 硬件连接:TMC2209 模块、扩展板、树莓派Pico扩展板、OLED、系统接线示意图、实物图;

  • 工程测试:MicoPython 编程,实现串口 JSON 指令控制步进电机旋转方向、角度和速度;

  • 网页设计:Web 界面及功能模块设计,连接串口并发送 JSON 消息,实现步进电机的转速和角度控制。


硬件连接

包括 TMC2209、OLED、步进电机、树莓派Pico的接线方式。

TMC2209

TMC2209 模块与树莓派 Pico 的接线方式如下


TMC2209RPi PicoNote
DirGP 16Direction
StepGP 17Step pulse
ENGP 18Enable
GNDGNDGround
VIO3V3Power


TMC2209 与步进电机的接线方式与相序判断方法详见:【静音步进电机控制实践过程帖】树莓派Pico扩展板设计 .


UART


USB-TTLRPi PicoNote
TXDGP1 (RX)Transmite
RXDGP0 (TX)Receive
GNDGNDGround


系统连接

connection_diagram.jpg

实物连接效果如下

web_uart_stepper_connect.jpg

OLED 连接详见:【静音步进电机控制实践过程帖】树莓派Pico扩展板设计 .

流程图

flowchart_uart_stepper_json.jpg

工程代码

运行 Thonny IDE 新建文件,添加如下代码

 '''
 电机:42步进电机
 电压:直流12V
 步距角:1.8度
 细分:8
 '''
 from machine import Pin, I2C, UART
 import ssd1306
 import time
 import ujson
 
 # ==== Define hardware pinout =====
 dir_pin = Pin(16, Pin.OUT)
 step_pin = Pin(17, Pin.OUT)
 en_pin = Pin(18, Pin.OUT)
 
 # Initialize OLED I2C
 i2c = I2C(0, scl=Pin(5), sda=Pin(4))
 oled = ssd1306.SSD1306_I2C(128, 64, i2c)
 
 # Initialize UART 
 uart = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1))
 
 # ======== Angle Calculation ==========
 step_angle = 1.8 # 步距角
 step_cycle = 360 / 1.8 # 360 / 1.8 = 200 步/圈
 # microstep mode, default is 1/8 so 8
 # another ex: 1/16 microstep would be 16
 microMode = 8
 # full rotation multiplied by the microstep divider
 steps = step_cycle * microMode  # 200 * 8细分 = 1600 脉冲/圈
 # n 脉冲/度
 STEPS_PER_DEGREE = steps / 360
 
 # ======== OLED Display ===========
 def display_motor(status="READY", angle=0.0, speed=1200, dir_str="STOP"):
     oled.fill(0)
     oled.text("==== MOTOR ====", 0, 0)
     oled.text(f"Status: {status}", 0, 15)
     oled.text(f"Angle: {angle:.1f} deg", 0, 27)
     oled.text(f"Direction: {dir_str}", 0, 39)
     oled.text(f"Speed: {speed}us", 0, 51)
     oled.show()
 
 # ======= Motor Control =========
 def rotate_angle(angle, speed_us):
     en_pin.value(0)
     dir_pin.value(angle > 0)   # Rotate direction
     dir_str = "CW" if angle > 0 else "CCW"
     
     display_motor("RUN", angle, speed_us, dir_str)  # rotate direction display
     target_angle = abs(angle)
     total_steps = int(target_angle * STEPS_PER_DEGREE)  # rotate steps
     
     # Start rotate
     for _ in range(total_steps):
         step_pin.value(1)
         time.sleep_us(speed_us)
         step_pin.value(0)
         time.sleep_us(speed_us)
     print("Rotate %.1f degree i.e. %d steps" % (angle, total_steps))
     release()
     display_motor("STOP", angle, speed_us, dir_str)
 
 def release():
     en_pin.value(1)
 
 # ======== UART Control =========
 def uart_control():
     while True:
         if uart.any():
             cmd = uart.read()
             try:
                 data = ujson.loads(cmd)
                 angle = float(data['angle'])
                 speed = int(data.get('speed', 1200))
                 
                 rotate_angle(angle, speed)
                 uart.write('OK\r\n')
                 
             except:
                 uart.write('Invalid command\r\n')
                 release()
         else:
             release()
             time.sleep_ms(50)
 
 # ======== main ==========
 display_motor()
 while True:
     uart_control()

保存代码。

串口指令

  • Thonny IDE 运行 stepper_uart_control.py 程序;

  • 打开串口调试助手软件,发送 JSON 格式的旋转方向、角度和速度指令 {"angle": 90, "speed": 1500} ;

  • uart_stepper_control_json.jpg

  • 通过角度数值的正负控制旋转方向;

  • 步进电机按照串口 JSON 指令,以目标速度旋转目标角度。


网页设计


网页设计包括串口配置、发送测试、运行测试、运行日志等模块。

上位机代码


 <!DOCTYPE html>
 <html>
 <head>
     <meta charset="UTF-8">
     <title>步进电机 Web Serial 控制器</title>
     <style>
         * {box-sizing: border-box; font-family: Arial, sans-serif;}
         body {max-width: 480px; margin: 20px auto; padding: 0 15px; background: #f5f5f5;}
         .card {background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); margin-bottom: 15px;}
         h2 {text-align: center; color: #333; margin-top: 0;}
         .group {margin: 12px 0;}
         label {display: block; margin-bottom: 6px; font-weight: bold; color: #555;}
         input {width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 6px; font-size: 16px;}
         button {width: 100%; padding: 12px; border: none; border-radius: 6px; font-size: 16px; color: white; margin: 5px 0; cursor: pointer;}
         .btn-connect {background: #007bff;}
         .btn-send {background: #28a745;}
         .btn-stop {background: #dc3545;}
         .log {background: #1e1e1e; color: #dcdcaa; padding: 10px; height: 160px; border-radius: 6px; overflow-y: auto; font-size: 14px; line-height: 1.4;}
     </style>
 </head>
 <body>
 <div>
     <h2>步进电机控制器</h2>
     <div>
         <label>旋转角度(正数=CW,负数=CCW)</label>
         <input type="number" id="angle" value="180" step="0.1">
     </div>
     <div>
         <label>速度(单位:us,越小越快)</label>
         <input type="number" id="speed" value="1000" min="200" max="5000">
     </div>
     <button id="connect">连接串口</button>
     <button id="send">发送指令</button>
     <div id="log"></div>
 </div>
 
 <script>
     let port;
     let reader;
     let logBox = document.getElementById('log');
 
     function log(msg) {
         logBox.innerHTML += msg + '<br>';
         logBox.scrollTop = logBox.scrollHeight;
     }
 
     document.getElementById('connect').addEventListener('click', async () => {
         try {
             port = await navigator.serial.requestPort();
             await port.open({ baudRate: 115200 });
             log('✅ 串口已连接 (115200)');
             
             reader = port.readable.getReader();
             readLoop();
         } catch (e) {
             log('连接失败:' + e.message);
         }
     });
 
     async function readLoop() {
         while (true) {
             try {
                 const { value, done } = await reader.read();
                 if (done) break;
                 let decoder = new TextDecoder();
                 let data = decoder.decode(value);
                 log('← ' + data.trim());
             } catch (e) {
                 log('读取失败');
                 break;
             }
         }
     }
 
     document.getElementById('send').addEventListener('click', async () => {
         if (!port) {
             log('请先连接串口');
             return;
         }
         let angle = parseFloat(document.getElementById('angle').value);
         let speed = parseInt(document.getElementById('speed').value);
         let cmd = JSON.stringify({ angle, speed });
         
         const encoder = new TextEncoder();
         const writer = port.writable.getWriter();
         await writer.write(encoder.encode(cmd));
         writer.releaseLock();
         
         log('→ ' + cmd);
     });
 </script>
 </body>
 </html>


保存代码。

控制方案

  • 双击打开网页,或使用浏览器加载 HTML 文件;

  • 点击连接串口按钮,选择目标串口并连接;

  • 设置目标旋转角度、速度;

  • 点击发送指令按钮,步进电机转动,完成后反馈 OK 字样;

web_uart_control.jpg


动态演示

  • Web 网页上位机运行后,步进电机按照设定的角度和速度旋转;

web_uart_stepper_run.gif

总结

本文介绍了 TMC2209 步进电机驱动板结合树莓派Pico实现串口控制,进一步设计Web网页上位机实现步进电机的可视化UI界面控制的项目设计,包括硬件连接、串口指令控制、网页上位机设计等,为相关产品的快速开发和应用设计提供了参考。





关键词: 步进电机     uart     python     web     json    

院士
2026-05-12 15:53:23     打赏
2楼

谢谢分享,学习学习。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]