第二周作业、停车场门禁控制系统状态机

状态机设计分析

根据要求,可以分为四个状态,令起落杆上限位传感器为TopSensor,下限位传感器为BottomSensor,汽车入闸传感器为CarIn,汽车出闸传感器为CarOut,则有

  • S1:Idle
    • 进入时设置通行灯为红灯,电机停止。
    • 当汽车入闸传感器CarIn变为True时,转移到状态S2
  • S2: BarrierRising
    • 进入时设置电机正转,保持通行灯状态
    • 当上限位传感器TopSensor变为True时,转移到状态S3
  • S3: CarDriving
    • 进入时设置通行灯为绿灯,电机停止
    • 当汽车出闸传感器CarOut变为True时,转移到状态S4
  • S4:BarrierFalling
    • 进入时设置电机反转,保持通行灯状态
    • 当下限位传感器BottomSensor变为True时,转移到状态S1

根据以上设计,建立模型。

状态机建模

状态机模型

运行示例

模拟运行

模型文件

Github仓库

C++ 实现

以Simulink Stateflow的模块为模板,作出以下设计。

状态机抽象

首先,设计三个类:一个用于表示状态,可以通过一个函数,检查绑定的触发条件,并返回符合条件的下一状态。类声明如下:

class State {
public:
    std::string Name;
    State(std::string);
    State* Trigger(void);
    void Add(std::function<bool(void)> fn, State* NextState);
    void SetEntry(void(*fn)(void));
    void Entry(void);

private:
    std::vector<std::function<bool(void)>> Condition;
    std::vector<State*> NextState;
    void (*FnEntry)(void);
};

class Machine {
public:
    Machine(State *InitState);
    void SetState(State *state);
    State *Curr;
    void Trigger(void);
};

一个类为布尔型传感器类,继承于传感器类模版。声明分别为:

template <typename T>
class TSensor {
protected:
    T value;

public:
    TSensor(){}
    TSensor(T value) {
        this->Set(value);
    }
    void Set(T value) {
        this->value = value;
    }
    T Get(void) {
        return this->value;
    }
};

class BoolSensor: public TSensor<bool> {
public:
    BoolSensor(bool value);
    bool IsTrue(void);
    bool IsFalse(void);
};

另一个类则为模拟机,模拟触发状态检查,并维护状态机的当前状态,同时在改变状态时能够触发相应的进入操作。类声明如下:

class Machine {
public:
    Machine(State *InitState);
    void SetState(State *state);
    State *Curr;
    void Trigger(void);
};

组装模型


// 定义传感器
    // 测试模型时所有传感器默认值均设为true,正常情况应默认为false
    BoolSensor CarIn{true};
    BoolSensor CarOut{true};
    BoolSensor TopSensor{true};
    BoolSensor BottomSensor{true};

// 定义状态
    State S1{"Idle"};
    State S2{"Barrier Rising"};
    State S3{"Car Driving"};
    State S4{"Barrier Falling"};

// 设置状态转移及入口动作
    S1.SetEntry(&S1_Entry);
    S1.Add(std::bind(&BoolSensor::IsTrue, &CarIn), &S2);

    S2.SetEntry(&S2_Entry);
    S2.Add(std::bind(&BoolSensor::IsTrue, &TopSensor), &S3);

    S3.SetEntry(&S3_Entry);
    S3.Add(std::bind(&BoolSensor::IsTrue, &CarOut), &S4);

    S4.SetEntry(&S4_Entry);
    S4.Add(std::bind(&BoolSensor::IsTrue, &BottomSensor), &S1);

其中,SetEntry为设置状态机的进入状态时的触发动作。

初始化并模拟运行

初始状态为S1,即Idle状态。

    Machine simulate{&S1};

    while (1) {
        simulate.Trigger();
        sleep(1);
    }

运行效果

Set State <Idle>
Light: Red
Motor: Stop
Switch From <Idle> to <Barrier Rising>
Light: Red
Motor: Forward Revolute
Switch From <Barrier Rising> to <Car Driving>
Light: Green
Motor: Stop
Switch From <Car Driving> to <Barrier Falling>
Light: Green
Motor: Backward Revolute
Switch From <Barrier Falling> to <Idle>
Light: Red
Motor: Stop
...

源代码

Github仓库

References

[1] [https://cn.mathworks.com/help/stateflow/ug/programming-your-chart-with-matlab-syntax.html]

原文地址:https://www.cnblogs.com/passerby233/p/rtcsd_w2_design_parking_lot_barrier_control_system.html