位置エンコーダとしてのBLDCホールセンサの使用 – パート3

Teensy 3.5マイクロコントローラを使用した位置、方向、および距離の計算

以下は、ホールセンサの論理出力を解釈して位置、方向、速度を特定するのを支援するための情報です。論理出力はBLDCモータのモータ転流にも使用できますが、今回は説明を省略します。

このブログシリーズのパート1およびパート2を参照して、ここまでのプロジェクトの内容を確認してください。

概要

BLDCの3つのホール効果センサ出力がマイクロコントローラに供給されると、信号は3チャンネルエンコーダのように処理されます。データは、パルスカウント、回転方向、および毎分回転数(RPM)の平均を特定するために表示または使用できます。RPMは、表示値の推移を滑らかにするために平均化されます。

PJRC Teensy 3.5開発ボード

SparkFunのPJRC Teensy 3.5開発ボード(1568-1464-ND)は、ホールセンサからの3つの信号入力を処理するために十分過ぎるほどのデジタル割り込みや、はんだ入りヘッダを備えています。Teensy 3.5は、十分な数のI/Oチャンネルが追加されているため、多くの付加的なタスクを実行するのに十分強力であり、内蔵SDカードによるデータロギングに使用できます。

図1: SparkFun ElectronicsのTeensy 3.5評価ボード。(画像提供: SparkFun Electronics)

センサ出力およびPJRC Teensy 3.5のブレッドボーディング

ブレッドボード(438-1045-NDまたは類似品)を使用して、USBコネクタが右になるようにTeensy 3.5を配置し、パーティションのすぐ上の列のブレッドボードホールに上部ヘッダピンを挿入します(図2)。これにより、Teensy I/Oへのセンサ出力の接続用の領域を確保することができます。

図2: Teensy 3.5開発ボードが搭載されたブレッドボードとジャンパ接続。(画像提供: DigiKey

ソリッドジャンパワイヤ(BKWK-3-ND)を使用してすべてのブレッドボード接続を行います。5V、1A電源の正(+)のリードをブレッドボードの上部または下部の正電源レールに接続してから、負(-)のリードを上部または下部の負電源レールに接続します。ホールセンサコネクタの正(赤)および負(黒)リードをブレッドボードの正および負レールにそれぞれ接続します。それから、コネクタの3本のセンサリードをTeensy 3.5のピン2、3、4に任意の順序で接続します。

センサ出力はアクティブローです。つまり、トリガされると、出力は負の電源レールに接続されます。トリガされない場合は、センサ出力を正の電源レールにプルアップして、2つの所定の論理状態を確立する必要があります。3つの4KΩ~8KΩ抵抗器をブレッドボードに挿入して、センサ出力のプルアップとして使用します(図2)。

USBマイクロB-標準Aケーブルを接続して、Teensy 3.5をコンピュータに接続します。

ソフトウェア

Teensy 3.5は、プログラミング用のArduino統合開発環境(IDE)に対応しています。IDEおよびTeensyduinoアドオンはオンラインで入手可能です。https://www.pjrc.com/teensy/td_download.htmlにあるインストール手順に従って続行します。

下記のプログラミングコード例は、3つのハードウェア割り込みを使用して、ホールセンサ出力のあらゆる変化(立ち上がりエッジと立ち下がりエッジ)を監視します。割り込みが発生すると、Teensy 3.5の経過時間クロック、および3つの入力ピンのうち2つのピンが読み取られます。センサ値の比較により、回転方向が特定されます。次に、他の計算が実行され、パルスカウントと平均RPMが特定されます。割り込み間の時間は、現在のクロック値と前回の割り込みで保存されたクロック値を比較することにより計算されます。

void loop内のシリアルプリントで4つの値が入手可能です。コードの行をコメント化または非コメント化して、シリアルプリント機能を非アクティブ化またはアクティブ化します。次に、コードをTeensyにダウンロードし、シリアルモニタを起動してライブデータを表示します。BLDCモータを回転させ、プリントモニタで値の変化を観察します。

注: シリアルプリント機能はマイクロコントローラの速度を低下させます。I/O割り込みにより、定義上入力ピンの状態が変化するたびにシリアルプリント処理が割り込まれるため、表示値の中断やジャンプが発生します。表示機能を使用しない場合は、すべてのシリアルプリント機能をコードからコメントアウトしてください。

コピー/* BLDC Hall Sensor read and calculation program for Teensy 3.5 in the Arduino IDE (Ver.1).DigiKey*/

/***************************** Variables *********************************/

#define CW             1			// Assign a value to represent clock wise rotation
#define CCW           -1			// Assign a value to represent counter-clock wise rotation

bool HSU_Val = digitalRead(2);		// Set the U sensor value as boolean and read initial state
bool HSV_Val = digitalRead(3);		// Set the V sensor value as boolean and read initial state 
bool HSW_Val = digitalRead(4);		// Set the W sensor value as boolean and read initial state 

int direct = 1;				// Integer variable to store BLDC rotation direction
int pulseCount;				// Integer variable to store the pulse count

float startTime;				// Float variable to store the start time of the current interrupt 
float prevTime; 				// Float variable to store the start time of the previous interrupt 
float pulseTimeW; 			// Float variable to store the elapsed time between interrupts for hall sensor W 
float pulseTimeU; 			// Float variable to store the elapsed time between interrupts for hall sensor U 
float pulseTimeV; 			// Float variable to store the elapsed time between interrupts for hall sensor V 
float AvPulseTime; 			// Float variable to store the average elapsed time between all interrupts 

float PPM;				// Float variable to store calculated pulses per minute
float RPM; 				// Float variable to store calculated revolutions per minute

/***************************** Setup *********************************/

void setup()
{
// Set digital pins 2, 3 and 4 as inputs
  pinMode(2, INPUT);			
  pinMode(3, INPUT);			
  pinMode(4, INPUT);

// Set digital pins 2, 3 and 4 as interrupts that trigger on rising and falling edge changes.Call a function (i.e.HallSensorU) on change
  attachInterrupt(digitalPinToInterrupt(2), HallSensorU, CHANGE);      
  attachInterrupt(digitalPinToInterrupt(3), HallSensorV, CHANGE);
  attachInterrupt(digitalPinToInterrupt(4), HallSensorW, CHANGE);

// Initialize the print monitor and set baud rate to 9600 
  Serial.begin(9600);
}

/*************************** Main Loop ******************************/

void loop()
{
  if ((millis() - prevTime) > 600) RPM = 0;                                     			// Zero out RPM variable if wheel is stopped

  //Serial.print(HSU_Val); Serial.print(HSV_Val); Serial.println(HSW_Val);      	// Display Hall Sensor Values
  //Serial.println(direct);                                                    				// Display direction of rotation
  //Serial.println(pulseCount);                                                 			// Display the pulse count
  Serial.println(RPM);                            		      			// Display revolutions per minute
}

/************************ Interrupt Functions ***************************/

void HallSensorW()
{
  startTime = millis();						// Set startTime to current microcontroller elapsed time value
  HSW_Val = digitalRead(4);					// Read the current W hall sensor value
  HSV_Val = digitalRead(3);						// Read the current V (or U) hall sensor value 
  direct = (HSW_Val == HSV_Val) ?CW : CCW;			// Determine rotation direction (ternary if statement)
  pulseCount = pulseCount + (1 * direct);				// Add 1 to the pulse count
  pulseTimeW = startTime - prevTime;				// Calculate the current time between pulses
  AvPulseTime = ((pulseTimeW + pulseTimeU + pulseTimeV)/3);	// Calculate the average time time between pulses
  PPM = (1000 / AvPulseTime) * 60;					// Calculate the pulses per min (1000 millis in 1 second)
  RPM = PPM / 90;						// Calculate revs per minute based on 90 pulses per rev
  prevTime = startTime;						// Remember the start time for the next interrupt
}

void HallSensorV()
{
  startTime = millis();
  HSV_Val = digitalRead(3);
  HSU_Val = digitalRead(2);					// Read the current U (or W) hall sensor value 
  direct = (HSV_Val == HSU_Val) ?CW : CCW;
  pulseCount = pulseCount + (1 * direct);
  pulseTimeV = startTime - prevTime;				
  AvPulseTime = ((pulseTimeW + pulseTimeU + pulseTimeV)/3);		
  PPM = (1000 / AvPulseTime) * 60;					
  RPM = PPM / 90;
  prevTime = startTime;
}

void HallSensorU()
{
  startTime = millis();
  HSU_Val = digitalRead(2);
  HSW_Val = digitalRead(4);					// Read the current W (or V) hall sensor value		
  direct = (HSU_Val == HSW_Val) ?CW : CCW;
  pulseCount = pulseCount + (1 * direct);
  pulseTimeU = startTime - prevTime;				
  AvPulseTime = ((pulseTimeW + pulseTimeU + pulseTimeV)/3);		
  PPM = (1000 / AvPulseTime) * 60;					
  RPM = PPM / 90;
  prevTime = startTime;
}

注: プログラマは、繰り返しの割り込み機能コードを追加機能に分割して、プログラム全体を簡素化したいと思うかもしれません。しかし、そうすることにより追加機能が割り込まれ、計算中に変更される値によりデータエラーが発生してしまいます。ブレッドボーディング手順およびコードで説明したように、センサ入力の順序は回転方向に影響を与えるだけです。変数「direct」に関連したシリアルプリント行を非コメント化して、表示モニタで値を確認します。ホイールを回す方向に基づいて、値が1または-1のままになっているかを確認します。値が逸脱する場合は、対応する割り込み関数の3進コード内の「CW」および「CCW」を反転させ、出力を修正します。

まとめ

これで、正確なデータを提供できる3チャンネルの低分解能エンコーダとして機能するBLDCホールセンサの構成が完了しました。このセンサは、主要なモータ制御機能を妨げることなくナビゲーションおよびホイール位置センシングに役立ちます。一部のBLDCコントローラは、コイルと磁石の位置を特定するためにバックEMFのみを使用し、ホールセンサ出力はナビゲーションおよび位置センシング専用に確保されます。どちらにしても、センサはモータ制御にとどまらない価値をユーザーに提供します。

関連リソース:

Arduino IDE: http://www.arduino.cc/en/Main/Software

Teensyduino: https://www.pjrc.com/teensy/td_145/TeensyduinoInstall.exe

著者について

Image of Don Johanneck

DigiKeyのテクニカルコンテンツ開発者であるDon Johanneck氏は、当社に2014年から勤務しています。最近現在の役職に移動し、彼はビデオの説明と製品の内容を書くことを担当しています。Donは、DigiKey奨学金プログラムを通じて、ノースランドコミュニティ&テクニカルカレッジのエレクトロニクステクノロジ&自動化システムで応用科学の準学士号を取得しました。彼はラジオコントロールのモデリング、ヴィンテージの機械の修復、そしていじくり回すことを楽しんでいます。

More posts by Don Johanneck
 TechForum

Have questions or comments? Continue the conversation on TechForum, Digi-Key's online community and technical resource.

Visit TechForum