[其他ST产品]

手把手移植 simpleFOC

[复制链接]
1679|9
手机看帖
扫描二维码
随时随地手机跟帖
狗啃模拟|  楼主 | 2024-3-30 16:41 | 显示全部楼层 |阅读模式
一版为SimpleFOCShield(单路):stm32f103cb+L6234D

另一版为SimpleFOC-PowerShield(双路):stm32f405G+btn8982。

上图:


501816607cffd0104d.png
SimpleFOCShield版


989376607d02a62f51.png

SimpleFOC-PowerShield版




使用特权

评论回复
狗啃模拟|  楼主 | 2024-3-30 16:41 | 显示全部楼层
移植目标
将Arduino里的 simpleFoc移植到gcc下,驱动层用STM32CubeMX生成,并且以arduino里应用层框架进行调试。既然用STM32CubeMX生成驱动,那么就要了解arduino里相应stm32f1x驱动细节,驱动逻辑上先保持原汁原味及一致性,只是写法要变得直接和简化,个人感觉arduino里驱动层太应用层化,并且冗余。

编译环境使用 gcc+vscode+STM32CubeMX,整个编译框架采用了odrive编译模型。目录结构如下,后续文件及文件夹有更新再上传到github
404596607d03d77d90.png

使用特权

评论回复
狗啃模拟|  楼主 | 2024-3-30 16:41 | 显示全部楼层
Makefile

# This is only a stub for various commands.
# Tup is used for the actual compilation.

BUILD_DIR = build
FIRMWARE = $(BUILD_DIR)/simpleFoc.elf
FIRMWARE_HEX = $(BUILD_DIR)/simpleFoc.hex
PROGRAMMER_CMD=$(if $(value PROGRAMMER),-c 'hla_serial $(PROGRAMMER)',)

include tup.config # source build configuration to get CONFIG_BOARD_VERSION

ifeq ($(shell python -c "import sys; print(sys.version_info.major)"), 3)
        PY_CMD := python -B
else
        PY_CMD := python3 -B
endif

ifneq (,$(findstring v1.,$(CONFIG_BOARD_VERSION)))
  OPENOCD := openocd -f interface/stlink-v2.cfg $(PROGRAMMER_CMD) -f target/stm32f1x.cfg -c init
  GDB := arm-none-eabi-gdb --ex 'target extended-remote | openocd -f "interface/stlink-v2.cfg" -f "target/stm32f1x.cfg" -c "gdb_port pipe; log_output openocd.log"' --ex 'monitor reset halt'
else ifneq (,$(findstring v4.,$(CONFIG_BOARD_VERSION)))
  OPENOCD := openocd -f interface/stlink.cfg $(PROGRAMMER_CMD) -f target/stm32f7x.cfg -c 'reset_config none separate' -c init
  GDB := arm-none-eabi-gdb --ex 'target extended-remote | openocd -f "interface/stlink-v2.cfg" -f "target/stm32f7x.cfg" -c "reset_config none separate" -c "gdb_port pipe; log_output openocd.log"' --ex 'monitor reset halt'
else
  $(error unknown board version)
endif

$(info board version: $(CONFIG_BOARD_VERSION))

all:
#        @mkdir -p autogen
#        @$(PY_CMD) ../tools/odrive/version.py --output autogen/version.c
        @tup --quiet -no-environ-check

clean:
        -rm -fR .dep $(BUILD_DIR)

flash-stlink2: all
        $(OPENOCD) \
                -c 'reset halt' \
                -c 'flash write_image erase $(FIRMWARE)' \
                -c 'reset run' \
                -c exit

gdb-stlink2:
        $(GDB) $(FIRMWARE)

# Erase entire STM32
erase-stlink2:
        $(OPENOCD) -c 'reset halt' -c 'flash erase_sector 0 0 last' -c exit

# Sometimes the STM32 will get it's protection bits set for unknown reasons. Unlock it with this command
unlock-stlink2:
        $(OPENOCD) -c 'reset halt' -c 'stm32f1x unlock 0'

flash-bmp: all
        arm-none-eabi-gdb --ex 'target extended-remote $(BMP_PORT)' \
                --ex 'monitor swdp_scan' \
                --ex 'attach 1' \
                --ex 'load' \
                --ex 'detach' \
                --ex 'quit' \
                $(FIRMWARE)

gdb-bmp: all
        arm-none-eabi-gdb --ex 'target extended-remote /dev/stlink' \
                --ex 'monitor swdp_scan' \
                --ex 'attach 1' \
                --ex 'load' $(FIRMWARE)


flash: flash-stlink2
gdb: gdb-stlink2
erase: erase-stlink2
unlock: unlock-stlink2

.PHONY: stlink2-config flash-stlink2 gdb-stlink2 erase-stlink2 unlock-stlink2
.PHONY: flash-bmp gdb-bmp
.PHONY: all clean flash gdb erase unlock

使用特权

评论回复
狗啃模拟|  楼主 | 2024-3-30 16:42 | 显示全部楼层
tup.config


# Copy this file to tup.config and adapt it to your needs
# make sure this fits your board
CONFIG_BOARD_VERSION=v1.0-12V
CONFIG_DEBUG=false
CONFIG_DOCTEST=false
CONFIG_USE_LTO=false

# Uncomment this to error on compilation warnings
#CONFIG_STRICT=true

使用特权

评论回复
狗啃模拟|  楼主 | 2024-3-30 16:42 | 显示全部楼层
Tupfile.lua

-- Utility functions -----------------------------------------------------------

function run_now(command)
    local handle
    handle = io.popen(command)
    local output = handle:read("*a")
    local rc = {handle:close()}
    return rc[1], output
end

-- If we simply invoke python or python3 on a pristine Windows 10, it will try
-- to open the Microsoft Store which will not work and hang tup instead. The
-- command "python --version" does not open the Microsoft Store.
-- On some systems this may return a python2 command if Python3 is not installed.
function find_python3()
    success, python_version = run_now("python --version 2>&1")
    if success and string.match(python_version, "Python 3") then return "python -B" end
    success, python_version = run_now("python3 --version 2>&1")
    if success and string.match(python_version, "Python 3") then return "python3 -B" end
    error("Python 3 not found.")
end

function add_pkg(pkg)
    if pkg.is_included == true then
        return
    end
    pkg.is_included = true
    for _, file in pairs(pkg.code_files or {}) do
        code_files += (pkg.root or '.')..'/'..file
    end
    for _, dir in pairs(pkg.include_dirs or {}) do
        CFLAGS += '-I'..(pkg.root or '.')..'/'..dir
    end
    tup.append_table(CFLAGS, pkg.cflags or {})
    tup.append_table(LDFLAGS, pkg.ldflags or {})
    for _, pkg in pairs(pkg.include or {}) do
        add_pkg(pkg)
    end
end

function compile(src_file, obj_file)
    compiler = (tup.ext(src_file) == 'c') and CC or CXX
    tup.frule{
        inputs={src_file},        
        command='^o^ '..compiler..' -c %f '..tostring(CFLAGS)..' -o %o',
        outputs={obj_file}
    }
end

-- Packages --------------------------------------------------------------------




stm32f1xx_hal_pkg = {
    root = 'Board/Drivers/STM32F1xx_HAL_Driver',
    include_dirs = {
        'Inc',
        '../CMSIS/Device/ST/STM32F1xx/Include',
        '../CMSIS/Include',
    },
    code_files = {      
        'Src/stm32f1xx_hal_gpio_ex.c',
        'Src/stm32f1xx_hal_adc.c',
        'Src/stm32f1xx_hal_adc_ex.c',
        'Src/stm32f1xx_hal.c',
        'Src/stm32f1xx_hal_rcc.c',
        'Src/stm32f1xx_hal_rcc_ex.c',
        'Src/stm32f1xx_hal_gpio.c',
        'Src/stm32f1xx_hal_dma.c',
        'Src/stm32f1xx_hal_cortex.c',
        'Src/stm32f1xx_hal_pwr.c',
        'Src/stm32f1xx_hal_flash.c',
        'Src/stm32f1xx_hal_flash_ex.c',
        'Src/stm32f1xx_hal_exti.c',
        'Src/stm32f1xx_hal_tim.c',
        'Src/stm32f1xx_hal_tim_ex.c',
        'Src/stm32f1xx_hal_pcd.c',
        'Src/stm32f1xx_hal_pcd_ex.c',
        'Src/stm32f1xx_ll_usb.c',
        'Src/stm32f1xx_hal_uart.c'
    },
    cflags = {'-mcpu=cortex-m3'}
}



simpleFoc_firmware_pkg = {
    root = '.',
    include_dirs = {
        '.',         
        'MotorControl',
    },
    code_files = {        
        'MotorControl/main.cpp',
    },
    -- cflags = {'-D_STM32_DEF_'},  
}

board_v1 = {
    root = 'Board',
    include = {stm32f1xx_hal_pkg},
    include_dirs = {
        'Inc',
        'Drivers/CMSIS/Device/ST/STM32F1xx/Include'
    },
    code_files = {
        './startup_stm32f103xb.s',      
        'Src/main.c',
        'Src/stm32f1xx_hal_msp.c',
        --[[ 'Src/stm32f4xx_hal_msp.c',
        'Src/stm32f4xx_hal_timebase_TIM.c', ]]
        'Src/stm32f1xx_it.c',
        'Src/system_stm32f1xx.c',     
     
        --[[ 'Src/usb_device.c',
        'Src/usbd_cdc_if.c',
        'Src/usbd_conf.c',              
        'Src/usbd_desc.c',
        'Src/can.c',   ]]
        --'Src/i2c.c',      
    },
    cflags = {'-DSTM32F103xB', '-DHW_VERSION_MAJOR=1'},   
    ldflags = {
        '-TBoard/STM32F103CBTx_FLASH.ld'
        -- '-l:iar_cortexM4lf_math.a',
    }
}


boards = {
    ["v1.0-12V"] = {include={board_v1}, cflags={"-DHW_VERSION_MINOR=0 -DHW_VERSION_VOLTAGE=12"}},
    ["v3.2"] = {include={board_v3}, cflags={"-DHW_VERSION_MINOR=2 -DHW_VERSION_VOLTAGE=24"}},
    ["v3.3"] = {include={board_v3}, cflags={"-DHW_VERSION_MINOR=3 -DHW_VERSION_VOLTAGE=24"}}   
}


-- Toolchain setup -------------------------------------------------------------
CC='arm-none-eabi-gcc -std=c99'
CXX='arm-none-eabi-g++ -std=c++17 -Wno-register'
LINKER='arm-none-eabi-g++'

-- C-specific flags
CFLAGS += '-D__weak="__attribute__((weak))"'
CFLAGS += '-D__packed="__attribute__((__packed__))"'
CFLAGS += '-DUSE_HAL_DRIVER'

-- -w:关闭编译时的警告,编译后不显示任何warning,因为有时在编译之后编译器会显示一些例如数据转换之类的警告,这些警告是我们平时可以忽略的。
-- -Wall:编译后显示所有警告。
-- -W:类似-Wall,会显示警告,但是只显示编译器认为会出现错误的警告。

CFLAGS += '-mthumb'
CFLAGS += { '-Wall', '-fdata-sections', '-ffunction-sections'}
CFLAGS += '-g'

-- linker flags
LDFLAGS += '-lc -lm -lnosys' -- libs
-- LDFLAGS += '-mthumb -mfloat-abi=hard -specs=nosys.specs -specs=nano.specs -u _printf_float -u _scanf_float -Wl,--cref -Wl,--gc-sections'
LDFLAGS += '-mthumb -specs=nosys.specs -Wl,--cref -Wl,--gc-sections'


-- Handle Configuration Options ------------------------------------------------

-- Switch between board versions
boardversion = tup.getconfig("BOARD_VERSION")
if boardversion == "" then
    error("board version not specified - take a look at tup.config.default")
elseif boards[boardversion] == nil then
    error("unknown board version "..boardversion)
end
board = boards[boardversion]

-- --not
-- TODO: remove this setting
if tup.getconfig("USB_PROTOCOL") ~= "native" and tup.getconfig("USB_PROTOCOL") ~= "" then
    error("CONFIG_USB_PROTOCOL is deprecated")
end

-- UART I/O settings
if tup.getconfig("UART_PROTOCOL") ~= "ascii" and tup.getconfig("UART_PROTOCOL") ~= "" then
    error("CONFIG_UART_PROTOCOL is deprecated")
end

-- Compiler settings
if tup.getconfig("STRICT") == "true" then
    CFLAGS += '-Werror'
end

if tup.getconfig("NO_DRM") == "true" then
    CFLAGS += '-DNO_DRM'
end

-- debug build
if tup.getconfig("DEBUG") == "true" then
    CFLAGS += '-gdwarf-2 -Og'
else
    CFLAGS += '-O2'
end




-- Generate Tup Rules ----------------------------------------------------------

python_command = find_python3()
print('Using python command "'..python_command..'"')

-- TODO: use CI to verify that on PRs the enums.py file is consistent with the YAML.
-- Note: we currently check this file into source control for two reasons:
--  - Don't require tup to run in order to use odrivetool from the repo
--  - On Windows, tup is unhappy with writing outside of the tup directory
--tup.frule{command=python_command..' interface_generator_stub.py --definitions odrive-interface.yaml --template enums_template.j2 --output ../tools/odrive/enums.py'}
-- tup.frule{
--     command=python_command..' ../tools/odrive/version.py --output %o',
--     outputs={'autogen/version.c'}
-- }
-- Autogen files from YAML interface definitions
--root_interface = board.include[1].root_interface
--tup.frule{inputs={'fibre-cpp/interfaces_template.j2', extra_inputs='odrive-interface.yaml'}, command=python_command..' interface_generator_stub.py --definitions odrive-interface.yaml --template %f --output %o', outputs='autogen/interfaces.hpp'}
--tup.frule{inputs={'fibre-cpp/function_stubs_template.j2', extra_inputs='odrive-interface.yaml'}, command=python_command..' interface_generator_stub.py --definitions odrive-interface.yaml --template %f --output %o', outputs='autogen/function_stubs.hpp'}
--tup.frule{inputs={'fibre-cpp/endpoints_template.j2', extra_inputs='odrive-interface.yaml'}, command=python_command..' interface_generator_stub.py --definitions odrive-interface.yaml --generate-endpoints '..root_interface..' --template %f --output %o', outputs='autogen/endpoints.hpp'}
--tup.frule{inputs={'fibre-cpp/type_info_template.j2', extra_inputs='odrive-interface.yaml'}, command=python_command..' interface_generator_stub.py --definitions odrive-interface.yaml --template %f --output %o', outputs='autogen/type_info.hpp'}
add_pkg(board)
-- add_pkg(freertos_pkg)
-- add_pkg(cmsis_pkg)
-- add_pkg(stm32_usb_device_library_pkg)
--add_pkg(fibre_pkg)
add_pkg(simpleFoc_firmware_pkg)
for _, src_file in pairs(code_files) do
    obj_file = "build/obj/"..src_file:gsub("/","_"):gsub("%.","")..".o"
    object_files += obj_file
    compile(src_file, obj_file)
end
tup.frule{
    inputs=object_files,
    command='^o^ '..LINKER..' %f '..tostring(CFLAGS)..' '..tostring(LDFLAGS)..
            ' -Wl,-Map=%O.map -o %o',
    outputs={'build/simpleFoc.elf', extra_outputs={'build/simpleFoc.map'}}
}
-- display the size
tup.frule{inputs={'build/simpleFoc.elf'}, command='arm-none-eabi-size %f'}
-- create *.hex and *.bin output formats
tup.frule{inputs={'build/simpleFoc.elf'}, command='arm-none-eabi-objcopy -O ihex %f %o', outputs={'build/simpleFoc.hex'}}
tup.frule{inputs={'build/simpleFoc.elf'}, command='arm-none-eabi-objcopy -O binary -S %f %o', outputs={'build/simpleFoc.bin'}}
if tup.getconfig('ENABLE_DISASM') == 'true' then
    tup.frule{inputs={'build/simpleFoc.elf'}, command='arm-none-eabi-objdump %f -dSC > %o', outputs={'build/simpleFoc.asm'}}
end

使用特权

评论回复
狗啃模拟|  楼主 | 2024-3-30 16:42 | 显示全部楼层
移植资料准备
1.simpleFoc源码
通过Arduino IDE下载Simple_FOC-2.3.0.zip,如图
418846607d076501ce.png

使用特权

评论回复
狗啃模拟|  楼主 | 2024-3-30 16:42 | 显示全部楼层
获取Arduino 下的stm32f1x的驱动层
windows下,运行cmd通过git获取驱动层源码

git clone https://github.com/stm32duino/Arduino_Core_STM32.git

使用特权

评论回复
狗啃模拟|  楼主 | 2024-3-30 16:42 | 显示全部楼层
建立基本工程,并运行
232芯片一般都有两路,那么在原理图设计时,就拉了两路串口,设计思路:串口1,使用printf函数可以打印些自己需要的调试信息。串口2,调给simpleFoc里的print。

在第一章节里目录结构Board目录下建立stm32cubx_mx工程,目录层次如图
808846607d08dd8492.png

使用特权

评论回复
狗啃模拟|  楼主 | 2024-3-30 16:43 | 显示全部楼层
建立基本工程,主要是启用串口1作为printf输出
668166607d09c48a6e.png

在main.c里添加代码
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int _write(int fd, char *ch, int len)
{
HAL_UART_Transmit(&huart1, (uint8_t*)ch, len, 0xFFFF);
return len;
}
/* USER CODE END 0 */

使用特权

评论回复
狗啃模拟|  楼主 | 2024-3-30 16:43 | 显示全部楼层
编译下载,成功
258326607d0bb99c7b.png

总结
这样编译框架基本建立,关于编译环境配置细节,可以去网上搜Odrive编译环境搭建,下一章节将会移植 simplefoc的print,因为这个在编码器,电流检测,pwm里都有调用。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

63

主题

803

帖子

2

粉丝