旋鈕鍵盤項目---foc講解(開環)

這里就不過多的講解什么原理,公式的變換了,感興趣的可以看燈哥開源,講解的非常好的。當然,更細致的講解,也可以看b站其他教學。

我這里主要講解我對于開環部分的理解,以及stm32代碼的實現邏輯。可以看作是講解燈哥的代碼流程,畢竟是一致的。

本次stm32使用hal庫開發。

一、為什么會有克拉克變換、帕克變換

一個電機,我們如果想要它能夠在損失最小的情況下運動,那么就是我們希望力永遠垂直魚當前指向的方向。(這里,我們把電機看作一個指針,電機轉動,其實就是指針轉動。想要指針損失最小轉動,自然力就是垂直與指針,否則就會有損耗,高中物理嘛)。那么問題來,我們知道需要力,我們該如何設定電機輸入的uwv電壓,來設定這個力呢?

我們可以將力分解,分解為一個固定坐標系下的兩個方向的力。一般是x,y軸的方向。為什么呢?當然是好算,很多的表達式都可以不要再去計算偏移角度了。當然,這里就出現了一個問題,這個力是不斷變化的,我們怎么分解?你這個力現在指向左側,一會又指向左下角了,怎么做分解呢?所有這個當前的角度,我們是必須知道的。有了角度才好分解。ok,這個角度,我們可以使用傳感器來獲取。這個變換也就是帕克逆變換!

好了,我們現在就當我們得到水平固定坐標系下的兩個分解,那么如何得到uwv呢?這個很簡單了,我們直接將u或者其他,無所謂哪一個當作x軸,這樣就不需要算它了。x軸分解得到多大,就是它的值。借用燈哥的圖,這里的la=lα,非常簡便,減少了計算。(所以其實不是一定要這樣的,你可以根據自己喜愛去偏轉,只是麻煩而已,而且計算會多一個正余弦計算)。好了,我們再將lβ分解。角度都知道,自然也就得到了lb,lc。這就是克拉克逆變換。

雖然說是逆變換,實際上就是輸入輸出地位的變換而已。自然的,我們反過來再順一遍,就知道我們輸入uwv,這個力是哪個方向的力了。

二、代碼

我的stm32是當時不知道什么時候收藏的一個stm32f407zgt6板子。

主要也是燈哥的代碼思路。

首先,我們轉動起來,需要去配置一個定時器來輸出三路pwm。

void PWM_gpio_init()
{__HAL_RCC_TIM1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10; // TIM1_CH1~CH3GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;        // 復用推挽GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;    // TIM1 對應的 AFHAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void PWM_init(uint16_t arr, uint16_t psc)
{PWM_gpio_init();TIM_OC_InitTypeDef sConfigOC = {0};TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};/* 基本定時器配置 */htim1.Instance = TIM1;htim1.Init.Prescaler = 0;                   // 不分頻htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;htim1.Init.Period = MAX_PWM-1;                   // PWM頻率 = 168MHz / (8399+1) = 20kHzhtim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim1.Init.RepetitionCounter = 0;htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;HAL_TIM_PWM_Init(&htim1);sConfigOC.OCMode = TIM_OCMODE_PWM1;sConfigOC.Pulse = 1400;                        // 初始占空比0sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2);HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3);HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
}

這樣我們就得到了三個pwm輸出。

剩下的foc開環部分用到的代碼,講解一下這個流程。其實就是void velocityOpenloop(float target_velocity)這個函數。核心作用是在開環條件下,根據目標轉速更新電機相角并輸出對應的 PWM 電壓。開環的情況,一般就是我們不算角度,那么角度怎么來呢?

????????1.我們可以通過定時器來,比如定時1ms,加上我們需要的速度,那么時間乘以角速度,就是角度了。當然了,這種是不準確的。

? ? ? ? 2.我們可以通過讀取當前獲取的時間,也就是記錄上一次進入函數的時間,和本次進入的時間,這兩者之差就是運行時間。當然,首先你要有這一個時間獲取的方法。我這里是hal庫,如果是標準庫,或者寄存器,或者其他開發板,就得自己想辦法了。

????????得到角度之后,我們就知道我們當前的所在的角度。然后輸入電壓值,電壓的大小代表著力矩的大小,同樣的,這個電壓不能太大。如果太大,可能會燒電機,或者其他問題。根據當前的所在角度,所給力,我們就可以由上邊的克拉克,帕克等變換,得到uwv,這時候在給pwm配置,就完成了一次運動。我們將velocityOpenloop放到main函數的while里就可以了。當然,也可以再開一個定時器,把這個放到定時器的回調函數里,這里的時間就是固定的了。可以參考定時器調用開環函數。


float _normalizeAngle(float angle){float a = fmod(angle, 2*PI);   //取余運算可以用于歸一化,列出特殊值例子算便知return a >= 0 ? a : (a + 2*PI);  
}void setPhaseVoltage(float Uq,float Ud, float angle_el) {angle_el = _normalizeAngle(angle_el + zero_electric_angle);// 帕克逆變換Ualpha =  -Uq*sin(angle_el); Ubeta =   Uq*cos(angle_el); // 克拉克逆變換Ua = Ualpha + voltage_power_supply/2;Ub = (sqrt(3)*Ubeta-Ualpha)/2 + voltage_power_supply/2;Uc = (-Ualpha-sqrt(3)*Ubeta)/2 + voltage_power_supply/2;setPwm(Ua,Ub,Uc);
}void setPwm(float Ua, float Ub, float Uc) {// 計算占空比// 限制占空比從0到1dc_a = _constrain(Ua / voltage_power_supply, 0.0f , 1.0f );dc_b = _constrain(Ub / voltage_power_supply, 0.0f , 1.0f );dc_c = _constrain(Uc / voltage_power_supply, 0.0f , 1.0f );//寫入PWM到PWM 0 1 2 通道__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,dc_a*MAX_PWM);__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_2,dc_b*MAX_PWM);__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_3,dc_c*MAX_PWM);
}
static inline uint32_t micros(void) {return DWT->CYCCNT / (SystemCoreClock / 1000000);
}
void velocityOpenloop(float target_velocity){unsigned long now_us = micros();float Ts = (now_us - open_loop_timestamp) * 1e-6f;if(Ts <= 0 || Ts > 0.5f) Ts = 1e-3f;shaft_angle = _normalizeAngle(shaft_angle + target_velocity*Ts);// 最大只能設置為Uq = voltage_power_supply/2,否則ua,ub,uc會超出供電電壓限幅float Uq = voltage_power_supply/8;setPhaseVoltage(Uq,  0, _electricalAngle(shaft_angle, 7));open_loop_timestamp = now_us;  //用于計算下一個時間間隔
}
float _electricalAngle(float shaft_angle, int pole_pairs) {return (shaft_angle * pole_pairs);
}
void DWT_Init(void) {CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // 使能 DWTDWT->CYCCNT = 0;                                // 清零計數DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;            // 啟動
}

講解的還是過于粗糙了,如果錯誤,歡迎指正。

智能旋鈕(一)---foc開環控制

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/95593.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/95593.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/95593.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據科學與計算:爬蟲和數據分析案例筆記

案例 1&#xff1a;中國大學排名爬取與分析 一、任務描述 目標&#xff1a;爬取高三網中國大學排名一覽表&#xff0c;提取學校名稱、總分、全國排名、星級排名、辦學層級等數據&#xff0c;并保存為 CSV 文件。 網址&#xff1a;2021中國的大學排名一覽表_高三網 二、任務…

華測科技的3D GPR數據分析

很高興得到了張總的支持&#xff0c;獲得了他們雷達的數據&#xff0c;并寫了雷達數據讀取和轉換文件。1 背景搜索后發現華測實力很強&#xff0c;因為他們可達到100km/h的時速&#xff0c;以前我只知道中電眾益可以達到這個速度。2數據格式分析2.1 華測數據因為長時間不編程&a…

最長鏈(二叉樹直徑DFS)

題目描述現給出一棵N個結點二叉樹&#xff0c;問這棵二叉樹中最長鏈的長度為多少&#xff0c;保證了1號結點為二叉樹的根。輸入第1行為包含了一個正整數N&#xff0c;為這棵二叉樹的結點數&#xff0c;結點標號由1至N。 接下來N行&#xff0c;這N行中的第i行包含兩個正整數l[i]…

802.11 Wi-Fi 競爭機制深度分析:CSMA/CA 與 DCF

802.11 Wi-Fi 競爭機制深度分析&#xff1a;CSMA/CA 與 DCF 一、核心機制&#xff1a;CSMA/CA&#xff08;載波偵聽多路訪問/沖突避免&#xff09; 傳統以太網使用 CSMA/CD&#xff08;沖突檢測&#xff09;&#xff0c;但無線環境中無法實現沖突檢測&#xff0c;因此802.11采用…

【Go語言-Day 36】構建專業命令行工具:`flag` 包入門與實戰

Langchain系列文章目錄 01-玩轉LangChain&#xff1a;從模型調用到Prompt模板與輸出解析的完整指南 02-玩轉 LangChain Memory 模塊&#xff1a;四種記憶類型詳解及應用場景全覆蓋 03-全面掌握 LangChain&#xff1a;從核心鏈條構建到動態任務分配的實戰指南 04-玩轉 LangChai…

C語言——深入理解指針(四)

C語言——深入理解指針&#xff08;四&#xff09; 數組名的意義sizeof&#xff08;數組名&#xff09;&#xff0c;且數組名單獨放在sizeof內部&#xff0c;則這里的數組名表示整個數組&#xff0c;計算的是整個數組的大小&數組名&#xff0c;這里的數組名表示的是整個數組…

LeetCode 刷題【42. 接雨水】

42. 接雨水 自己做 解&#xff1a;雙指針左右分割容器 class Solution { public:int trap(vector<int>& height) {int res 0;int len height.size();if(len < 2) //構不成一個容器了&#xff0c;直接返回return res;int end len - 1; //右邊界int…

網絡的基本概念、通信原理以及網絡安全問題

目錄 1、 什么是網絡&#xff1f; &#xff08;1&#xff09;網絡的概念與本質 &#xff08;2&#xff09;電壓信號的合并與抵消 &#xff08;3&#xff09;電壓的本質 2、中轉設備 &#xff08;1&#xff09;背景 &#xff08;2&#xff09;中轉設備的處理能力與編程能…

Windows下使用WSL2創建Ubuntu子系統(更改安裝位置與啟動圖形桌面)

Windows下使用WSL2創建Ubuntu子系統&#xff08;更改安裝位置與啟動圖形桌面&#xff09; 本文介紹如何使用WSL2創建Ubuntu子系統&#xff0c;并更改安裝位置到其他磁盤&#xff0c;并啟動圖形桌面Xfce4。 WSL 版本: 2.5.7.0 系統版本: Windows11 23H2 相關工具&#xff1a;Mo…

時間泄漏 TemporalLeakage

時間泄漏 TemporalLeakage: 就是后續有事件發生&#xff0c;然后才有了這個結果&#xff0c;但是在該事件發生之前&#xff0c;不應該預測該結果。 Temporal Leakage 問題是往往導致縱向Planning不“果斷”。 解決方案&#xff1a;人工標注出時間發生的時刻 真值只監督時間發生…

獨立書店數字化轉型:絕版書修復檔案系統與讀者閱讀行為分析營銷平臺

在電商沖擊與閱讀習慣變遷的雙重壓力下&#xff0c;獨立書店正遭遇 “舊書修復難、新書賣不動” 的生存困境。傳統模式中&#xff0c;絕版書修復依賴老師傅經驗&#xff0c;單本修復周期長達 2 周&#xff0c;損耗率超 30%&#xff1b;營銷缺乏數據支撐&#xff0c;導致客流年均…

const修飾指針用法詳解

目錄 一、const修飾變量 繞過const限制的問題 二、const修飾指針變量 1、無const修飾的指針 2、const放在*左邊 3、const放在*右邊 4、*兩邊都有const 三、使用建議 四、記憶技巧 一、const修飾變量 在C語言中&#xff0c;變量默認是可修改的。如果我們希望某個變量不能…

pcl法線估計的踩坑

1&#xff0c;normalestimation對點云法線的評估&#xff0c;只輸出法線向量&#xff0c;并不輸出xyz值。如果輸出類型是pointnormal&#xff0c;那么這點云的法向量有值&#xff0c;xyz值都是02&#xff0c;添加點云xyz數據。可以使用 pcl::concatenatefields(*a,*b,*c)函數p…

利用Minicsv庫解析csv文件的c程序及讀入測試

上午的c程序寫入xlsx較快但不正確&#xff0c;python程序雖正確但過慢。所以找了一個全部源程序加起來不到4K字節的C語言csv解析庫Minicsv&#xff0c;來改寫&#xff0c;改寫結果如下&#xff1a; #include <stdio.h> #include <stdlib.h> #include <string.h…

企微用戶部門同步HRS系統

企微用戶導入HR系統流程說明 概述 本文檔詳細說明了WechatUserImportServiceImpl.importWechatUsersToHrs()方法的業務流程和實現邏輯。該方法負責將企業微信用戶數據同步導入到HR管理系統中&#xff0c;包括員工信息、工作信息和任職記錄的創建與更新。 主要功能 數據同步…

告別傳統SEO!擁抱下一代流量密碼:生成式引擎優化(GEO)實戰指南

前言&#xff1a;為什么你的“最佳實踐”SEO正在失效&#xff1f;你是否發現&#xff0c;即使嚴格遵循了谷歌自2019年以來的所有“最佳實踐”&#xff0c;你的技術博客或產品文檔的流量依舊增長乏力&#xff0c;甚至不升反降&#xff1f;你不是一個人。問題在于&#xff0c;游戲…

week1-[一維數組]傳送

week1-[一維數組]傳送 題目描述 有 nnn 個傳送門&#xff0c;從第 iii 個傳送門進去后會被傳送到第 aia_iai? 個傳送門&#xff0c;進而被傳送到第 aaia_{a_i}aai?? 個傳送門&#xff0c;如此一直下去……小 A 想知道從第 kkk 個傳送門進去后&#xff0c;能不能回到第 kkk 個…

【18】目心智能——目心智能 嵌入式一面 ,校招,面試問答記錄

目心智能——目心智能 嵌入式一面 &#xff0c;校招&#xff0c;面試問答記錄 1 簡單自我介紹2 你做了這么多算法&#xff0c;為什么不找算法的&#xff1f;3 我們主要還是軟件開發&#xff0c;不做結構設計4 模電知識6 CSDN應該附鏈接在簡歷上&#xff0c;稍后發給我&#xff…

C++第二十課:快遞運費計算器 / 黑白配+石頭剪刀布小游戲

快遞運費計算器幫一家快遞站點開發一個快遞運費計算器&#xff0c;快遞站點人員只需要輸入包裹重量和地點編號即可計算出對應的運費。假設快遞費計算規則如下&#xff1a;首重&#xff1a;3公斤 3公斤以內&#xff1a;1.東三省/寧夏/青海/海南&#xff1a;12元&#xff0c;2.新…

網絡安全藍隊常用工具全景與實戰指南

摘要 在現代信息系統的安全防護中&#xff0c;藍隊承擔著防御、檢測、響應和持續改進的核心職責。要實現高效、可持續的防御能力&#xff0c;藍隊需要一整套成熟、可靠的工具集來進行威脅情報收集、日志分析、入侵檢測、漏洞評估、端點防護、網絡流量監控、事件響應與取證等工作…