2015-05-20 2 views
3

Я пишу программное обеспечение в Qt/C++, которое связывается через последовательный порт с ардуино и другими электронными устройствами.Лучший способ синхронизации событий в Qt

мне нужно, чтобы начать последовательность событий, которые вызывают разные слот с разными сроками, как это:

  • Пуск двигателя 1 в течение 20 секунд
  • Через 10 секунд Пуск двигателя 2
  • Остановка двигателя 1
  • Изменение двигателя 1 скорость
  • Пуск двигателя 1 Для 30 второго

Я пробовал с QTimer :: singleShot, но он работает только с слотом без параметров, и мне нужно время от времени устанавливать параметры, такие как скорость двигателя.

Прямо сейчас я использую функцию задержки, которая противостоит currentTime do dieTime, но сложно отслеживать синхронизацию всех устройств.

Какое оптимальное решение? Предложения?

+0

Если статическая функция QTimer :: singleShot не работает для вас, то, что касается использования экземпляров QTimer, используется однократное использование (http://doc.qt.io/qt-5/qtimer.html#singleShot -prop) – TheDarkKnight

+2

'QTimer' действительно лучшее решение. И вы можете передавать параносы через поля класса. – Amartel

+0

@Amartel, я пытаюсь передать параметры через поля класса, но моя проблема заключается в том, как передавать параметры по времени. Если, например, я хочу установить двигатель на скорость x, запустить двигатель на 30 секунд, остановить двигатель, установить его на скорость y, а затем начать снова, как я могу обновить параметры в соответствии с синхронизацией? Я думаю о настройке всех параметров, но я не думаю, что это хорошее решение. – nicodio

ответ

4

Вы можете использовать статическую функцию одиночного выстрела QTimer, если вы используете overloaded method, который принимает Functor (объект функции). Это позволит вам фиксировать требуемые переменные; какой двигатель, скорость, действие и т. д. Если вы не знакомы с Функторами, вы можете прочитать о них here.

В качестве альтернативы, поскольку вопрос не содержит примеров кода, предположим, что вы уже написали функции для запуска и остановки двигателей. Для более прямого метода, with C++11, вы могли бы сделать что-то вроде этого:

StartMotor(1); 

// Stop in 20 seconds 
QTimer* p1 = new QTimer; 
connect(p1, &QTimer::timeout, [=]{ 
    StopMotor(1); 
    p1->deleteLater(); // clean up 
}); 
p1->start(1000 * 20); // trigger in 20 seconds 

// After 10 seconds, start motor 2 

QTimer* p2 = new QTimer; 
connect(p2, &QTimer::timeout, [=]{ 
    StartMotor(2); 

    // And Stop Motor 1 
    StopMotor(1); 

    p2->deleteLater(); // clean up 
}); 
p2->start(1000 * 10); // trigger in 10 seconds 

... И так далее для каждого таймерного действия.

+0

Использование лямбда в качестве слота/обратного вызова выглядит очень элегантно. Нет необходимости определять каждый таймер. QTimer * p; и p = новый QTimer; каждый раз тоже сделаю. –

+0

@ValentinHeinitz, абсолютно, хотя я определил отдельные таймеры для ясности здесь. – TheDarkKnight

+0

Я принял этот ответ, потому что это то, что мне нужно было сделать прямо сейчас.Единственное, что с большой инструкцией код может быть немного трудным для чтения, но моя работа - написать все, что я могу. Спасибо. – nicodio

3

Реализуйте класс для двигателя т.д .:

class Motor:public QObject 
{ 
    Q_OBJECT 
    public slots: 
    void start(); 
    void start(int ms); //this one starts QTimer::singleShot and calls stop 
    void stop(); 
}; 

Я рекомендовал бы проверить QStateMachine Framework. Когда задачи будут усложняться, вам лучше использовать FSM, чем спагетти вызовов сигнальных слотов.

В моем текущем проекте я построил FSM на основе QStateMachine, где определение FSM выполняется в DSL (конкретном домене).

+0

В этом решении, если из основного класса я делаю что-то вроде этого: motor1-> start (10); motor1-> SetSpeed ​​(100); motor1-> начать (20); Он принимает только первую команду, потому что, когда я вызываю второй и третий, первый все еще выполняется. Должен ли я создавать какую-то очередь для того, чтобы все команды отправлялись? – nicodio

+1

зависит от того, что вы хотите. Если команды должны выполняться один за другим асинхронно, да, очередность - единственное решение. Очередь или строки как команды и интерпретировать их до окончания предыдущей команды или использовать шаблон команды - инкапсулировать команду в классе. –

+0

Спасибо. Я принял другой ответ, потому что это более специфично для моего вопроса. Но я также буду использовать ваши предложения, чтобы написать лучший и полезный код. – nicodio

Смежные вопросы