Link

霍尔传感器设置

步骤1.实例化 HallSensor

为了初始化霍尔传感器 ,你需要提供 A, BC (有时称为 U,VW)通道的引脚编号和电机的极对 pp 的数量。

// 霍尔传感器实例
// HallSensor(int hallA, int hallB , int hallC , int pp)
//  - hallA, hallB, hallC    - 霍尔传感器 A、 B 和 C 引脚
//  - pp                     - 极对数
HallSensor sensor = HallSensor(2, 3, 4, 11);

步骤2.配置

此外,霍尔传感器还有一个可选参数的上拉位置。霍尔传感器通常需要上拉,如果你的传感器需要上拉电阻,而你手上没有,你可以使用 Arduino pullups。则可以使用Arduino pullups的encoder.pullup 值来设置。默认值设置为Pullup::USE_EXTERN 但如果你想改用MCU的内部上拉,可以:

// 使用内部上拉
sensor.pullup = Pullup::USE_INTERN;

Arduino Pullup 20kΩ

使用内部上拉时要小心,Arduino有比较高的20kΩ左右的上拉电阻,这意味着可能较高转速下(较短的脉冲持续时间)会出现一些问题。推荐的上拉值在1kΩ到5kΩ之间。.

步骤3.中断设置

有两种使用Simple FOC库运行霍尔传感器的方法。

软件中断

使用硬件外部中断通常会得到更好和更可靠的性能,但是软件中断在较低的速度下也运行得很好,特别是在没有足够的硬件中断引脚的板上。有了这个功能基本上可以在这些板上实现FOC。

硬件外部中断

Arduino UNO有两个硬件外部中断引脚,pin 23,Arduino Mega有6个中断引脚, 2, 3, 18, 19, 202 ,而STM32如Nucleo和Bluepill可以以任意引脚为中断引脚,使实现更加容易。对于Arduino Uno,编码器通道 AB 必须连接到pins 23,以便使用硬件中断。

Simple FOC HallSensor 类已经实现了初始化和编码器A, BC 通道回调。你需要做的就是定义三个函数 doA(), doB()doC(),传感器回调函数的buffer函数sensor.handleA(), sensor.handleB()sensor.handleC().

// 中断例程初始化
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}

并将这些功能提供给霍尔传感器中断初始化功能 sensor.enableInterrupts().

// 启用霍尔编码器硬件中断
sensor.enableInterrupts(doA, doB, doC)

你可以自行命名buffer函数。将它们提供给 sensor.enableInterrupts()是很重要的。这个过程是可伸缩性和简单性之间的权衡。这可以实现一个MCU连接多个编码器。你所需要做的就是实例化新的 HallSensor类并创建新的buffer函数。例如:

//  编码器 1
HallSensor sensor1 = HallSensor(...);
void doA1(){sensor1.handleA();}
void doB1(){sensor1.handleB();}
void doC1(){sensor1.handleC();}
//  编码器 2
HallSensor sensor2 = HallSensor(...);
void doA2(){sensor2.handleA();}
void doB2(){sensor2.handleB();}
void doC2(){sensor2.handleC();}

void setup(){
...
  sensor1.init();
  sensor1.enableInterrupts(doA1,doB1,doC1);
  sensor2.init();
  sensor2.enableInterrupts(doA2,doB2,doC2);
...
}

软件中断

如果你无法使用Arduino UNO的pin 23 ,或者想使用多个编码器,你就必须使用软件中断方法。

我建议使用PciManager library.

在代码中使用这个库的步骤与 hardware interrupt非常相似。SimpleFOC Encoder 类提供所有 A, BIndex 通道的回调,但Simple FOC library 不会初始化中断。

为了使用 PCIManager,你需要将它include进你的代码中:

#include <PciManager.h>
#include <PciListenerImp.h>

下一步和前面一样,初始化新 HallSensor 实例

HallSensor sensor = HallSensor(2, 3, 4, 11);
// A、B和C中断调回buffers
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}

然后你声明监听器 PciListenerImp :

// 初始化编码器中断
PciListenerImp listenA(sensor.pinA, doA);
PciListenerImp listenB(sensor.pinB, doB);
PciListenerImp listenC(sensor.pinC, doC);

最后,在运行 encoder.init() 之后,跳过 encoder.enableInterrupts() 并调用PCIManager library来注册所有编码器通道的中断。

// 初始化编码器硬件
sensor.init();
// 初始化中断
PciManager.registerListener(&listenA);
PciManager.registerListener(&listenB);
PciManager.registerListener(&listenC);

就是这样,非常简单。如果你想要多个编码器,你只需初始化新的 Encoder实例,创建新的A, BC 回调,初始化新的监听器。下面是一个简单的例子:

// 编码器 1
HallSensor sensor1 = HallSensor(2, 3, 4, 11);
void doA1(){sensor1.handleA();}
void doB1(){sensor1.handleB();}
void doC1(){sensor1.handleC();}
PciListenerImp listenC1(sensor1.pinC, doC1);

// 编码器 2
HallSensor sensor2 = HallSensor(5, 6, 7, 11);
void doA2(){sensor2.handleA();}
void doB2(){sensor2.handleB();}
void doC2(){sensor2.handleC();}
PciListenerImp listenA2(sensor2.pinA, doA2);
PciListenerImp listenB2(sensor2.pinB, doB2);
PciListenerImp listenC2(sensor2.pinC, doC2);

void setup(){
...
  // 编码器 1
  sensor1.init();
  sensor1.enableInterrupts(doA1,doB1); // 两个硬件中断
  PciManager.registerListener(&listenC1); // 一个软件中断

  // 编码器 2
  sensor2.init();
  PciManager.registerListener(&listenA2);
  PciManager.registerListener(&listenB2);
  PciManager.registerListener(&listenC2);
...
}

步骤4.实时使用霍尔传感器

使用霍尔传感器实现在这个库有两种方法:

  • 作为FOC算法的电机位置传感器
  • 作为独立位置传感器

FOC算法的位置传感器

要利用这个库通过编码器实现FOC算法,一旦你已经初始化传感器 sensor.init()它并启用中断传感器 sensor.enableInterrupts(...) 你只需要通过执行链接它到BLDC电机:

motor.linkSensor(&sensor);

独立的传感器

获得霍尔传感器的角度和速度,你可以使用public方法:

 HallSensor{
 public:
    // 获取轴速度
    float getVelocity();
	  // 获取轴角度
    float getAngle();
}

下面是一个只使用硬件中断的快速示例:

#include <SimpleFOC.h>

// 霍尔传感器实例
// HallSensor(int hallA, int hallB , int hallC, int pp)
//  - hallA, hallB, hallC    - 霍尔传感器 A、 B 和 C 引脚
//  - pp                     - 极对数
HallSensor sensor = HallSensor(2, 3, 4, 11);

// 中断例程初始化
// 通道A和B回调
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}

void setup() {
  // 监视点
  Serial.begin(115200);

  // 检查是否需要内部上拉
  sensor.pullup = Pullup::USE_EXTERN;
  
  // 初始化磁传感器硬件
  sensor.init();
  // 启用硬件中断
  sensor.enableInterrupts(doA, doB, doC);

  Serial.println("Sensor ready");
  _delay(1000);
}

void loop() {
  // 在终端显示角度和角速度
  Serial.print(sensor.getAngle());
  Serial.print("\t");
  Serial.println(sensor.getVelocity());
}

下面是一个使用软件中断的快速示例:

#include <SimpleFOC.h>

// 霍尔传感器实例
// HallSensor(int hallA, int hallB , int hallC, int pp)
//  - hallA, hallB, hallC    - 霍尔传感器 A、 B 和 C 引脚
//  - pp                     - 极对数
HallSensor sensor = HallSensor(2, 3, 4, 11);

// 中断例程初始化
// 通道A和B回调
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}

// 初始化传感器中断
PciListenerImp listenA(sensor.pinA, doA);
PciListenerImp listenB(sensor.pinB, doB);
PciListenerImp listenC(sensor.pinC, doC);

void setup() {
  // 监视点
  Serial.begin(115200);

  // 检查是否需要内部上拉
  sensor.pullup = Pullup::USE_EXTERN;
  
  // 初始化磁传感器硬件
  sensor.init();
  // 中断初始化
  PciManager.registerListener(&listenA);
  PciManager.registerListener(&listenB);
  PciManager.registerListener(&listenC);

  Serial.println("Sensor ready");
  _delay(1000);
}

void loop() {
  // 在终端显示角度和角速度
  Serial.print(sensor.getAngle());
  Serial.print("\t");
  Serial.println(sensor.getVelocity());
}