2015-09-30 120 views
0

我借用PJRC's Encoder library来管理步进驱动注射泵我运行的是Sparkfun RedBoardBigEasy DriverPJRC编码器对象作为另一个对象的属性

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

我正按照Arduino教程推荐的将库组织成头文件和'.cpp'文件。该泵类被声明为“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()尝试调试和弄清是怎么从我所看到的发生和编码器对象,它是一个泵对象的属性没有将其位置更新为轴而编码器对象在Arduino草图中声明并传递给Pump构造函数。

正如你上面看到的,我尝试初始化泵构造函数中的编码器,但是我尝试过的2或3件事情在我尝试编译时在Arduino IDE中抛出了一系列神秘错误,留下了注释所以你可以看到我正在尝试的东西。

我觉得非常恼人的是,虽然我自己的步进器对象工作正常,泵对象可以打开电机,但编码器对象不会在泵对象内运行。当我运行的草图:

#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()总是返回零水泵的对象,但是当我把它叫做末我的素描在setup()函数中变成了我完全按照我想要的方式旋转。

谢谢您的阅读。我很感激有关如何正确传递一个活动的Encoder对象到Pump的指导,或者如何正确地初始化Pump中的一个Encoder对象而不会吓坏编译器。

回答

0

事实上,关键在于初始化Pump对象中的编码器,因为我一直在阅读人们发布的Arduino板卡上的某些版本的问题。

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

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

它现在可以正常工作。有可能选择将编码器引脚传递给Pump构造函数,并使其具有灵活性,但是目前我需要的东西比我需要的东西更完美。

相关问题