完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
该库目前支持以下类型的位置传感器:
1. 实例化Encoder类 要初始化编码器,您需要提供编码器A和B通道引脚、编码器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信号A和B- ,其每次旋转的脉冲数 ( ) 将增加四倍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 库运行编码器。
使用硬件外部中断通常会产生更好和更可靠的性能,但软件中断对于较低的速度会很好地工作。特别是在没有足够硬件中断引脚的板上,具有此功能基本上可以在这些板上启用 FOC。 硬件外部中断 Arduino的UNO有两个硬件外部中断引脚,为引脚2和3,Arduino Mega有6个中断引脚,引脚2,3,18,19,20和2而STM32板如Nucleo and Bluepill可以使用所有的数字引脚作为中断引脚,这使得实现更加容易。对于 Arduino Uno,编码器通道A和B必须准确连接到 pisn2和3,以便使用硬件中断。 简单的 FOCEncoder类已经实现了初始化以及编码器A和B通道回调。您需要做的就是定义两个函数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 库使您能够使用与通道A和B. 首先,您需要为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); ... } 如果您的应用程序使您用完硬件中断引脚A,B则可以对引脚执行相同的过程。软件中断非常强大,可以产生与硬件中断相当的结果,尤其是在您别无选择的情况下。indexpin每转产生一次中断,因此并不重要,因此软件或硬件中断在性能方面不会发生太大变化。 为了更好地探索编码器功能与硬件和软件中断方法的区别,请查看示例encoder_example.ino和encoder_software_interrupts_example.ino。 软件引脚变化中断 如果您无法访问您的引脚2和3Arduino UNO,或者您想使用多个编码器,则必须使用软件中断方法。我建议使用PciManager 库。 在代码中使用这个库的步骤与硬件中断非常相似。该SimpleFOCEncoder类仍然为您提供所有的回调A,B和Index通道,但简单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); 就是这样,非常简单。如果你想要多个编码器,你只需初始化新的类实例,创建新的A和B回调,初始化新的监听器。这是一个快速示例: // 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 算法一起使用,在初始化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()); } |
|
|
|
只有小组成员才能发言,加入小组>>
3278 浏览 9 评论
2955 浏览 16 评论
3455 浏览 1 评论
8987 浏览 16 评论
4050 浏览 18 评论
1102浏览 3评论
570浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
568浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2301浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1856浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-21 22:45 , Processed in 1.138525 second(s), Total 82, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号