【问题标题】:PJRC Encoder Object as Property of Another ObjectPJRC 编码器对象作为另一个对象的属性
【发布时间】:2015-09-30 21:15:03
【问题描述】:

我借用PJRC's Encoder library 来管理步进驱动的注射泵,我正在使用Sparkfun RedBoardBigEasy Driver

我一直在模块化开发程序,首先定义较低级别的类,然后从那里开始工作。我的愿望是高级类将低级类的实例作为属性。在我目前的噩梦中,我正在构建一个注射器泵类,其中步进电机和编码器对象作为属性。

我正在按照 Arduino 教程的建议将库组织成头文件和“.cpp”文件。 Pump 类在“Pump.h”中声明如下:

#include "Arduino.h"
#include "Stepper.h"
#include "Encoder.h"

#define PUMP_TOP_SPEED 50   // ml/min               top pump speed
#define PUMP_ERROR 10       // encoder counts       acceptable error

class Pump {

    private:

        Stepper motor;          // object       stepper motor
        Encoder encoder;        // object       attached encoder
        int countPerRev;        // #            encoder counts per relovlution
        float nominalVolume;    // mL           nominal syringe volume
        float innerDiameter;    // cm           syringe inner diameter
        float shaftLead;        // cm           driveshaft threading lead distance
        float degVolume;        // mL           effective volume change per degree of rotation
        bool state;             // boolean      T = ready, F = slept

    public:

        // constructor
        Pump(const Stepper& stp, const Encoder& enc, int cpr, float vol, float diam, float lead);

        float volume();                         // returns nominalVolume
        float position();                       // returns current pump position in mL
        void hold();                            // high power state to resist back-pressure
        void relax();                           // low power state
        void pump(float vol, float rate);       // pumps the requested volume at requested rate
        void release();                         // moves the plunger all the way out so syringe can be serviced
        void set();                             // returns plunger to zero mL
};

我一直在测试的“Pump.cpp”文件中的相关代码是pump()方法的构造函数和定义,如下所示:

// constructor
Pump::Pump(const Stepper& stp, const Encoder& enc, int cpr, float vol, float diam, float lead) : motor(stp), encoder(enc), countPerRev(cpr), nominalVolume(vol), innerDiameter(diam), shaftLead(lead) {

    // calculate volume per degree
    // (diameter^2 / 4) * PI * (lead / 360) = mL / deg
    // diam * diam * lead * PI / 360 / 4 = (diam diam lead PI) / 1440
    degVolume = innerDiameter * innerDiameter * shaftLead * PI / 1440;

    // construct the encoder inside here
    /*encoder = new(Encoder(2,3));

    // set it to 0
    encoder.write(0);*/
}

// pumping function
void Pump::pump(float vol, float rate) {

    /*
        vol < 0         INFUSE
        vol > 0         WITHDRAW
    */

    if (rate > PUMP_TOP_SPEED) rate = PUMP_TOP_SPEED; // limit rate

    if (!state) hold(); // wake up the motor if it's asleep

    // make sure this doesn't push outside of the acceptable range
    if (position() + vol <= nominalVolume && position() + vol >= 0) {

        // (mL) / (mL/deg) = deg
        float degrees = vol / degVolume; // find number of degrees to turn the motor
        Serial.print("Looking to turn ");
        Serial.print(degrees, DEC);
        Serial.print(" degrees at ");

        // (count) + (deg) * (count/rev) / (deg/rev) = count
        long goal = encoder.read() + degrees * countPerRev / 360; // set target encoder reading

        // (mL/min) / (mL/deg) / (deg/rev) = RPM
        int rpm = abs(rate) / degVolume / 360; // find RPM to turn the motor
        Serial.print(rpm, DEC);
        Serial.println(" RPM in full-stepping mode");
        Serial.print("Going from encoder count ");
        Serial.print(encoder.read(), DEC);
        Serial.print(" to ");
        Serial.println(goal, DEC);

        motor.drive(degrees, 1, rpm); // drive the pump

        int err = goal - encoder.read(); // how far from the goal are we in counts?
        Serial.print("Reached encoder count ");
        Serial.println(encoder.read(), DEC);
        Serial.print("Missed by ");
        Serial.println(err, DEC);

    }
}

我一直在测试我的pump() 方法并投入一大堆Serial.print() 来尝试调试并找出正在发生的事情,从我所见,编码器对象是一个属性Pump 对象的位置不会随着轴的转动而更新,而编码器对象在 Arduino 草图中声明并传递给 Pump 构造函数。

正如您在上面看到的,我尝试在泵构造函数中初始化编码器,但是当我尝试编译时,我尝试的 2 或 3 件事都在 Arduino IDE 中引发了一堆神秘错误,留下了注释掉的部分这样你就可以看到我在尝试什么。

我觉得非常烦人的是,虽然我自己的 Stepper 对象工作正常,但 Pump 对象可以转动电机,而 Encoder 对象在 Pump 对象内不起作用。当我运行草图时:

#include <Stepper.h>
#include <Encoder.h>
#include <Pump.h>

// initialize stepper
Stepper motor(4, 5, 6, 7, 8, 9, 10, 11);

// initialize encoder
Encoder encoder(2, 3);

// initialize the pump
Pump pump(motor, encoder, 1440, 25, 2.328, 0.1);

void setup() {
  // start the Serial connection
  Serial.begin(9600);

  // set up the motor
  motor.enable();
  motor.reset();

  // pump
  pump.pump(0.25,25);

  Serial.print("Pump reading:       ");
  Serial.println(pump.position(), DEC);
  Serial.print("Encoder reading:    ");
  Serial.println(encoder.read(), DEC);

  // cool boards
  pump.relax();

}

void loop() {}

我在串行监视器中返回以下内容:

Looking to turn 211.4397277832 degrees at 58 RPM in full-stepping mode
Going from encoder count 0 to 845
Reached encoder count 0
Missed by 845
Pump reading:       0.0000000000
Encoder reading:    845

因此,encoder.read() 方法在 Pump 对象中始终返回零,但是当我在 setup() 函数中的草图末尾调用它时,它转身完全按照我的意愿转动。

感谢您的阅读。对于如何正确地将活动编码器对象传递给 Pump,或者如何在 Pump 中正确初始化编码器对象而不吓到编译器,我将不胜感激。

【问题讨论】:

    标签: c++ arduino arduino-uno


    【解决方案1】:

    事实上,关键在于初始化 Pump 对象中的编码器,正如我一直在阅读人们发布的一些关于我的问题的变体的 Arduino 板上的内容。

    我在“Pump.h”的属性声明中构建了编码器。由于我正在使用的RedBoard 是 Arduino Uno,本质上,唯一可接受的引脚是用于中断的 2 和 3。我在类的私有属性列表下使用以下行声明了编码器:

    Encoder encoder = Encoder(2,3);     //  attached encoder
    

    它现在可以完美运行。可能有一个选项可以将编码器引脚传递给 Pump 构造函数并使其灵活,但目前我需要的东西比我需要的东西更完美。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-14
      • 1970-01-01
      • 1970-01-01
      • 2013-07-03
      • 2020-06-22
      • 1970-01-01
      相关资源
      最近更新 更多