AD |
Дата 17.6.2009, 17:50 |
|
Ну разобрался, наконец-то! Вот окончательная версия:
/// В классе. signals: void _timeout(QTime); void working_light();
/// Слот работы прожектора - вращения в обеих плоскостях void ContinueRotation::workSpotlight() { timerTicks();
int geted_angle_elev = -1, geted_azimuth = -1;
/// Перемещение вниз и вправо до упора int angle_elevation = -110 * 10, azimuth = 172 * 10; inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation); inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation); inf_to_ed_packet.low_azim = LOWBYTE(azimuth); inf_to_ed_packet.high_azim = HIGHBYTE(azimuth); if(imitTsl) imitTsl -> writeFromCtrlContinuous(); readAngleElevation(geted_angle_elev, (double)angle_elevation / 10.); readAzimuth(geted_azimuth, (double) azimuth / 10.);
timerTicks();
/// Перемещение вверх и влево до упора angle_elevation = 10 * 10; azimuth = -172 * 10; inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation); inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation); inf_to_ed_packet.low_azim = LOWBYTE(azimuth); inf_to_ed_packet.high_azim = HIGHBYTE(azimuth); if(imitTsl) imitTsl -> writeFromCtrlContinuous(); readAngleElevation(geted_angle_elev, (double)angle_elevation / 10.); readAzimuth(geted_azimuth, (double)azimuth / 10.);
timerTicks();
/// Возврат в исходное положение angle_elevation = 0; azimuth = 0; inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation); inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation); inf_to_ed_packet.low_azim = LOWBYTE(azimuth); inf_to_ed_packet.high_azim = HIGHBYTE(azimuth); if(imitTsl) imitTsl -> writeFromCtrlContinuous();
timerTicks(); }
/// Запуск потока вращения в обеих плоскостях длительный промежуток времени void ContinueRotation::run() { timerTicks(); originPosition(); readAngles();
int timer_count = 0; connect(this, SIGNAL(working_light()), SLOT(workSpotlight())); while(QTime::currentTime() <= finished_time) { timerTicks(); if(timer_count == 60) timer_count = 0; if(!timer_count) emit working_light(); msleep(1000); ++timer_count; } if(QTime::currentTime() > finished_time && _working_spotlight.isActive()) _working_spotlight.stop(); }
|
AD |
Дата 17.6.2009, 15:52 |
|
igor_bogomolov, видимо, я так не смогу сам определить, как надо сделать, можешь подсказать? Не понимаю, что за эмит надо сделать? Какой счетчик? Где? |
AD |
Дата 17.6.2009, 12:08 |
|
Цитата(igor_bogomolov @ 17.6.2009, 12:30) Высылай сигнал раз в секунду. А в обработчике, создай счетчик прореживания. Как счетчик станет равным 60, выполняй нужное действие. Это ты имел в виду? Смутно как-то я понял это, но попробую, как только исправлю баг в приложении. |
igor_bogomolov |
Дата 17.6.2009, 11:30 |
|
Цитата(AD @ 17.6.2009, 10:29) Это насколько я попытался сделать не совсем то, что мне нужно! Время должно передаваться раз в секунду (ну как секундомер, часы....). А вот выполняться действие уже раз в минуту. Подскажите, пожалуйста! Что-то действительно не получается. Не знаю, как исправить.... Высылай сигнал раз в секунду. А в обработчике, создай счетчик прореживания. Как счетчик станет равным 60, выполняй нужное действие.
Это ты имел в виду? |
AD |
Дата 17.6.2009, 9:29 |
|
Цитата(igor_bogomolov @ 15.6.2009, 23:43) Тут столько разных реализаций придумать можно. Несколько у тебя уже есть. void ContinueRotation::run() { const int pause = 1000 * 60; QDateTime startDT = QDateTime::currentDateTime();
while(finish_datatime >= startDT) { msleep(pause); startDT = QDateTime::currentDateTime(); //emit - эмитируем сигнал с периодом "pause". } }
Это насколько я попытался сделать не совсем то, что мне нужно! Время должно передаваться раз в секунду (ну как секундомер, часы....). А вот выполняться действие уже раз в минуту. Подскажите, пожалуйста! Что-то действительно не получается. Не знаю, как исправить.... |
AD |
Дата 16.6.2009, 14:23 |
|
Никак не пойму, почему таймер не срабатывает. Делаю теперь так, учтя все советы:
/// Класс потока - вращение вокруг осей заданное количество времени - длительное вращение class ContinueRotation: public QThread { Q_OBJECT
private: INFO_TO_EXTERN_DEVICE inf_to_ed_packet; ///< пакет данных внешнему устройству в режиме авто управления INFO_FROM_EXTERN_DEVICE inf_from_ed_packet; ///< пакет данных от внешнего устройства в режиме авто управления const int MAXBYTES; ///< константа максимального количества байт ImitatorTSL* imitTsl; ///< указатель на класс главного окна QTime _time; ///< счетчик времени вращения прожектора QTime starting_time, finished_time; ///< время начала и окончания отсчета QMutex mutex; ///< мьютекс блокировки работы QTimer _working_spotlight; ///< таймер работы прожектора
private: void readAzimuth(int& geted_azimuth, double limit); void readAngleElevation(int& geted_angle_elev, double limit); void originPosition(); void readAngles(); void timerTicks();
protected: virtual void run();
signals: void _timeout(QTime);
private slots: void workSpotlight();
public: ContinueRotation(QObject *parent); ~ContinueRotation(); void tsl(ImitatorTSL* im) { imitTsl = im; } ImitatorTSL* tsl() const { return imitTsl; } INFO_TO_EXTERN_DEVICE continueControl(); void fromExternalDevice(INFO_FROM_EXTERN_DEVICE& mp); void setToEDInfo(const INFO_TO_EXTERN_DEVICE& ed) { inf_to_ed_packet = ed; } void setFromEDInfo(const INFO_FROM_EXTERN_DEVICE& ed) { inf_from_ed_packet = ed; } INFO_TO_EXTERN_DEVICE toEDInfo() { return inf_to_ed_packet; } INFO_FROM_EXTERN_DEVICE fromEDInfo() { return inf_from_ed_packet; } QTime elapsedTime() const { return _time; } QTime startingTime() const { return starting_time; } void setTime(const QTime& t) { _time = t; } void setTime(const int h, const int m) { _time.setHMS(h, m, 0, 0); } void setStartingTime(const QTime& t); };
ContinueRotation::ContinueRotation(QObject *parent): QThread(parent), MAXBYTES(256), imitTsl(0), inf_to_ed_packet(INFO_TO_EXTERN_DEVICE()), inf_from_ed_packet(INFO_FROM_EXTERN_DEVICE()) {}
ContinueRotation::~ContinueRotation() {}
/// Получение азимута void ContinueRotation::readAzimuth(int& geted_azimuth, double limit) { if(!imitTsl) return; while(geted_azimuth < ((limit - 1.5) * 10) || geted_azimuth > ((limit + 1.5) * 10)) { imitTsl -> readFromCtrlPage(); geted_azimuth = VALFROMBYTES(inf_from_ed_packet.high_azim, inf_from_ed_packet.low_azim); } }
/// Получение угла места void ContinueRotation::readAngleElevation(int& geted_angle_elev, double limit) { if(!imitTsl) return; while(geted_angle_elev < ((limit - 1.5) * 10) || geted_angle_elev > ((limit + 1.5) * 10)) { imitTsl -> readFromCtrlPage(); geted_angle_elev = VALFROMBYTES(inf_from_ed_packet.high_angle_elev, inf_from_ed_packet.low_angle_elev); } }
/// Чтение углов void ContinueRotation::readAngles() { if(!imitTsl) return; int geted_azimuth, geted_angle_elev; QTime begining_time(QTime::currentTime()); do { imitTsl -> readFromCtrlPage(); geted_azimuth = VALFROMBYTES(inf_from_ed_packet.high_azim, inf_from_ed_packet.low_azim); geted_angle_elev = VALFROMBYTES(inf_from_ed_packet.high_angle_elev, inf_from_ed_packet.low_angle_elev); int secs = begining_time.secsTo(QTime::currentTime()); if(secs > 10) break; } while(geted_azimuth < 0 || geted_azimuth > 3 || geted_angle_elev < 0 || geted_angle_elev > 3); }
/// Возвращение пакета с данными от внешнего устройства в режиме автоматического управления INFO_TO_EXTERN_DEVICE ContinueRotation::continueControl() { BYTE sum = 0; BYTE* ptr = (BYTE*) (&inf_to_ed_packet); for(register int i=0; i<(sizeof(inf_to_ed_packet) - 1); ++i) sum += ptr[i]; inf_to_ed_packet.checksum = MAXBYTES - sum; return inf_to_ed_packet; }
/// Установка пакета данных от внешнего управления в автоматической режиме работы void ContinueRotation::fromExternalDevice(INFO_FROM_EXTERN_DEVICE& mp) { BYTE sum = 0; BYTE* ptr = (BYTE*) (&mp); for(register int i=0; i<(sizeof(mp) - 1); ++i) sum += ptr[i]; if((MAXBYTES - sum) == mp.checksum) inf_from_ed_packet = mp; }
/// Установка времен начала и окончания работы прожектора void ContinueRotation::setStartingTime(const QTime& t) { starting_time = t; finished_time.setHMS(starting_time.hour() + _time.hour(), starting_time.minute() + _time.minute(), starting_time.second() + _time.second(), starting_time.msec() + _time.msec()); }
/// Перемещение прожектора в исходную позицию void ContinueRotation::originPosition() { int geted_azimuth = VALFROMBYTES(inf_from_ed_packet.high_azim, inf_from_ed_packet.low_azim); int geted_angle_elev = VALFROMBYTES(inf_from_ed_packet.high_angle_elev, inf_from_ed_packet.low_angle_elev); if(geted_azimuth || geted_angle_elev) { int azimuth = 0, angle_elevation = 0; inf_to_ed_packet.low_azim = LOWBYTE(azimuth); inf_to_ed_packet.high_azim = HIGHBYTE(azimuth); inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation); inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation); if(imitTsl) imitTsl -> writeFromCtrlContinuous(); } }
/// Отсчет оставшегося времени работы прожектора void ContinueRotation::timerTicks() { int secs = QTime::currentTime().secsTo(finished_time); QTime t; t = t.addSecs(secs); int el_t = t.hour() * 60 * 60 * 1000 + t.minute() * 60 * 1000 + t.second() * 1000 + t.msec(); int _t = _time.hour() * 60 * 60 * 1000 + _time.minute() * 60 * 1000 + _time.second() * 1000 + _time.msec(); float diff = _t - el_t; mutex.lock(); _time = t; if(fabs(diff) >= 1000) emit _timeout(_time); mutex.unlock(); }
/// Слот работы прожектора - вращения в обеих плоскостях void ContinueRotation::workSpotlight() { timerTicks();
int geted_angle_elev = -1, geted_azimuth = -1;
/// Перемещение вниз и вправо до упора int angle_elevation = -110 * 10, azimuth = 172 * 10; inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation); inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation); inf_to_ed_packet.low_azim = LOWBYTE(azimuth); inf_to_ed_packet.high_azim = HIGHBYTE(azimuth); if(imitTsl) imitTsl -> writeFromCtrlContinuous(); readAngleElevation(geted_angle_elev, (double)angle_elevation / 10.); readAzimuth(geted_azimuth, (double) azimuth / 10.);
timerTicks();
/// Перемещение вверх и влево до упора angle_elevation = 10 * 10; azimuth = -172 * 10; inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation); inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation); inf_to_ed_packet.low_azim = LOWBYTE(azimuth); inf_to_ed_packet.high_azim = HIGHBYTE(azimuth); if(imitTsl) imitTsl -> writeFromCtrlContinuous(); readAngleElevation(geted_angle_elev, (double)angle_elevation / 10.); readAzimuth(geted_azimuth, (double)azimuth / 10.);
timerTicks();
/// Возврат в исходное положение angle_elevation = 0; azimuth = 0; inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation); inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation); inf_to_ed_packet.low_azim = LOWBYTE(azimuth); inf_to_ed_packet.high_azim = HIGHBYTE(azimuth); if(imitTsl) imitTsl -> writeFromCtrlContinuous();
timerTicks(); }
/// Запуск потока вращения в обеих плоскостях длительный промежуток времени void ContinueRotation::run() { timerTicks(); originPosition(); readAngles();
connect(&_working_spotlight, SIGNAL(timeout()), this, SLOT(workSpotlight())); const int working_time = 60 * 1000; _working_spotlight.start(working_time);
while(QTime::currentTime() <= finished_time) { timerTicks(); msleep(1000); } if(QTime::currentTime() > finished_time && _working_spotlight.isActive()) _working_spotlight.stop(); }
Думаю, если есть неточности в коде, то они кроются в функции run():
/// Запуск потока вращения в обеих плоскостях длительный промежуток времени void ContinueRotation::run() { timerTicks(); originPosition(); readAngles();
connect(&_working_spotlight, SIGNAL(timeout()), this, SLOT(workSpotlight())); const int working_time = 60 * 1000; _working_spotlight.start(working_time);
while(QTime::currentTime() <= finished_time) { timerTicks(); msleep(1000); } if(QTime::currentTime() > finished_time && _working_spotlight.isActive()) _working_spotlight.stop(); }
|
AD |
Дата 16.6.2009, 11:38 |
|
Цитата(igor_bogomolov @ 16.6.2009, 12:03) Тагда остается проблемма если твой прожектор должен крутиться больше суток Если конечно такое возможно Ну это не проблема! Больше чем 24 часа нельзя задать. SpinBox для задания времени ограничил специально! |
igor_bogomolov |
Дата 16.6.2009, 11:03 |
|
Цитата(Игорь) А я вот совершенно не уверен (по тому коду, что сейчас есть). Что произойдет, когда int secs станет отрицательным. t = t.addSecs(secs) останется инициализированным нулями? Я не проверял такого поведения. Т.е. я не говорил, что это плохо, а только то что, не знаю как данный код отработает. Теперь буду знать, что addSecs может принимать отрицательное значение, и коректно его отрабатывать.
Тагда остается проблемма если твой прожектор должен крутиться больше суток Если конечно такое возможно |
AD |
Дата 16.6.2009, 9:56 |
|
вызвать сигнал, который ассоциирую со слотом, выполняющим нужные мне вращения прожектора.
igor_bogomolov, прости, но я в упор не понимаю, чем плохо то, что получилось отрицательное число? вот я задал такой код:
QTime p(0, 0, 25, 100); int secs = QTime::currentTime().secsTo(p); QTime t; t = t.addSecs(secs);
В Петербурге сейчас 10:50 (округленно). Он мне и посчитал, что до окончания работы должно пройти 13 часов 10 минут. Ведь правильно? В чем проблемы? Т.е. в t занеслось вполне корректное время. Функция addSecs умеет обрабатывать заданные промежутки. Где может поломаться-то? |
Litkevich Yuriy |
Дата 16.6.2009, 8:55 |
|
Цитата(AD @ 16.6.2009, 12:44) или же в самом emit что-то сделать? а что ты в нём можешь сделать? |
Просмотр темы полностью (откроется в новом окне) |
|