使用 BLDC 霍尔传感器作为位置编码器 - 第 3 部分
使用 Teensy 3.5 微控制器计算位置、方向和距离
以下内容旨在帮助解释霍尔传感器的逻辑输出,以便确定位置、方向和速度。虽然该输出可用于电机换向,但这方面内容属于 BLDC 电机运行范畴,本文不予以介绍。
请参见此博客系列中的第 1 部分和第 2 部分,回顾此项目前面的内容。
概述
BLDC 中的三个霍尔效应传感器输出送入微控制器后,信号便可以像三通道编码器那样进行处理。输出数据可以显示出来,或者用来确定脉冲计数、旋转方向和平均每分钟转数 (RPM)。RPM 求取的是平均值,以便使显示的值平滑过渡。
PJRC Teensy 3.5 开发板
SparkFun 的 PJRC Teensy 3.5 开发板 (1568-1464-ND) 配有焊入式针座,并可产生足够多的数字中断,用于处理霍尔传感器的三个信号输入。由于具有大量的额外 I/O 通道,Teensy 3.5 有能力执行很多其他任务,并且可使用内置 SD 卡进行数据记录。
图 1:SparkFun Electronics 的 Teensy 3.5 评估板。(图片来源:SparkFun Electronics)
使用试验板测试传感器输出和 PJRC Teensy 3.5
使用一块试验板(438-1045-ND 或类似产品),将 Teensy 3.5 的 USB 连接器放置在右侧,并将上方针座引脚插入分隔槽上面的第一行试验板插孔中(图 2)。这样可以留出空间,以便将传感器输出连接到 Teensy I/O。
图 2:包含 Teensy 3.5 开发板和跳线连接的试验板。(图片来源:Digi-Key Electronics)
使用实芯跳线 (BKWK-3-ND) 进行试验板上的所有连线。将 5 V、1 A 电源的正极 (+) 引线连接到试验板的上方或下方正电源轨上,随后将负极 (-) 电源引线连接到上方或下方负电源轨上。将霍尔传感器连接器的正极(红色)和负极(黑色)引线,分别连接到试验板的正、负电源轨上,然后将连接器的三根传感器引线,以任意顺序连接到 Teensy 3.5 的第 2、3 和 4 号引脚。
传感器输出为有源低电平,这是指当触发时,输出连接到负电源轨;而没有触发时,需要将传感器输出上拉至正电源轨,以创建两个定义的逻辑状态。在试验板中插入三个 4 KΩ – 8 KΩ 的电阻器,即可用作传感器输出的上拉电阻器(图 2)。
使用 Micro B 转标准 A 型 USB 电缆,将 Teensy 3.5 连接到计算机。
软件
为便于编程,Teensy 3.5 与 Arduino 集成开发环境 (IDE) 相兼容。IDE 和 Teensyduino 插件可在线获取。请按照 https://www.pjrc.com/teensy/td_download.html 中的安装步骤继续操作。
下文中提供的编程示例代码使用了三个硬件中断,来监控霍尔传感器输出的任何变化(上升沿和下降沿)。一旦发生中断,将读取 Teensy 3.5 的历时时钟和三个输入引脚中的两个引脚。之后将比较传感器的值,以确定旋转方向,然后再进行其他计算来确定脉冲计数和平均 RPM。中断之间的时间间隔计算方法是:比较当前时钟值与上一次中断中存储的时钟值。
在 void loop 中,有四个值可用于串行打印。可以通过注释或取消注释代码行,来禁用或激活串行打印功能,然后将代码下载到 Teensy 并启动串行监视器,以查看实时数据。旋转 BLDC 电机,在打印监视器中观察值的变化情况。
注意:串行打印功能会减慢微控制器的运行速度。I/O 中断会导致显示的值发生停止和跳跃,因为根据定义,每次输入引脚改变状态时,串行打印过程都会发生中断。如果未使用显示功能,请确保从代码中注释掉所有串行打印功能。
复制/* BLDC Hall Sensor read and calculation program for Teensy 3.5 in the Arduino IDE (Ver.1).Digi-Key Electronics*/ /***************************** 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,具体取决于您旋转电机轮的方式。如果出现偏差,则在相应中断函数的三进制代码中调换“CW”和“CCW”,以更正输出。
总结
BLDC 霍尔传感器现在配置为三通道、低分辨率编码器,能够提供精准数据,帮助进行导航和电机轮位置检测,而不会妨碍其主要的电机控制功能。一些 BLDC 控制器只使用反电动势来确定线圈和磁铁的位置,使霍尔传感器输出仅用于导航和位置检测。但无论如何,传感器对于用户而言,不只具有电机控制功能,还有其他更多价值。
其它资源:
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