黄工无刷电机学习
直播中

马占云

7年用户 1537经验值
私信 关注
[问答]

如何通过CN3口直接控制台达伺服电机A2-M?

如何通过CN3口直接控制台达伺服电机A2-M?

回帖(1)

闫康

2021-10-8 11:23:56
最近太忙,一直没时间更新,使用Python和tkinter简单写了一个通过速度模式进行寸动控制的程序,另外外接了一个20倍的减速器,虽然将就可用,但是精度只能控制为0.3°的倍数,没有达到我理想中的1°控制
简单界面如下:

Python的源码如下:(python使用的版本为3.8.3 pyinstaller版本为4.0 )

import tkinter as tk
from tkinter import ttk
from tkinter import *
from tkinter import messagebox
import threading
import os
import datetime
import serial
import time
import serial.tools.list_ports
import crcmod.predefined


# CRC16校验 入参为校验数据(16进制字符串) 返回带校验码的数据
def mk_crc_16(data):
    crc16_func = crcmod.predefined.mkCrcFun('modbus')
    crc8_func_value = crc16_func(bytes().fromhex(data))
    CRC_16_result = hex(crc8_func_value)
    # 去掉0x 并且对校验结果补位
    CRC_16_result = CRC_16_result[2:]
    CRC_16_result = CRC_16_result.***ill(4)
    # 高低位颠倒
    final_data = data + CRC_16_result[2:] + CRC_16_result[0:2]
    return final_data
   
# 线程函数,用于开启独立线程后台执行,不影响界面刷新
def thread_another(func, *args):


    # 创建
    t = threading.Thread(target=func, args=args)
    # 守护  随主进程消亡
    t.setDaemon(True)
    # 启动
    t.start()


#
def send_485_cmd(cmd):


    ser = serial.Serial('COM21', 38400, bytesize=8, parity='E', stopbits=1)  # 选择串口,并设置波特率
    if ser.is_open:
        print("打开串口成功")


        # 获取协议数据的CRC16校验码
        agreement_add_crc = mk_crc_16(cmd)
        print(agreement_add_crc)


        # hex(16进制)转换为bytes(2进制)
        send_data = bytes.fromhex(agreement_add_crc)  # 发送数据转换为b'xffx01x00Ux00x00V'
        ser.write(send_data)  # 发送命令
        time.sleep(0.1)  # 延时,否则len_return_data将返回0,此处易忽视!!!


        len_return_data = ser.inWaiting()  # 获取缓冲数据(接收数据)长度
        if len_return_data:
            return_data = ser.read(len_return_data)  # 读取缓冲数据
            str_return_data = str(return_data.hex())
            print(str_return_data)
            print(agreement_add_crc)
            # 判断设置成功与否
            if str_return_data == agreement_add_crc:
                print("设置成功")
                # messagebox.showinfo(title='提示信息', message='设置成功')
            else:
                print("设置失败")
                # messagebox.showinfo(title='提示信息', message='设置失败')


    ser.close()


# 关闭窗口回调函数
def on_closing():
    if messagebox.askokcancel("退出", "   是否确定关闭程序?"):
        window.destroy()


# 电机servo ON
def motor_servo_on():
    print("电机启动")
    # 设置P2-10 为 1
    send_485_cmd('010602140001')
        
# 电机servo OFF
def motor_servo_off():
    print("电机停止")
    # 设置P2-10 为 101
    send_485_cmd('010602140101')   


# 电机寸动(JOG)控制 顺时针
def motor_ccw():
    print("电机顺时针转")
    # 设置P4-05地址 040A 040B  十进制为4998
    send_485_cmd('0106040a1386')


# 电机寸动(JOG)控制 逆时针
def motor_cw():
    print("电机逆时针转")
    # 设置P4-05地址 040A 040B  十进制为4999
    send_485_cmd('0106040a1387')


# 电机寸动(JOG)控制 停止运转
def motor_stop():
    print("电机停止运转")
    # 设置P4-05地址 040A 040B  十进制为0
    send_485_cmd('0106040a0000')


def motor_speed_set():
    print("电机速度设置")
    # 设置P4-05地址 040A 040B  十进制范围:1~5000
    # 获取设置的值
    speedVar = speed_entry.get()
    toHexStr = hex(int(speedVar))[2:]
    print(toHexStr)
    # 补位 补0
    if len(toHexStr) < 4:
        toHexStr = toHexStr.***ill(4)
    print(toHexStr)
    # 组帧
    speedCMD = '0106040a' + toHexStr
    print(speedCMD)
    send_485_cmd(speedCMD)


window = tk.Tk()
# 设置窗口大小
winWidth = 515
winHeight = 295
# 获取屏幕分辨率
screenWidth = window.winfo_screenwidth()
screenHeight = window.winfo_screenheight()


x = int((screenWidth - winWidth) / 2)
y = int((screenHeight - winHeight) / 2)


# 设置主窗口标题
window.title("台达A2-M 485控制")
# 设置窗口初始位置在屏幕居中
window.geometry("%sx%s+%s+%s" % (winWidth, winHeight, x, y))
# 设置窗口图标
# 获取当前路径下的CAN动态库路径
ico_realPath = os.path.join(os.path.dirname(os.path.realpath(__file__)), '123.ico')
window.iconbitmap(ico_realPath)
# 设置窗口宽高固定
window.resizable(0, 0)


# 电机 servo on
Button1 = Button(window, text='电机servo ON', borderwidth=2, relief="groove", width=14, height=1, font=('Microsoft YaHei', 13), fg='white', bg='Purple', command=lambda :thread_another(motor_servo_on))
Button1.grid(row=0, column=0, columnspan=2, rowspan=1, padx = 10, pady = 10)


# 电机 servo off
Button2 = Button(window, text='电机servo OFF', borderwidth=2, relief="groove", width=14, height=1, font=('Microsoft YaHei', 13), fg='white', bg='Purple', command=lambda :thread_another(motor_servo_off))
Button2.grid(row=0, column=2, columnspan=2, rowspan=1, padx = 10, pady = 10)


# 电机寸动 逆时针
Button3 = Button(window, text='寸动(顺时针)', borderwidth=2, relief="groove", width=14, height=1, font=('Microsoft YaHei', 13), fg='white', bg='Purple', command=lambda :thread_another(motor_ccw))
Button3.grid(row=1, column=0, columnspan=2, rowspan=1, padx = 10, pady = 10)


# 电机寸动 顺时针
Button4 = Button(window, text='寸动(逆时针)', borderwidth=2, relief="groove", width=14, height=1, font=('Microsoft YaHei', 13), fg='white', bg='Purple', command=lambda :thread_another(motor_cw))
Button4.grid(row=1, column=2, columnspan=2, rowspan=1, padx = 10, pady = 10)


# 电机停止运转
Button5 = Button(window, text='停止运转', borderwidth=2, relief="groove", width=14, height=1, font=('Microsoft YaHei', 13), fg='white', bg='Purple', command=lambda :thread_another(motor_stop))
Button5.grid(row=1, column=4, columnspan=2, rowspan=1, padx = 10, pady = 10)


# 寸动速度 标签
speed_label = Label(window, text='寸动速度(r/min):', width=14, height=1, font=('Microsoft YaHei', 13), fg='blue')
speed_label.grid(row=2, column=0, columnspan=2, rowspan=1, padx = 10, pady = 10)


# 寸动速度 输入框
speed_num = StringVar()
speed_entry = Entry(window, textvariable = speed_num, width=14, font=('Microsoft YaHei', 13), fg='blue')
speed_entry.grid(row=2, column=2, columnspan=2, rowspan=1, padx = 10, pady = 10)


# 寸动速度 设置按钮
Button6 = Button(window, text='速度设置', borderwidth=2, relief="groove", width=14, height=1, font=('Microsoft YaHei', 13), fg='white', bg='Purple', command=lambda :thread_another(motor_speed_set))
Button6.grid(row=2, column=4, columnspan=2, rowspan=1, padx = 10, pady = 10)


#window.protocol("WM_DELETE_WINDOW", on_closing)
window.mainloop()

举报

更多回帖

发帖
×
20
完善资料,
赚取积分