みなさん、こんにちは。Xiaozhengです。この記事では、バランストロリーモーターのエンコーダーについて説明します。各パートナーに、エンコーダのハードウェア構造とソフトウェアプログラミングをより明確に理解させます。
1.ハードウェア構造
1.エンコーダとは何ですか?
エンコーダは、角変位または角速度を一連の電気デジタルパルスに変換するロータリーセンサーです。エンコーダは、光電エンコーダとホールエンコーダに分けられます。
2.エンコーダの動作原理
ここでは主にホールエンコーダを紹介します(光電エンコーダの精度はホールの38倍です)。ホールエンコーダは、ホールホースプレートとホール素子で構成されています。ハルマプレートは、特定の直径の円形プレート上で異なる磁極に分割されています。ホールホースディスクはモーターと同軸であり、モーターが回転するとホール素子が複数のパルス信号を検出して出力します。回転方向を判断するには、通常、一定の位相差のある2組の方形波信号を出力します。概略図は次のとおりです。
3.エンコーダインターフェースピン
使用するモーターはGM25-370DCギアモーター(ホールエンコーダ付き)で、対応するエンコーダピン図は次のとおりです。
4.単位時間あたりのエンコーダの速度測定原理。
パルスの移動距離に応じてモーターの実際の速度を計算します。ここでは、10msのタイマー割り込みが使用されます。
5.データを収集する方法は通常2つあります
。最初のソフトウェア技術は外部割り込みを直接使用して収集し、AB位相差の差によって正または負を判断できます。2番目のハードウェアテクノロジはタイマーエンコーダモードを直接使用し、2番目のテクノロジはここで使用されます。また、測定精度を向上させるとよく言われる周波数を4倍にする方法でもあります。実際、フェーズABの立ち上がりエッジと立ち下がりエッジの両方を収集するだけなので、1は4に変わります。外部割り込みモードを使用して実装するには、より多くのリソースが必要です。パルス変化値を測定するには、タイマーのエンコーダモードを使用することをお勧めします。
2、ソフトウェアプログラミング
1.エンコーダ機能-Encoder.c1 )エンコーダ1およびエンコーダ2初期化関数の 入力パラメータ:なし①GPIO初期化②タイマー基本構造初期化③エンコーダ設定機能④タイマー入力キャプチャ機能⑤タイマー更新フラグのクリアサイン更新割り込みの実行∥タイミングのクリアデータ⑧タイマーイネーブル
エンコーダ構成機能の具体的な説明です
// 编码器配置函数: 定时器2,模式3,上升沿
TIM_EncoderInterfaceConfig(TIM2,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
①最初のパラメータはタイマーの選択です。
②2番目のパラメータはエンコーダ開始モードです。TIM_EncoderMode_TI12:T1とT2の各遷移エッジでカウントします。
[モード]:
Tl1モード:T1のすべてのエッジをカウントします。
Tl2モード:T2のすべてのエッジをカウントします。
Tl1l2モード:T1とT2のすべてのエッジをカウントします。
簡単な例を挙げると、Tl1が立ち上がりエッジにあるとき、Tl2はローレベルにあります。これは、対応するTl1FP1信号がカウントアップすることを意味します。類推すると、下の図では、エンコーダのカウント操作から派生したカウントモードを丸で囲んでいます。
③3番目と4番目のパラメータは極性構成ですが、ここでは立ち上がりエッジと立ち下がりエッジに分けられますが、極性を設定すると立ち上がりエッジと立ち下がりエッジが設定されるのはなぜですか?stm32f10x.tim.c関数を入力すると、極性の設定が実際にはTIM_CCER_CC1Pレジスタに関連していることがわかります。STM32中国語リファレンスマニュアルを調べるとわかります。
ここでわかるように、IC1の立ち上がりエッジに対応して、反転しないように設定します。
エンコーダ機能コード:
#include "encoder.h"
#include "sys.h"
void Encoder_TIM2_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
TIM_ICInitTypeDef TIM_ICInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 ,ENABLE); // 开启定时器时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE); // 开启GPIO时钟
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; // 编码器1:PA0/PA1
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA ,&GPIO_InitStruct);
TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; // 不分频
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
TIM_TimeBaseInitStruct.TIM_Period = 65535; // 重装载值65535
TIM_TimeBaseInitStruct.TIM_Prescaler =0; // 分频系数0
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
// 编码器配置函数: 定时器2,模式3,上升沿
TIM_EncoderInterfaceConfig(TIM2,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
TIM_ICStructInit(&TIM_ICInitStruct);
TIM_ICInitStruct.TIM_ICFilter = 10; // 滤波器设置为10
TIM_ICInit(TIM2,&TIM_ICInitStruct);
TIM_ClearFlag(TIM2,TIM_FLAG_Update); // 清除定时器标志位
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); // 定时器2,溢出更新,使能
TIM_SetCounter(TIM2,0); // 定时数据清零
TIM_Cmd(TIM2,ENABLE); // 定时器2使能
}
void Encoder_TIM4_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
TIM_ICInitTypeDef TIM_ICInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4 ,ENABLE); // 开启定时器时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE); // 开启GPIO时钟
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // 编码器2:PB6/PB7
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB ,&GPIO_InitStruct);
TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; // 不分频
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
TIM_TimeBaseInitStruct.TIM_Period = 65535; // 重装载值65535
TIM_TimeBaseInitStruct.TIM_Prescaler = 0; // 分频系数0
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStruct);
// 编码器配置函数:定时器4,模式3,上升沿
TIM_EncoderInterfaceConfig(TIM4,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
TIM_ICStructInit(&TIM_ICInitStruct);
TIM_ICInitStruct.TIM_ICFilter = 10; // 滤波器设置为10
TIM_ICInit(TIM4,&TIM_ICInitStruct);
TIM_ClearFlag(TIM4,TIM_FLAG_Update); // 清除定时器溢出更新标志位
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); // 定时器4,溢出更新,使能
TIM_SetCounter(TIM4,0); // 定时数据清零
TIM_Cmd(TIM4,ENABLE); // 定时器2使能
}
2)エンコーダデータ読み出し機能の
入口パラメータ:タイマー×
①タイマーの選択×
②エンコーダのカウント値を収集して保存
③タイマーのカウント値をクリア
④タイマーのカウント値を返す
注:TIM_GetCounterが短くなるためint(short int)なので、ここでは強制を実行する必要があります。
int Read_Speed(int TIMx)
{
int value_1;
switch(TIMx)
{
case 2:
value_1 = (short)TIM_GetCounter(TIM2); // 采集编码器的计数值并保存
TIM_SetCounter(TIM2,0); // 将定时器的计数值清零
break;
case 4:
value_1 = (short)TIM_GetCounter(TIM4); // 采集编码器的计数值并保存
TIM_SetCounter(TIM4,0); // 将定时器的计数值清零
break;
default: value_1 = 0;
}
return value_1;
}
3)タイマー割り込みサービス機能
// 定时器2中断服务函数
void TIM2_IRQHandler()
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET) // 中断标志位置1
{
TIM_ClearITPendingBit(TIM2,TIM_IT_Update); // 清楚中断标志位
}
}
// 定时器4中断服务函数
void TIM4_IRQHandler()
{
if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET) // 中断标志位置1
{
TIM_ClearITPendingBit(TIM4,TIM_IT_Update); // 清楚中断标志位
}
}
2.エンコーダー機能ヘッダーファイル-Encoder.h
#ifdef _ENCODER_H
#define _ENCODER_H
void Encoder_TIM2_Init(void); // 编码器1初始化函数
void Encoder_TIM4_Init(void); // 编码器2初始化函数
int Read_Speed(int TIMx); // 编码器速度读取函数
void TIM2_IRQHandler(void); // 定时器2中断服务函数
void TIM4_IRQHandler(void); // 定时器4中断服务函数
#endif
上記は、バランスカーシリーズの記事エンコーダーの3回目の講義で、ハードウェア構造の説明とSTM32ソフトウェアプログラミングの説明が含まれています。記事に誤りがあるか、友人が上記の内容について質問しています。コメントエリアにメッセージを残してください、Xiaozhengは私ができるだけ早くあなたに返信するのを見ます!
【バランスカー製作】(4)ジャイロMPU6050(超詳細)https://blog.csdn.net/weixin_44270218/article/details/113656398