自走式光追尾カー

CdSフォトトランジスタサーボモータの上につけ、光の最も強い方向を探す。
見つけた方向に車体を回転させ、少し前進。
を繰り返し、光源に近づいていく。


#include "mbed.h"

Serial pc(USBTX, USBRX);

//-----------------------------------------------------------
// CLASS for DC moter driver TA7291P
class MoterDrive
{
public:
    MoterDrive(PinName in1, PinName in2)
    {
        mIn1 = new PwmOut(in1);
        mIn2 = new PwmOut(in2);

        mIn1->period(0.020);
        mIn2->period(0.020);
    };

    ~MoterDrive()
    {
        delete mIn1;
        delete mIn2;
    };

    // parameter degree takes the value -1.0 ^ 1.0
    // 0.0 means stop
    // positive value means go forward
    // negative value means fo backward
    void run(double degree)
    {
        if (degree < -1.0)
        degree = degree < -1.0 ? -1.0 : degree;
        degree = degree >  1.0 ?  1.0 : degree;
        
        if (0.0 < degree){ // go forward
            mIn1->write(degree);
            mIn2->write(0.0);
        }
        else if (degree < 0.0){ // go back
            degree = fabs(degree);
            mIn1->write(0.0);
            mIn2->write(degree);
        }
        else { // degree == 0.0 , then stop
            mIn1->write(0.0);
            mIn2->write(0.0);
        }
    };
        
private:
    PwmOut *mIn1, *mIn2;
};

//-----------------------------------------------------------
// CLASS for servo moter SG90
class ServoMoter
{
public:
    ServoMoter(PinName in)
    {
        servo = new PwmOut(in);

        servo->period(0.020);
    };

    ~ServoMoter()
    {
        delete servo;
    };
    
    // parameter degree takes -90 ~ 90
    // it represents axis
    // About SG90
    // duty range is 0.5ms ~ 2.4ms corresponds to -90 degree to 90 degree.
    // especially, 1.45ms means 0 degree.
    // the relation degree and duty cycle is below.
    // y = (1.9/180)*x + 1.45
    void run(int degree)
    {
        degree = degree < -90 ? -90 : degree;
        degree = degree >  90 ?  90 : degree;
        double duty = (1.9/180)*(double)degree + 1.45;
        servo->pulsewidth(duty/1000.0);
    };
        
private:
    PwmOut *servo;

};



//-----------------------------------------------------------
// CLASS for Photo register CDS MI5 series
class PhotoRegister
{
public:
    PhotoRegister(PinName in)
    {
        photo = new AnalogIn(in);
    };
    
    ~PhotoRegister()
    {
        delete photo;
    };

    uint16_t value(void)
    {
        return photo->read_u16();
    };

private:
    AnalogIn *photo;
};


//-----------------------------------------------------------
class CarControl
{
public:

    CarControl(MoterDrive *l, MoterDrive *r)
    {
        left = l;
        right = r;
    };
    
    ~CarControl(){}
    
    void stop(void)
    {
        left->run(0.0);
        right->run(0.0);
    };

    void forward(void)
    {
        left->run(degree);
        right->run(degree);
    };

    void backward(void)
    {
        left->run(degree*(-1));
        right->run(degree*(-1));
    };
    
    void rotate(int angle)
    {
        stop();
        if(angle > 0){
            left->run(degree);
            right->run(degree*(-1));
        }
        else if(angle < 0){
            left->run(degree*(-1));
            right->run(degree);
        }
        double waitTime = ((double)abs(angle)) * rotateDeg;
        pc.printf("rotate time : %f\n", waitTime);
        wait(waitTime);
        stop();
    };

private:
    MoterDrive *left, *right;
    
    static const double degree = 0.5;
    static const double rotateDeg = 0.02;
};


//-----------------------------------------------------------
class SearchLihgt
{
public:
    SearchLihgt(PhotoRegister *sensor, ServoMoter *servo)
    {
        pr = sensor;
        sm = servo;
        
        measures[0].angle = 90;
        measures[1].angle = -90;
        measures[2].angle = 75;
        measures[3].angle = -75;
        measures[4].angle = 60;
        measures[5].angle = -60;
        measures[6].angle = 45;
        measures[7].angle = -45;
        measures[8].angle = 30;
        measures[9].angle = -30;
        measures[10].angle = 15;
        measures[11].angle = -15;
        measures[12].angle = 0;
    };

    ~SearchLihgt(){}
    
    int search(void)
    {
        int index;
        int maxCandidate = 0;
        uint16_t candidateValue = 0;
        for(index = 0;index<13;index++){
            sm->run(measures[index].angle);
            wait(0.5);
            measures[index].value = pr->value();
            
            if(measures[index].value > candidateValue){
                maxCandidate = index;
                candidateValue = measures[index].value;
            }
//            pc.printf("search() %d : %d : %d\n", index, measures[index].angle, measures[index].value);

        }
//        pc.printf("Found min pos : %d\n", maxCandidate);
        
        sm->run(measures[maxCandidate].angle);
        return measures[maxCandidate].angle;
    };

    struct pair
    {
        int angle;
        uint16_t value;
    };
    
    struct pair measures[13];
        
private:
    PhotoRegister *pr;
    ServoMoter *sm;
    
};



//-----------------------------------------------------------
class Led
{
public:
    Led(PinName pin)
    {
        led = new DigitalOut(pin);
        *led = 0;
        state = 0;
    };

    void toggle(void)
    {
        if (state == 0){
            *led = 1;
            state = 1;
        }
        else{
            *led = 0;
            state = 0;
        }
    };

private:
    DigitalOut *led;
    int state;
};


//-----------------------------------------------------------
void autoDrive(void)
{
    MoterDrive *md1 = new MoterDrive(P2_1, P2_0);
    MoterDrive *md2 = new MoterDrive(P2_3, P2_2);
    ServoMoter *sm  = new ServoMoter(P2_5);
    PhotoRegister *pr = new PhotoRegister(P1_31);

    CarControl *cc = new CarControl(md1, md2);
    SearchLihgt *sl = new SearchLihgt(pr, sm);
    
    Led *led = new Led(LED1);
    
    for(int count=0;;count++){

        cc->stop();
        int angle = sl->search();
        wait(1.0);
        led->toggle();
        pc.printf("DC_moter %d : %d\n", count / 100, angle);
        cc->rotate(angle);
        wait(1.0);
        led->toggle();
        cc->forward();
        wait(2.0);
        led->toggle();
    }
}


//-----------------------------------------------------------
int main() {
    autoDrive();

    while(1){}
}