天天看點

序列槽總線舵機之配置舵機一、配置舵機代碼二、測試

在我們使用舵機的過程中,我們需要先對舵機進行配置,設定一下必要的參數,還要設定ID

文章目錄

  • 一、配置舵機代碼
  • 二、測試
    • 1.硬體連接配接
    • 2.測試

這部分在config_serial_servo檔案裡

一、配置舵機代碼

# 配置序列槽舵機
#!/usr/bin/python3
# encoding: utf-8
# 配置序列槽舵機的參數
# 每次隻能配置一個舵機,且樹莓派擴充闆隻能連接配接一個舵機,既是一個舵機一個舵機配置參數
import sys
if sys.version_info.major == 2:
    print('Please run this program with python3!')  # 請運作在python3的環境下
    sys.exit(0)  # 結束程式
    
from SerialServoCmd import *  # 導入序列槽舵機指令庫

# 序列槽舵機設定ID
# oldid 原來的ID  newid 要設定的新的ID
def serial_servo_set_id(oldid, newid): 
    serial_serro_wirte_cmd(oldid, LOBOT_SERVO_ID_WRITE, newid) # 寫入舵機id

# 序列槽舵機讀ID
# id 如果不傳參,預設廣播 此時隻能有一個舵機連接配接,否則會亂碼 
def serial_servo_read_id(id=None):
    while True:
        if id is None:  # 如果這個id是空的
        #0xfe 為舵機的廣播位址,總線上智能接一個舵機,不然都會傳回資料造成總線沖突
            serial_servo_read_cmd(0xfe, LOBOT_SERVO_ID_READ)
        else:
            serial_servo_read_cmd(id, LOBOT_SERVO_ID_READ)  # 讀取舵機的ID
        # 擷取内容
        msg = serial_servo_get_rmsg(LOBOT_SERVO_ID_READ)  # 如果資訊不是空
        if msg is not None: # 傳回資訊
            return msg 

# 序列槽舵機停止
# id: 要停止的舵機
def serial_servo_stop(id=None):
    serial_serro_wirte_cmd(id, LOBOT_SERVO_MOVE_STOP) # 發送指令舵機停止運作

# 配置偏差 掉電保護
# id:舵機id  d :偏差
def serial_servo_set_deviation(id, d=0):
    # 設定偏差  掉電不保護
    serial_serro_wirte_cmd(id, LOBOT_SERVO_ANGLE_OFFSET_ADJUST, d)  # 角度偏差調整
    # 設定為掉電保護
    serial_serro_wirte_cmd(id, LOBOT_SERVO_ANGLE_OFFSET_WRITE)  # 角度偏差寫

# 序列槽舵機讀取偏內插補點 範圍-125--125  對應角度-30度--30度
# id:要讀取的舵機ID
def serial_servo_read_deviation(id):
    # 發送讀取偏差指令
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_ANGLE_OFFSET_READ) # 讀取偏內插補點
        # 擷取資料
        msg = serial_servo_get_rmsg(LOBOT_SERVO_ANGLE_OFFSET_READ)  # 傳回偏內插補點的資訊
        if msg is not None: # 消息不為空
            return msg # 傳回消息(偏內插補點)
# 設定序列槽舵機轉動範圍
# id: 要設定的舵機  low: 最小角度的範圍0-1000 high:最大角度範圍0-1000
def serial_servo_set_angle_limit(id, low, high):
    serial_serro_wirte_cmd(id, LOBOT_SERVO_ANGLE_LIMIT_WRITE, low, high)  # 寫入角度的轉動範圍
#讀取舵機轉動範圍
# id: 要讀取的舵機
def serial_servo_read_angle_limit(id):
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_ANGLE_LIMIT_READ) # 讀取角度範圍指令
        msg = serial_servo_get_rmsg(LOBOT_SERVO_ANGLE_LIMIT_READ) # 讀取資料
        if msg is not None: # 消息不為空
            return msg  # 傳回舵機的轉動範圍
# 設定序列槽舵機的電壓值範圍 4500-12000mv  4.5V-12V
def serial_servo_set_vin_limit(id, low, high):
    serial_serro_wirte_cmd(id, LOBOT_SERVO_VIN_LIMIT_WRITE, low, high)
# 讀取序列槽舵機的電壓值範圍
def serial_servo_read_vin_limit(id):
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_VIN_LIMIT_READ) # 讀舵機電壓值
        msg = serial_servo_get_rmsg(LOBOT_SERVO_VIN_LIMIT_READ)
        if msg is not None:  # 消息不為空
            return msg
# 設定舵機最高溫度限制 範圍50-100度 預設值85度
def serial_servo_set_max_temp(id, m_temp):
    serial_serro_wirte_cmd(id, LOBOT_SERVO_TEMP_MAX_LIMIT_WRITE, m_temp) # 舵機最高溫度指令
# 讀取舵機最高溫度限制
def serial_servo_read_temp_limit(id):
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_TEMP_MAX_LIMIT_READ) # 讀舵機最高溫度指令
        msg = serial_servo_get_rmsg(LOBOT_SERVO_TEMP_MAX_LIMIT_READ) # 讀資料
        if msg is not None:
            return msg
# 讀取舵機目前的實際角度位置值  
def serial_servo_read_pos(id):
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_POS_READ) # 讀目前位置指令
        msg = serial_servo_get_rmsg(LOBOT_SERVO_POS_READ)  # 讀資料
        if msg is not None:  # 消息不為空
            return msg
#讀取舵機内部實時溫度
def serial_servo_read_temp(id):
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_TEMP_READ) # # 讀舵機溫度指令
        msg = serial_servo_get_rmsg(LOBOT_SERVO_TEMP_READ) #讀資料
        if msg is not None:  #消息不為空
            return msg
# 讀取舵機内部目前輸入電壓值
def serial_servo_read_vin(id):
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_VIN_READ) # 讀電壓指令
        msg = serial_servo_get_rmsg(LOBOT_SERVO_VIN_READ) #讀資料
        if msg is not None: #消息不為空
            return msg
# 把舵機複位到中位
def serial_servo_rest_pos(oldid):
    # 舵機清零偏差和P值中位(500)
    serial_servo_set_deviation(oldid, 0)    # 清零偏差
    time.sleep(0.1)
    serial_serro_wirte_cmd(oldid, LOBOT_SERVO_MOVE_TIME_WRITE, 500, 100) # 設定舵機角度為500,移動時間為100ms

# 顯示舵機目前的狀态
# id:要顯示的舵機  預設廣播, 
def show_servo_state(id = None):
    oldid = serial_servo_read_id(id) #讀出舵機的id
    portRest() # 端口複位
    if oldid is not None: # 如果ID是不是空的
        print('目前的舵機ID是:%d' % oldid)
        pos = serial_servo_read_pos(oldid) # 讀出舵機的位置
        print('目前的舵機角度:%d' % pos)
        portRest()

        now_temp = serial_servo_read_temp(oldid) # 現在舵機的溫度
        print('目前的舵機溫度:%d°' % now_temp)
        portRest()

        now_vin = serial_servo_read_vin(oldid) #讀電壓值
        print('目前的舵機電壓:%dmv' % now_vin)
        portRest()

        d = serial_servo_read_deviation(oldid) #讀偏內插補點
        print('目前的舵機偏差:%d' % ctypes.c_int8(d).value) 
        portRest()

        limit = serial_servo_read_angle_limit(oldid) #讀轉動角度範圍
        print('目前的舵機可控角度為%d-%d' % (limit[0], limit[1]))
        portRest()

        vin = serial_servo_read_vin_limit(oldid) #讀電壓值範圍
        print('目前的舵機報警電壓為%dmv-%dmv' % (vin[0], vin[1]))
        portRest()

        temp = serial_servo_read_temp_limit(oldid) #讀溫度範圍
        print('目前的舵機報警溫度為50°-%d°' % temp)
        portRest()

    return oldid # 傳回舵機的id

# 如果是單獨執行這個程式的話
if __name__ == '__main__':
    portInit()  # 端口複位
    oldid = show_servo_state() # 列印舵機的資訊
    while True:
        print ('*' * 50)  # 列印50個*字元
        print ('1、設定舵機ID号')
        print ('2、設定舵機偏差')
        print ('3、設定舵機轉動角度範圍')
        print ('4、設定舵機電壓報警範圍')
        print ('5、設定舵機溫度報警範圍')
        print ('6、顯示舵機狀态')
        print ('7、中位舵機')
        print ('8、退出')
        print ('*' * 50)
        num = int(input('請輸入需要配置的數字')) # 輸入一個int型數字
        num6_flag = 0
        while 1 <= num <= 7: # 這個數字在1-7範圍内
            if num == 1:
                num6_flag = 0
                n_id = int(input('請輸入新的舵機ID号(範圍:0-253)')) # 輸入新舵機ID
                if n_id > 253:
                    print ('超過範圍,請重新輸入')
                else:
                    serial_servo_set_id(oldid, n_id) # 設定新舵機id
                    portRest()
                    if serial_servo_read_id() == n_id: # 讀取舵機的ID
                        # 設定不成功的話繼續設定
                        oldid = n_id # 設定成功
                        print ('設定成功')
                        break
            elif num == 2:
                num6_flag = 0
                n_d = int(input('請輸入舵機偏內插補點(範圍:-125 ~ 125)'))  # 輸入舵機的偏內插補點
                if n_d < -125 or n_d > 125: # 超出範圍
                    print ('超過範圍,請重新輸入')
                else:
                    serial_servo_set_deviation(oldid, n_d) # 設定舵機的偏內插補點
                    time.sleep(0.1)
                    portRest()
                    zf_d = serial_servo_read_deviation(oldid) # 讀舵機的偏內插補點
                    if zf_d > 127:  # 負數 最高位是1
                        zf_d = -(0xff - (zf_d - 1)) # 轉換為正值
                    if zf_d == n_d:
                        print ('設定成功')
                        break # 跳出循環
            elif num == 3:
                num6_flag = 0
                print ('請輸入舵機的轉動範圍(0 ~ 1000)')
                low_ang_limit = int(input('請輸入低範圍值'))
                high_ang_limit = int(input('請輸入高範圍值'))
                # 還需要判斷low_ang_limit >high_ang_limit的情況
                if low_ang_limit < 0 or high_ang_limit < 0 or low_ang_limit >= 1000 or high_ang_limit > 1000:
                    print ('超過範圍,請重新輸入')
                else:
                    serial_servo_set_angle_limit(oldid, low_ang_limit, high_ang_limit) 
                    portRest()
                    lim = serial_servo_read_angle_limit(oldid) # 讀取舵機的角度範圍
                    if lim[0] == low_ang_limit and lim[1] == high_ang_limit:
                        print ('設定成功')
                        break # 跳出循環
            elif num == 4:
                num6_flag = 0
                print ('請輸入舵機的電壓報警範圍(4500 ~ 12000)mv')
                low_vin_limit = int(input('請輸入低範圍值'))
                high_vin_limit = int(input('請輸入高範圍值'))
                # 還需要判斷low_vin_limit > high_vin_limit的情況
                if low_vin_limit < 4500 or high_vin_limit < 4500 or low_vin_limit >= 12000 or high_vin_limit > 12000:
                    print ('超過範圍,請重新輸入')
                else:
                    serial_servo_set_vin_limit(oldid, low_vin_limit, high_vin_limit)
                    portRest()
                    vin = serial_servo_read_vin_limit(oldid) # 讀電壓值範圍
                    if vin[0] == low_vin_limit and vin[1] == high_vin_limit:
                        print ('設定成功')
                        break
            elif num == 5:
                num6_flag = 0
                n_temp = int(input('請輸入舵機的溫度報警範圍(範圍:50-100)度'))
                if n_temp > 100 or n_temp < 50:
                    print ('超過範圍,請重新輸入')
                else:
                    serial_servo_set_max_temp(oldid, n_temp) # 設定舵機的溫度報警上限
                    portRest()
                    if serial_servo_read_temp_limit(oldid) == n_temp:
                        # 不成功繼續
                        print ('設定成功')
                        break
            elif num == 6: # 顯示舵機狀态
                if num6_flag == 0:
                    oldid = show_servo_state() # 顯示舵機的狀态
                    num6_flag = 1
                break # 跳出循環    
            elif num == 7: # 中位舵機
                num6_flag = 0
                serial_servo_rest_pos(oldid) # 設定舵機到中位
                print ('中位成功')
                break # 跳出循環
        # 沒有進入循環
        if num == 8:
            break # 跳出大循環 退出程式
        elif num < 1 or num > 8: # 不在菜單範圍内
            print ('輸入有誤,請重新輸入')




           

二、測試

1.硬體連接配接

我連接配接的是6号舵機

序列槽總線舵機之配置舵機一、配置舵機代碼二、測試

2.測試

序列槽總線舵機之配置舵機一、配置舵機代碼二、測試

輸入對應的編号就可以配置對應的資訊