一、編碼器測速重要參數
? ? ? ? 有刷電機編碼器參數(其他的后面會慢慢提及,也可以在某寶看)
? ? ? ? 1. 編碼器分辨率(PPR)
? ? ? ? 2. 編碼器工作電壓?
? ? ? ? 3. 電機減速比 例如 30:1 指的就是電機減速軸轉1圈,編碼器轉30圈。
????????注意明確一個關系,大部分直流減速電機的機械結構,是編碼器套在主軸,而電機軸是經過機械傳動減速后轉動的,所以我們把這類電機叫做減速電機。
? ? ? ? 參數1和3到底有什么用呢?
? ? ? ? 舉個栗子,我們的編碼器在VOFA上的測速結果為300RPM,而編碼器接口配置為100方式計數,即四倍頻,那么:
? ? ? ? 電機減速轉速??=? 主軸轉速? /? 減速比
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? =? 編碼器轉速 / 減速比
? ? ? ? ? ? ? ? ? =? (計數器接收脈沖個數 / 四倍頻?/ PPR / 減速比)*? 測速中斷頻率??
? ? ? ? 實際代碼中,還需要考慮時間單位s->min的換算
二、Encoder的HAL庫函數
? ? ? ? (1)HAL_TIM_Encoder_Init()
????????初始化定時器基礎參數,以及編碼器接口,如果用的是Cube則不需要編寫。
? ? ? ? (2)HAL_TIM_Base_Start_IT()
????????定時器外設若需要使用中斷功能(比如編碼本身和編碼過程中斷回調處理),則必須提前使能定時器base中斷。
? ? ? ? (3)HAL_TIM_Encoder_Start()
? ? ? ? 開啟編碼器接口通道,與PWM_start有異曲同工之妙。
? ? ? ? (4)定時器更新中斷回調函數
? ? ? ? ?有兩種處理方式,一種是單定時器中斷,通過使用encoder本身的更新中斷,當計數值達到ARR時候,自動進入中斷處理測量的脈沖數。
? ? ? ? ?第二種是Encoder中斷+其他定時器中斷,通過其他定時器預設定的中斷頻率,來對速度采樣頻率進行自由的改動,不受編碼器采樣頻率的限制,但如果中斷頻率設置過高會造成嚴重誤差。
? ? ? ? (5)__HAL_TIM_IS_COUNTING_DOWN()
? ? ? ? 在無CubeMX時,用于讀取DIR位,進而判斷計數方向。
? ? ? ? 有Cube時,直接判斷編碼器反饋數值的正負。
三、Encoder的定時器配置
? ? ? ? (1)配置編碼器模式
? ? ? ? ? ? ? ? TI1與TI2都檢測,也就是四倍頻
????????????????
? ? ? ? (2)配置Encoder雙輸入通道參數
? ? ? ? ? ? ? ? 理論上兩個通道參數應該一致。
????????????????因為是100法計數,根據功能表規則,我們的計算規則應該是上升沿有效,所以邊沿極性選擇為上升沿。
? ? ? ? ? ? ? ? IC采用直接選擇
? ? ? ? ? ? ? ? 分頻因子不分頻,如果分頻了,那我們何必用四倍頻呢?
? ? ? ? ? ? ? ? 接下來,輸入濾波器可以暫時先設置為10。它起到一個什么作用呢?
? ? ? ? ? ? ? ? 通俗的講,它把一個電平信號掃描十次,然后判斷是否有高低反轉的不穩定情況,如果信號不穩定,則丟棄這一幀。
????????????????
? ? ? ? ? ? ? ? 實際上,它是一個低通濾波器,對高頻干擾信號做衰減。你的參數設置的越大,它掃描次數越多,過濾高頻尖刺的能力也就更強,但芯片工作量也會隨之增加。(濾波過程可以近似參考模擬線路的0.1uF的RC濾波器。圖畫的可能不標準,具體內容請見隔壁DSP)
????????????????
? ? ? ? ? ? ? ? (3)中斷方法1:Encoder更新中斷
? ? ? ? ? ? ? ? 我的這款主控找不到Encoder更新中斷開啟,可能是因為Cube封裝了Encoder的更新中斷的總計數值更新過程,如果要找得去ISR文件看看,下面介紹另外一種方法。
? ? ? ? ? ? ? ? (4)中斷方法2:另開定時器進行中斷
? ? ? ? ? ? ? ? 為了節省資源,我選了基本定時器做定時器中斷。
? ? ? ? ? ? ? ? 這里設置中斷頻率為10Hz,也就是0.1s中斷一次,對于我自己的外設來說效果比較理想,實際工程中需要不斷調試?中斷頻率 和 PWM的ARR?去測試它的開環測量準確度。?? ? ? ? ?
?四、實戰例程
? (1)使能中斷功能并開啟編碼器
? ? ? ? ? ? ? ? 雖然我們沒手寫編碼器的ISR,但是我們還是需要它的中斷測量總計數值,它沒有被禁用只是在后臺默默的為我們計數。
HAL_TIM_Base_Start_IT(&htim6);HAL_TIM_Base_Start_IT(&htim2); HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);
?????????????????我們使用GetCounter函數來一段時間內的獲取編碼值,獲取完立刻清零,不能放在其他位置,否則會因為其他輪詢代碼的運行造成結果偏小的誤差(我們下一次中斷還要用!)
? ? ? ? ? ? ? ? 至于轉速查看的方法,我不建議用串口打印,因為它背后調用了stdio庫,運行速度肯定沒有VOFA+的float協議來的快。
? ? ? ? ? ? ? ? VOFA+的標準用法,我會在補充章節分享。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){if(htim==&htim6){printf("entered");int16_t val = (int16_t)__HAL_TIM_GetCounter(&htim2);__HAL_TIM_SET_COUNTER(&htim2, 0);float RPM =(float)((val/7.0/50.0/4.0)*600);Vofa_data(RPM);
// printf("RPM: %.3f \r \n",RPM);
// __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1,BINMotor_SpeedtoPulse(BACK,L_AddPID.pwm_add));dc_motor_pwmset(RPM,&spdPID);}}
? ? ? ? ? ? ? ??
????????????????