위치 인코더로 BLDC 홀 센서 사용하기 3부
Teensy 3.5 마이크로 컨트롤러를 사용하여 위치, 방향 및 거리 계산
다음 정보는 위치, 방향, 속도를 결정하기 위한 목적으로 홀 센서 논리 출력을 해석하는 데 도움을 주기 위한 것입니다. 이 출력은 모터 정류에 사용될 수 있지만 이 글에서는 BLDC 모터 작동의 측면에서 설명하지 않습니다.
이 프로젝트의 이전 단계를 보려면 이 블로그 시리즈의 1부 및 2부를 참조하십시오.
개요
BLDC의 홀 효과 센서 출력 세 개가 마이크로 컨트롤러에 공급되면 3채널 인코더처럼 신호를 처리할 수 있습니다. 데이터는 펄스 수, 회전 방향 및 분당 평균 회전 수(RPM)를 결정하기 위해 표시되거나 사용될 수 있습니다. RPM은 값의 변화가 매끄럽게 표시되도록 평균값으로 계산됩니다.
PJRC Teensy 3.5 개발 기판
SparkFun의 PJRC Teensy 3.5 개발 기판(1568-1464-ND)에는 홀 센서의 세 신호 입력을 처리할 수 있는 디지털 인터럽트가 있으며 납땜 헤더가 함께 제공됩니다. 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 전원 공급 장치의 양극(+) 리드를 브레드 기판의 상단 또는 하단 전력 양극 레일에 연결합니다. 그런 다음, 음극(-) 공급 리드를 상단 또는 하단 음극 전력 레일에 연결합니다. 홀 센서 커넥터의 양극(빨간색) 및 음극(검은색) 리드를 브레드 기판의 양극 및 음극 레일에 각각 연결합니다. 그런 다음 커넥터의 세 센서 리드를 Teensy 3.5의 핀 2, 3 및 4에 순서 상관없이 연결합니다.
센서 출력은 Low 활성이므로, 트리거될 경우 출력이 음극 전력 레일에 연결됩니다. 트리거되지 않을 경우 센서 출력을 양극 전력 레일로 풀업하여 두 개의 정의된 논리 상태를 만들어야 합니다. 세 개의 4KΩ - 8KΩ 저항기를 센서 출력의 풀업으로 사용될 브레드 기판에 삽입합니다(그림 2).
USB micro B - 표준 A 케이블을 사용하여 Teensy 3.5를 컴퓨터에 연결합니다.
소프트웨어
Teensy 3.5는 프로그래밍 목적으로 Arduino IDE(Integrated Development Environment)와 호환됩니다. IDE 및 Teensyduino 애드온은 온라인에서 사용 가능합니다. 계속하려면 https://www.pjrc.com/teensy/td_download.html의 설치 절차를 수행하십시오.
아래 제공된 프로그래밍 예제 코드에서는 세 개의 하드웨어 인터럽트를 사용하여 홀 센서 출력의 변화(상승 및 하강 에지)를 모니터합니다. 인터럽트가 발생하면 Teensy 3.5 및 세 입력 핀 중 두 개의 경과 시간 클록을 읽습니다. 센서 값을 비교하여 회전 방향을 결정합니다. 그런 다음 다른 계산을 수행하여 펄스 수와 평균 RPM을 결정합니다. 인터럽트 간 시간은 현재 클록 값을 이전 인터럽트에서 저장된 클록 값에 비교하여 계산됩니다.
네 개의 값은 비어 있는 루프 내 직렬 인쇄에 사용 가능합니다. 코드 라인을 주석 처리하거나 주석 해제하여 직렬 인쇄 기능을 비활성화 또는 활성화한 다음 코드를 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”를 전환하여 출력을 수정하십시오.
요약
이제 BLDC 홀 센서는 기본 모터 제어 기능을 방해하지 않고 탐색 및 휠 위치 감지에 도움이 되는 정확한 데이터를 제공할 수 있는 3채널, 저분해능, 인코더로 구성되었습니다. 일부 BLDC 컨트롤러에서는 후면 EMF만 사용하여 코일 및 자석 위치를 결정하고 홀 센서 출력은 탐색 및 위치 감지에만 사용합니다. 어떤 방법이든지 센서는 단순한 모터 제어 이상의 기능적인 가치를 제공합니다.
추가 리소스:
Arduino IDE: http://www.arduino.cc/en/Main/Software
Teensyduino: https://www.pjrc.com/teensy/td_145/TeensyduinoInstall.exe
Have questions or comments? Continue the conversation on TechForum, Digi-Key's online community and technical resource.
Visit TechForum


