锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Arduino SimpleFOC库-006-位置传感器

时间:2022-08-21 03:30:00 磁性传感器磁铁

该库目前支持以下类型的位置传感器

  • 编码器
    • 传感器计数ABindex引导脉冲估计位置。
    • 例子:
      • 光学:10000欧姆龙P
      • 电容:AMT103 CUI
      • 磁性:AS5047U- 使用 ABI
  • 磁传感器:
    • 用精确的磁场测量来估计位置的传感器。
      • 它们有多种不同的通信标准,如:SPI、SSI、I2C、ABI、UVW、PWM……
      • 支持通信:(发布)
        • SPI、I2C、模拟、PWM
        • UVW(使用霍尔传感器接口
        • ABI(使用编码器接口
    • 例子:AS5048A,AS5047U,AS5600
  • 霍尔传感器:
    • 传感器通过读取转子上的磁铁位置来估计转子位置。
    • 示例:49E 霍尔探测器,105 霍尔传感器

所有类型的传感器都是通用的,以支持尽可能多的版本。

1. 实例化Encoder

要初始化编码器,您需要提供编码器AB通道引脚,编码器PPR和可选的index引脚。

//  Encoder(int encA, int encB , int cpr, int index) //  - encA, encB    - encoder A and B pins //  - ppr           - impulses per rotation  (cpr=ppr*4) //  - index pin     - (optional input) Encoder encoder = Encoder(2, 3, 8192, A0);

2. 配置

当 Encoder 当类被实例化时,我们需要配置它。我们可以配置的第一个功能是启用或禁用Quadrature模果编码器在正交模式下运行,PPR每过检测每一个CHANGE信号AB- ,每次旋转的脉冲数 () 将增加四倍CPR = 4xPPR。编码器在某些应用程序中PPR很高时,Arduino 可能处理不了太多,最好不要用Quadrature模式。默认情况下,使用所有编码器Quadrature模式。如果您想启用或禁用此参数,请setup()init()调用前在 Arduino此操作在函数中执行:

// Quadrature mode enabling and disabling //  Quadrature::ON - CPR = 4xPPR  - default //  Quadrature::OFF - CPR = PPR encoder.quadrature = Quadrature::OFF;

CPR, PPR?!

PPR(每转脉冲数) - 这是编码器每转脉冲的物理数量。CPR(每转计数) - 这是编码器完全旋转后你将在计数器中拥有的数量。现在,根据您是否使用正交模式(计算脉冲的每个边缘)或不使用(仅计算上升边缘),对于相同的模式 PPR,你会有不同的 CPR。您将获得正交模式 CPR = 4xPPR,如果不使用正交模式,您将得到它 CPR=PPR

此外,编码器还有一个更重要的参数,即上拉位置。许多编码器需要上拉。如果你有一个编码器需要上拉,而你没有,你可以使用它 Arduino 上拉。这是通过改变encoder.pullup设置变量值。默认值设置为,Pullup::USE_EXTERN但是,如果你想把它改为使用,如果你想把它改为使用它 MCU,请执行以下操作:

// check if you need internal pullups // Pullup::USE_EXTERN - external pullup added  - default // Pullup::USE_INTERN - needs internal arduino pullup encoder.pullup = Pullup::USE_INTERN;

Arduino 上拉 20kΩ

使用内部上拉时要小心,Arduino 具有 20kΩ 相对较高的上拉值意味着你可能会在更高的速度(短脉冲持续时间)下遇到一些问题。推荐的上拉值介于 1kΩ 和 5kΩ 之间。

3. 中断设置编码器

你可以用两种方法 Simple FOC 库运行编码器。

  • 使用硬件外部中断
    • Arduino UNO(Atmega328) 引脚23
    • STM32板任何引脚
    • ESP32 任意引脚
  • 通过使用PciManager库使用软件引脚变化中断
    • 仅适用于 Arduino 设备(Atmga328 和 Atmage2560)

软件中断

硬件外部中断的使用通常会产生更好、更可靠的性能,但软件中断将以较低的速度工作。特别是在硬件中断引脚不够的板上,这个功能基本上可以在这些板上使用 FOC。

硬件外部中断

Arduino的UNO两个硬件外部中断引脚23,ArduinoMega有6个中断引脚,引脚231819202而STM32板如Nucleo and Bluepill所有的数字引脚都可以用作中断引脚,这使得更容易实现。 Arduino Uno,编码器通道AB必须准确连接到 pisn23,以便使用硬件中断。

简单的 FOCEncoder类已经实现了初始化以及编码器AB通道回调。您需要做的就是定义两个函数doA()and doB(),编码器回调函数的缓冲函数encoder.handleA()encoder.handleB()

// interrupt routine initialization
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}

并将这些函数提供给编码器中断 init 函数 encoder.enableInterrupts()

// enable encoder hardware interrupts
encoder.enableInterrupts(doA, doB)

您可以根据需要命名缓冲函数。将它们提供给encoder.enableInterrupts()函数很重要。此过程是可扩展性和简单性之间的权衡。这允许您将多个编码器连接到同一个 MCU。您需要做的就是实例化新Encoder类并创建新的缓冲区函数。例如:

// encoder 1
Encoder enc1 =  Encoder(...);
void doA1(){enc1.handleA();}
void doB1(){enc1.handleB();}
// encoder 2
Encoder enc2 =  Encoder(...);
void doA2(){enc2.handleA();}
void doB2(){enc2.handleB();}

void setup(){
...
  enc1.init();
  enc1.enableInterrupts(doA1,doB1);
  enc2.init();
  enc2.enableInterrupts(doA2,doB2);
...
}

索引引脚配置

为了有效地读取索引引脚,简单的 FOC 库使您能够使用与通道AB. 首先,您需要为Encoder类提供索引引脚号:

Encoder encoder = Encoder(pinA, pinB, cpr, index_pin);

如果您使用的是 Arduino Mega 和类似的 Arduino 板,并且您有 2 个以上的硬件中断,则可以将索引引脚连接到硬件中断引脚(例如 Arduino Mega 引脚21)。您的代码将如下所示:

Encoder encoder =  Encoder(2,3,600,21);
// A and B interrupt routine 
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}
void doIndex(){encoder.handleIndex();}

void setup(){
  ...
  encoder.enableInterrupts(doA,doB,doIndex);
  ...
  }

该函数enableInterrupts将为您处理所有初始化。

如果您使用 Arduino UNO 来运行此算法并且您没有足够的硬件中断引脚,您将需要使用软件中断库,例如PciManager 库。使用带索引的编码器的 Arduino UNO 代码可以是:

Encoder encoder =  Encoder(2,3,600,A0);
// A and B interrupt routine 
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}
void doIndex(){encoder.handleIndex();}

// software interrupt listener for index pin
PciListenerImp listenerIndex(encoder.index_pin, doIndex);

void setup(){
  ...
  // hardware interrupts for A and B
  encoder.enableInterrupts(doA,doB);
  // software interrupt for index
  PciManager.registerListener(&listenerIndex);
  ...
  }

如果您的应用程序使您用完硬件中断引脚AB则可以对引脚执行相同的过程。软件中断非常强大,可以产生与硬件中断相当的结果,尤其是在您别无选择的情况下。indexpin每转产生一次中断,因此并不重要,因此软件或硬件中断在性能方面不会发生太大变化。

为了更好地探索编码器功能与硬件和软件中断方法的区别,请查看示例encoder_example.inoencoder_software_interrupts_example.ino

软件引脚变化中断

如果您无法访问您的引脚23Arduino UNO,或者您想使用多个编码器,则必须使用软件中断方法。我建议使用PciManager 库。

在代码中使用这个库的步骤与硬件中断非常相似。该SimpleFOCEncoder类仍然为您提供所有的回调ABIndex通道,但简单FOC库不会初始化中断你。

为了使用该PCIManager库,您需要将其包含在您的代码中:

#include 
#include 

下一步与之前相同,您只需初始化新Encoder实例。

Encoder encoder = Encoder(10, 11, 8192);
// A and B interrupt callback buffers
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}

然后你声明监听器PciListenerImp 

// encoder interrupt init
PciListenerImp listenerA(encoder.pinA, doA);
PciListenerImp listenerB(encoder.pinB, doB);

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

// initialize encoder hardware
encoder.init();
// interrupt initialization
PciManager.registerListener(&listenerA);
PciManager.registerListener(&listenerB);

就是这样,非常简单。如果你想要多个编码器,你只需初始化新的类实例,创建新的AB回调,初始化新的监听器。这是一个快速示例:

// encoder 1
Encoder enc1 =  Encoder(9, 10, 8192);
void doA1(){enc1.handleA();}
void doB1(){enc1.handleB();}
PciListenerImp listA1(enc1.pinA, doA1);
PciListenerImp listB1(enc1.pinB, doB1);

// encoder 2
Encoder enc2 =  Encoder(13, 12, 8192);
void doA2(){enc2.handleA();}
void doB2(){enc2.handleB();}
PciListenerImp listA2(enc2.pinA, doA2);
PciListenerImp listB2(enc2.pinB, doB2);

void setup(){
...
  // encoder 1
  enc1.init();
  PciManager.registerListener(&listA1);
  PciManager.registerListener(&listB1);
  // encoder 2
  enc2.init();
  PciManager.registerListener(&listA2);
  PciManager.registerListener(&listB2);
...
}

您可以查看HMBGC_example.ino示例以查看此代码的实际效果。

索引引脚配置

在软件中断的情况下使能索引引脚非常简单。您只需要将它Encoder作为附加参数提供给类初始化。

Encoder encoder = Encoder(pinA, pinB, cpr, index_pin);

之后,您创建与AandB通道相同类型的回调缓冲函数,并使用PCIManager工具初始化和注册index通道的侦听器,如为Aand B。这是一个快速示例:示例:

// class init
Encoder encoder =  Encoder(9, 10, 8192,11);
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}
void doIndex(){encoder.handleIndex();}
// listeners init
PciListenerImp listenerA(encoder.pinA, doA);
PciListenerImp listenerB(encoder.pinB, doB);
PciListenerImp listenerIndex(encoder.index_pin, doIndex);

void setup(){
...
  // enable the hardware
  enc1.init();
  // enable interrupt
  PciManager.registerListener(&listenerA);
  PciManager.registerListener(&listenerB);
  PciManager.registerListener(&listenerIndex);
...
}

 4. 实时使用编码器

有两种方法可以使用在这个库中实现的编码器:

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

FOC算法的位置传感器

要将编码器传感器与在此库中实现的 foc 算法一起使用,在初始化encoder.init()它并启用中断后,encoder.enableInterrupts(...)您只需通过执行以下命令将其链接到 BLDC 电机:

motor.linkSensor(&encoder);

独立传感器

要在任何给定时间获取编码器角度和速度,您可以使用公共方法:

class Encoder{
 public:
    // shaft velocity getter
    float getVelocity();
	  // shaft angle getter
    float getAngle();
}
#include 

Encoder encoder = Encoder(2, 3, 8192);
// interrupt routine initialization
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}

void setup() {
  // monitoring port
  Serial.begin(115200);

  // enable/disable quadrature mode
  encoder.quadrature = Quadrature::ON;

  // check if you need internal pullups
  encoder.pullup = Pullup::USE_EXTERN;
  
  // initialize encoder hardware
  encoder.init();
  // hardware interrupt enable
  encoder.enableInterrupts(doA, doB);

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

void loop() {
  // display the angle and the angular velocity to the terminal
  Serial.print(encoder.getAngle());
  Serial.print("\t");
  Serial.println(encoder.getVelocity());
}

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章