<!-- {%hackmd theme-dark %} --> > 建議程度:在stm IDE中會使用.h和.cpp > 幫我選一下深色模式 # [STM Template](https://drive.google.com/file/d/1YhRkzcaMQ52boAED4liR4jURWMzd1Jfo/view?usp=sharing)導入 ### 1. **更變程式語言** 打開STM32CubeIDE,**新建專案**(建議)或用已有專案修改,板子選要用的就好 新專案選C++,或者對專案點擊右鍵轉為C++(已經是C++的會寫convert to C) ![image](https://hackmd.io/_uploads/Sks9RKfuR.png =x350) ![image](https://hackmd.io/_uploads/BJnEkqzd0.png =x350) ### 2. **導入函式庫** 解壓縮剛下載的STM_template資料夾,**直接**將user_lib拖到Inc,user拖到Src ![image](https://hackmd.io/_uploads/H19zZqz_R.png =x250) ![image](https://hackmd.io/_uploads/r1AmD5Mu0.png =x180) ### 3. **專案設定** * **user_lib的設定** 對user_lib和ros_lib右鍵點開,選擇Add/remove include path(使得可以被include) ![image](https://hackmd.io/_uploads/BJKhE5MuA.png =x350) ![image](https://hackmd.io/_uploads/ryfVBqGdC.png =x220) * **user的設定** 點開main.c,找到USER CODE BEGIN Includes,再往下找到USER CODE BEGIN 2 (迴圈上面) ![image](https://hackmd.io/_uploads/ryW4I5zuC.png) 記得按ctrl+s儲存 :::spoiler 備註 mainpp.cpp裡面放了main_function,搶先main.c的while進入迴圈 ![image](https://hackmd.io/_uploads/HJ2U_5fuC.png =x300) ::: > **導入完成,可以試著編譯看看~** # STM模板介紹 根據TDK 27th stm程式衍生出的TDK架構改版而來 ![TDK架構](https://hackmd.io/_uploads/r1aTxoGOC.png) :::spoiler 概念 由Arduino IDE的程式架構可知,程式僅需由setup和loop組成 ![arduino程式](https://hackmd.io/_uploads/SyBoboG_A.png =x180) 觀察mainpp.cpp中的main_function,會發現有相似的結構 ![mainpp main_function](https://hackmd.io/_uploads/HkyXroMu0.png) ::: ## 變數的原則 <font color="#9CF763">變數</font>定義在**xxx.cpp**(本體在cpp),會在檔案間共用的變數再用`extern`宣告在**xxx.h** (避免重複定義) <font color="#9CF763">腳位</font>的`#define`、<font color="#9CF763">Timer</font>的`extern`也是放在**xxx.h** <font color="#9CF763">數值</font>的`const` `#define`沒什麼規範,放哪順眼就好。除非也是會在檔案間共用,則放在**xxx.h** :::info * 查找時比較方便整齊(多用註解標示&分類) * 方便其他檔案在引用時能直接使用,extern易找根據 * 不需使用時直接將**xxx.h檔中的不需要的宣告註解掉/刪掉**,再編譯會報錯幫忙顯示出不需要的部分方便修改 * 若整個都不需要時直接將`#include "xxx.h"`註解掉/刪掉即可 ::: > 備註:在函數外變數的都是全域變數(可用現場表達式) --- ### <font color="#68DBEC">mainpp</font> 程式運行自main.c開始,mainpp作**c與c++接口**,程式在此運行 :::spoiler mainpp.h ![image](https://hackmd.io/_uploads/ByDguW4d0.png =x190) > 如果要加新東西記得在兩個#ifdef之間的區域 ::: :::spoiler mainpp.cpp ![mainpp.cpp](https://hackmd.io/_uploads/B19P8xEdA.png =x230) * main_function() 程式在這裡運作(自main.c進入main_function()),用於<font color="#9CF763">初始化</font>及作為<font color="#9CF763">高速迴圈</font>(CPU速度),loop放需要高速執行的函式,通常不放複雜的運算 ::: ### <font color="#68DBEC">TIM_IT</font> 除了mainpp的迴圈程式在運行,stm32還有以特定頻率運行的Timer中斷(們) > 程式執行時會持續運作的程式:**mainpp迴圈** & **Timer中斷函式** 僅此 :::spoiler TIM_IT.h 基本上<font color="#68DBEC">**所有的腳位和Timer**</font>都放在這裡統一管理(記得分類),<font color="#9CF763">引用各自板子的函式庫</font>使得**腳位**和**Timer**的型態有定義 (還有**中斷函式**) <font color="#68DBEC">**(記得ioc也要設定加儲存)**</font> ![TIM_IT.h](https://hackmd.io/_uploads/r1IiBlVdR.png =x280) ::: :::spoiler TIM_IT.cpp ![TIM_IT.cpp](https://hackmd.io/_uploads/H1K2wlVu0.png =x250) > 這裡會引入很多自訂函式庫 * HAL_TIM_PeriodElapsedCallback 以固定頻率進入中斷 (插隊main_function的while(1):grinning:),作為<font color="#9CF763">低速迴圈</font>使用,基本上<font color="#68DBEC">**絕大部分操作都在HAL_TIM_PeriodElapsedCallback裡**</font>(極少部分在mainpp的while) 在編譯時改變原函式的弱定義,進中斷時調度,所以只需要放在TIM_IT中即可使用,不須放到mainpp.cpp * TIM_Start() 觀察其他程式,發現stm的setup只有Timer要開,所以放置 :::info * Timer開始計時 * encoder啟用 * Timer_IT(中斷模式)啟用 ::: ### <font color="#68DBEC">ros_port</font> **通訊**要使用ros的物件格式所以將ros相關的都放在這個檔案統一管理,不須通訊時可不使用。 :::spoiler ros_port.h 在.h檔引入ros的物件格式包,因為可能會有需要在檔案之間使用的ros變數,以及callback函式的參數項。 在.cpp檔時只要引入ros_port.h即可繼續使用已定義的物件格式 ![image](https://hackmd.io/_uploads/Bkc12nR_R.png =x300) ::: :::spoiler ros_port.cpp > callback函式及宣告(放在上面) ![image](https://hackmd.io/_uploads/rJUA55ROA.png =x150) * ros_setup <font color="#68DBEC">**(放在mainpp.cpp,執行一次)**</font> ![image](https://hackmd.io/_uploads/S1nDhuR_C.png =x100) * ros_sub 用於接收ros傳過來的資料 <font color="#68DBEC">**(放在mainpp.cpp的while裡以便隨時接收)**</font> ![image](https://hackmd.io/_uploads/SkQ52_0O0.png =x70) * ros_pub 用於發送資料給ros <font color="#68DBEC">**(放在Timer中斷函式裡,發送頻率在100hz上下)**</font> ![image](https://hackmd.io/_uploads/BkDjY50_R.png =x100) ::: 通訊的基本設定可以參考學長的[2022 東京威力TEL 筆記](https://hackmd.io/@925/S1lQD_ljq/%2Fs%2Fryg2eQv4Q1Gplup81jfMRw)的 03. ROS x STM > 通訊時stm用**傳輸線**接電腦或派就可以了,比較穩固方便。不夠就接hub ## 其他函式庫 存放函數或class(藍圖),不放實例或腳位、Timer,以一種機構新增一個檔案為原則 ### <font color="#9CF763">dc_motor</font> ![image](https://hackmd.io/_uploads/HyFxiR_sR.png) :::info 作為虛擬直流馬達的class(藍圖),要使用時引用`dc_motor.h`,接著根據 DC_motor( double res, double ratio, double p, double i, double d ) 填入參數,建立虛擬馬達 ex : `DC_motor motor1(512,20,30,1,0)` ::: > freq是進Timer中斷的頻率(基本相同,因為放在同一個Timer運作) 建立足夠的馬達,在Timer中斷函式裡把函式用這樣的方式接著就可以了 (只有箭頭之間的程式有次序性) ![image](https://hackmd.io/_uploads/SyTglyKjR.png =x350) ::: spoiler 使用者會用到的變數: ![image](https://hackmd.io/_uploads/S1WVN0diA.png) * SP(set point):PID控制的設定值,在這裡是指<font color="#9CF763">**設定的轉速**</font> * PV(Process value):當前的過程測量值,在這裡是指<font color="#9CF763">**實際的轉速**</font> * output_ratio:PID的輸出結果,作為<font color="#9CF763">**PWM的輸出比例**</font>,介於1和-1之間 ::: ### <font color="#9CF763">kinematic_model</font> 裡面放置了各種標準底盤的正逆運動學模型,用namespace區隔 (要用時尺寸參數要設好) ~~想要奇奇怪怪底盤可以自己設計運動學模型~~ > <font color="#9CF763">**直角座標速度**(m/s)</font><=><font color="#9CF763">**各輪輪速**(rad/s)</font> :::spoiler 函式的設計概念 利用指標來直接改變所接輸出變數的值,以隔離外界變數成為純參數的函數 ![model](https://hackmd.io/_uploads/rkVHkq_sA.png =x200) :::