代码之家  ›  专栏  ›  技术社区  ›  AaronD

如何在qt中设置“死区开关”?

  •  0
  • AaronD  · 技术社区  · 7 年前

    我想监控一个周期性的动作,这样当它停止时我可以做一些事情。例如,切换到本地计时器以保持该操作继续,并在再次启动时切换回主源。

    我能想到的最好的理论例子是:

    #define FRAME_INTERVAL_MSEC     33  // ~30Hz
    bool periodFromUSB;
    QTimer* myTimer;
    
    void Processing::localTimeout()
    {
        //connected to myTimer->timeout();
        if (periodFromUSB)
        {
            periodFromUSB = false;
            myTimer->stop();
            myTimer->setSingleShot(false);
            myTimer->setInterval(FRAME_INTERVAL_MSEC);
            myTimer->start();
        }
    
        processDMX();
    }
    
    void Processing::newFrame()
    {
        //called periodically from my USB driver
        myTimer->stop();
        if(!periodFromUSB)
        {
            periodFromUSB = true;
            myTimer->setSingleShot(true);
            myTimer->setInterval(FRAME_INTERVAL_MSEC * 2);
        }
        myTimer->start();
    
        processDMX();
    }
    

    但无论我如何安排,当我的USB驱动程序运行时,我都会不断地调用这两个函数。(立即点击上面代码中的任何断点)

    有没有更好的方法来做一个死人?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Martin Hennings    7 年前

    如果调用start(),计时器将重置为0并重新启动当前间隔。也就是说,只要在超时之前调用newframe()槽,就永远不会调用localtimeout()。

    您的代码如下所示:

    #define FRAME_INTERVAL_MSEC     33  // ~30Hz
    bool periodFromUSB;
    QTimer* myTimer;
    
    void Processing::localTimeout()
    {
        //connected to myTimer->timeout();
        if (periodFromUSB)
        {
            periodFromUSB = false;
        }
    
        processDMX();
    }
    
    void Processing::newFrame()
    {
        //called periodically from my USB driver
        if(!periodFromUSB)
        {
            periodFromUSB = true;
        }
        myTimer->start(); // restarts current timer interval
    
        processDMX();
    
        // for debugging: display actual interval length in milliseconds:
        static qint64 start = QDateTime::currentMSecsSinceEpoch();
        static qint64 count = 0;
        ++count;
        qint64 curr = QDateTime::currentMSecsSinceEpoch();
        float msecsPerInterval = float(curr - start) / float(count);
        qDebug() << "msecs per interval: " << msecsPerInterval;
    }
    
    void Processing::init()
    {
        myTimer = new QTimer();
        connect(myTimer, &QTimer::timeout, this, &Processing::newFrame);
        myTimer->setInterval(FRAME_INTERVAL_MSEC);
        myTimer->start();
    }
    

    如果仍然调用localtimeout()插槽,则说明您的帧间隔时间太短。

    您可以使用我添加到的调试代码来检查这一点 newFrame() .

    这可能是因为:

    • USB驱动程序接收数据太少或
    • 处理 processDMX() 需要太长时间(如果 进程DX() 比帧间隔时间长,下一个插槽无法及时调用)