chakokuのブログ(rev4)

テック・コミック・DTM・・・ごくまれにチャリ

MicroPythonからHuskyLensを制御する(UART接続)

目的:マイコンとHuskyLensをUARTで接続してAPIが正常に動作するか確認する
結論:機能を効果的に使い分けているか自信がないが、TAG認識情報は取得できた
詳細:
先人がやり倒しているが、理解のためにHuskyLensのAPIを呼び出してみる。
以下のコードで、TAGのXY座標、Width/Heightが取れるところまでは確認した
HuskyLensとマイコン(ESP32-C3)はUARTで接続しており、ESP32-C3とPCはUSB/Serialで接続
メカコン?専用設計の?TAGだけあって、TAG認識は安定して動作する。
次は、LEGO SPIKE上でMicroPythonを走らせて、LEGOのHUBからHuskyLensを制御する


# 
#
#

import machine
import time

KNOCK = bytes((0x55,0xAA,0x11,0x00,0x2C,0x3C))
CMD_REQ = bytes((0x55, 0xAA, 0x11, 0x00, 0x20, 0x30))
CMD_REQ_BLOCKS = bytes((0x55, 0xAA, 0x11, 0x00, 0x21, 0x31))


COMMAND_POS=4
COMMAND_RETURN_INFO = 0x29
COMMAND_RETURN_BLOCK = 0x2A
COMMAND_RETURN_ARROW = 0x2B

def parse_return_info(data):
    command = data[COMMAND_POS]
    if command == 0x29:
        show_return_info(data[5:])
    elif command == 0x2A:
        show_return_block(data[5:])
    elif command == 0x2B:
        show_return_arrow(data[5:])

def show_return_block(data):
    x_center = ( data[1] << 8 ) + data[0]
    y_center = ( data[3] << 8 ) + data[2]
    width = ( data[5] << 8 ) + data[4]
    height = ( data[7] << 8 ) + data[6]
    id = ( data[9] << 8 ) + data[8]
    print('show return block',end=' ')
    print(id, x_center, y_center, width, height)

def show_return_arrow(data):
    x_origin = ( data[1] << 8 ) + data[0]
    y_origin = ( data[3] << 8 ) + data[2]
    x_target = ( data[5] << 8 ) + data[4]
    y_target = ( data[7] << 8 ) + data[6]
    id = ( data[9] << 8 ) + data[8]
    print('show return arrow',end=' ')
    print(id, x_origin, y_origin, x_target, y_target)

def show_return_info(data):
    n_of_blk_arw = (data[1] << 8 ) + data[0]
    n_of_id = (data[3] << 8 ) + data[2]
    fr_no = (data[5] << 8 ) + data[4]
    print('show return info',end=' ')
    print(n_of_blk_arw, n_of_id, hex(fr_no))

uart1 = machine.UART(1)
uart1.init(baudrate=9600, bits=8, parity=None, stop=1, tx=21, rx=20)

uart1.write(KNOCK)
time.sleep(0.1)
data = uart1.read()

#
# read loop (CMMAND REQUEST BLOCK)
#
while True:
    uart1.write(CMD_REQ_BLOCKS)
    time.sleep(0.1)
    if uart1.any() > 0:
        data = uart1.read()
        #print([hex(x) for x in data])
        parse_return_info(data)
        if len(data) > 16:
            parse_return_info(data[16:])
        if len(data) > 32:
            parse_return_info(data[32:])

#
# read loop (CMMAND REQUEST)
#
while True:
    uart1.write(CMD_REQ)
    time.sleep(0.1)
    if uart1.any() > 0:
        data = uart1.read()
        #print([hex(x) for x in data])
        parse_return_info(data)
        if len(data) > 16:
            parse_return_info(data[16:])
        if len(data) > 32:
            parse_return_info(data[32:])

■追記
Huskylens Driver (V0.1)

# 
#
#

import machine
import time

CMD_REQ_KNOCK = bytes((0x55,0xAA,0x11,0x00,0x2C,0x3C))
CMD_REQ_BLKS_ARWS = bytes((0x55, 0xAA, 0x11, 0x00, 0x20, 0x30))
CMD_REQ_BLOCKS = bytes((0x55, 0xAA, 0x11, 0x00, 0x21, 0x31))
CMD_REQ_ARROWS = bytes((0x55, 0xAA, 0x11, 0x00, 0x22, 0x32))

COMMAND_POS=4
COMMAND_RETURN_INFO = 0x29
COMMAND_RETURN_BLOCK = 0x2A
COMMAND_RETURN_ARROW = 0x2B

def parse_return_data(data):
    command = data[COMMAND_POS]
    if command == 0x29:
        return parse_return_info(data[5:])
    elif command == 0x2A:
        return parse_return_block(data[5:])
    elif command == 0x2B:
        return parse_return_arrow(data[5:])

def parse_return_block(data):
    x_center = ( data[1] << 8 ) + data[0]
    y_center = ( data[3] << 8 ) + data[2]
    width = ( data[5] << 8 ) + data[4]
    height = ( data[7] << 8 ) + data[6]
    id = ( data[9] << 8 ) + data[8]
    return ('block', id, x_center, y_center, width, height)

def parse_return_arrow(data):
    x_origin = ( data[1] << 8 ) + data[0]
    y_origin = ( data[3] << 8 ) + data[2]
    x_target = ( data[5] << 8 ) + data[4]
    y_target = ( data[7] << 8 ) + data[6]
    id = ( data[9] << 8 ) + data[8]
    return ('arrow', id, x_origin, y_origin, x_target, y_target)

def parse_return_info(data):
    n_of_blk_arw = (data[1] << 8 ) + data[0]
    n_of_id = (data[3] << 8 ) + data[2]
    fr_no = (data[5] << 8 ) + data[4]
    return('info', n_of_blk_arw, n_of_id, hex(fr_no))

def send_CMD_REQ_KNOCK(uart):
    uart.write(CMD_REQ_KNOCK)

def send_CMD_REQ_BLOCKS(uart):
    uart.write(CMD_REQ_BLOCKS)

def send_CMD_REQ_ARROWS(uart):
    uart.write(CMD_REQ_ARROWS)

def send_CMD_REQ_ALGO(uart, type):
    cmd_pre_part = (0x55, 0xAA, 0x11, 0x02, 0x2D)
    if type == 'FACE_RECOG':
        algo_defs = (0x00,0x0)
    elif type == 'OBJ_TRACK':
        algo_defs = (0x01,0x00)
    elif type == 'OBJ_RECOG':
        algo_defs = (0x02,0x00)
    elif type == 'LINE_TRACK':
        algo_defs = (0x03,0x00)
    elif type == 'COLOR_RECOG':
        algo_defs = (0x04,0x00)
    elif type == 'TAG_RECOG':
        algo_defs = (0x05,0x00)
    elif type == 'OBJ_CLSSIFY':
        algo_defs = (0x06,0x00)

    cmd = cmd_pre_part + algo_defs
    parity = sum(cmd) & 0xff
    cmd = cmd + (parity,)
    uart.write(bytes(cmd))


uart1 = machine.UART(1)
uart1.init(baudrate=9600, bits=8, parity=None, stop=1, tx=21, rx=20)


send_CMD_REQ_KNOCK(uart1)
time.sleep(0.1)
data = uart1.read()
print(data)


# Set Color Recognition
send_CMD_REQ_ALGO(uart, 'COLOR_RECOG')

#
# read loop (CMMAND REQUEST BLOCKS)
#
while True:
    send_CMD_REQ_BLOCKS(uart1)
    time.sleep(0.1)
    if uart1.any() > 0:
        data = uart1.read()
        #print([hex(x) for x in data])
        info = parse_return_data(data)
        print(info)
        if len(data) > 16:
            info=parse_return_data(data[16:])
            print(info)
        if len(data) > 32:
            info=parse_return_data(data[32:])
            print(info)

■追記(2024/12/14)

評価中のHuskyLensの情報と試作ドライバは以下のGithubで公開しています。不明な点等ありましたらお問い合わせください。
GitHub - TomoniCodeAcademy/AI-Camera: AI Cameraに関する情報やライブラリ類をまとめる


■参考URL
HUSKYLENSArduino/HUSKYLENS Protocol.md at master · HuskyLens/HUSKYLENSArduino · GitHub