crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Чтение параметра, правка алгоритма
AD
  опции профиля:
сообщение 3.6.2009, 13:27
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Делаю имитатор прожектора. Есть следующие вещи: задается количество циклических перемещений прожектора (из крайне правого положения в крайне левое и обратно).
Алгоритм следующий:
виджет-вкладка в котором рисуются все нужные кнопки переопределен
вот так:
/// Класс отображения параметров внешних устройств управления в автоматическом режиме
class AutoControl: public QWidget, public AutoControlClass
{
    Q_OBJECT

private:
// какие-то данные
}

внутри класса есть следующие переменные:

private:
    INFO_FROM_EXTERN_DEVICE inf_from_ed_packet;    ///< пакет данных от внешнего устройства в режиме авто управления
    const int MAXBYTES;                            ///< константа максимального количества байт
    ImitatorTSL* imitTsl;                        ///< указатель на класс главного окна


Слоты запуска циклических перемещений по каждой оси и функции чтения:
private:
    void readAzimuth(int& geted_azimuth, double limit);
    void readAngleElevation(int& geted_angle_elev, double limit);

private slots:
    void startHorizontalCycles();
    void startVerticalCycles();


Далее реализация. Вот так соединяется слот с сигналом и реализация слота:
connect(btnStartHorizontal, SIGNAL(clicked()), this, SLOT(startHorizontalCycles()));

В слоте происходит следующее:
1) проверяется текущее положение прожектора
2) если он не в крайне правом положении, переводим его в это положение
3) далее запускается цикл перехода из крайне правого в крайне левое и обратно
4) счетчик соответственно уменьшается

/// Получение азимута
void AutoControl::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 AutoControl::startHorizontalCycles()
{
    int geted_azimuth = VALFROMBYTES(inf_from_ed_packet.high_azim, inf_from_ed_packet.low_azim);
    int azimuth = 172 * 10;                                ///< правый предел прожектора
    if(geted_azimuth < ((172. - 1.5) * 10) || geted_azimuth > ((172. + 1.5) * 10))
    {
        inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
        inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);        ///< перевод в этот предел прожектора
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
    }
    readAzimuth(geted_azimuth, 172.);

    /// внешний цикл по количеству перемещений
    const int number_cycles = spinHorizCycles -> value();
    for(register int i=0; i<number_cycles; ++i)
    {
        azimuth = -172 * 10;
        inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
        inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
        readAzimuth(geted_azimuth, -172.);

        azimuth = 172 * 10;
        inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
        inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
        readAzimuth(geted_azimuth, 172.);

        spinHorizCycles -> setValue(number_cycles - (i + 1));
        spinHorizCycles -> update();
    }
}

Проблема в том, что при заходе в функцию readAzimuth, там он зацикливается. Если делать все под отладчиком, то при поставке точек останова, алгоритм срабатывает.


Вот функции главного окна, которые считывают и записывают в порт:
// Получение пакета данных из поступившего куска байт со страницы управления с внешнего устройства
INFO_FROM_EXTERN_DEVICE* ImitatorTSL::packetFromPage(BYTE* buffer, unsigned int len)
{
    if(!buffer) return 0;
    if(len < INFO_FROM_EXTERN_DEVICE().length)
        return 0;
    BYTE sum = 0;
    BYTE* packet = new BYTE[INFO_FROM_EXTERN_DEVICE().length];
    for(register int i=0; i<INFO_FROM_EXTERN_DEVICE().length; ++i)
        sum += buffer[i];
    if(!sum)
        for(register int i=0; i<INFO_FROM_EXTERN_DEVICE().length; ++i)
            packet[i] = buffer[i];
    else return 0;

    return (INFO_FROM_EXTERN_DEVICE*)packet;
}

/// Циклическое чтение из COM-порта, пока не соберем пакет данных
INFO_FROM_EXTERN_DEVICE* ImitatorTSL::readCyclic()
{
    BYTE buffer[128] = {0};
    INFO_FROM_EXTERN_DEVICE* pack;
    unsigned long len_result;
    ::ReadFile(COMPort::instanceCOM() -> comHandle(), buffer, sizeof(buffer), &len_result, 0);
    if(len_result > 0 && buffer != 0)
    {
        unsigned int new_len = 0;
        BYTE* _buffer = findHead(buffer, len_result, INFO_FROM_EXTERN_DEVICE().header, new_len);
        if(_buffer == 0 || new_len == 0) return 0;
        memmove(buffer, _buffer, new_len);
        pack = packetFromPage(buffer, new_len);
        if(!pack) readCyclic();
        delete[] _buffer;    _buffer = 0;
    }
    return pack;
}

/// Чтение данных из порта для страницы контроля с внешнего управления
void ImitatorTSL::readFromCtrlPage()
{
    INFO_FROM_EXTERN_DEVICE* pack = readCyclic();
    if(!pack) return;

    if(_timerCtrlManual.isActive())
    {
        tabManualControl -> fromExternalDevice(*pack);
        tabManualControl -> checkPacket();
    }
    else if(_timerCtrlAuto.isActive())
    {
        tabAutoControl -> fromExternalDevice(*pack);
        tabAutoControl -> checkPacket();
    }
}

/** Запись в COM-порт данных со страницы управления прожектором с внешнего устройства и прием данных из порта
    Автоматический режим работы. */
void ImitatorTSL::writeFromCtrlAutoPage()
{
    readFromCtrlPage();
    unsigned long length_result;
    INFO_TO_EXTERN_DEVICE inf_ed_packet = tabAutoControl -> autoControl();
    ::WriteFile(COMPort::instanceCOM() -> comHandle(), &inf_ed_packet, sizeof(inf_ed_packet), &length_result, 0);
}


/// Установка пакета данных от внешнего управления в автоматической режиме работы
void AutoControl::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;
}


Сможете помочь решить проблему? Я уже не знаю как заставить отрабатывать так, чтобы при запуске без отладчика и точек останова, алгоритм срабатывал без зацикливания.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 3.6.2009, 20:58
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Сильно в алгоритм не вникал, вот что бросилось сразу в глаза:

/// Циклическое чтение из COM-порта, пока не соберем пакет данных
INFO_FROM_EXTERN_DEVICE* ImitatorTSL::readCyclic()
{
    BYTE buffer[128] = {0};
    INFO_FROM_EXTERN_DEVICE* pack; // !!! Указатель необходимо устанавливать в 0!!!
    unsigned long len_result;
    ::ReadFile(COMPort::instanceCOM() -> comHandle(), buffer, sizeof(buffer), &len_result, 0);

        // !!! Для чего ты вставил проверку buffer != 0 ??? Может ты хотел сделать *buffer != 0 или buffer[0] != 0?
    if(len_result > 0 && buffer != 0)
    {
        unsigned int new_len = 0;
        BYTE* _buffer = findHead(buffer, len_result, INFO_FROM_EXTERN_DEVICE().header, new_len);
        if(_buffer == 0 || new_len == 0) return 0;
        memmove(buffer, _buffer, new_len);

                // !!! Здесь не сообразил, для чего рекурсия и что хотел этим сделать?
        pack = packetFromPage(buffer, new_len);
        if(!pack) readCyclic();

        delete[] _buffer;    _buffer = 0;
    }
    return pack;
}


Отдельно эта функция проверялась, она работает?

Есть классная штука для отладки это ЛОГИ. Если поставить много qDebug в нужных местах с выводом необходимых параметров, то разобраться можно в разы быстрее. ;)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 3.6.2009, 21:18
Сообщение #3


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9656
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(AD @ 3.6.2009, 17:27) *
Если делать все под отладчиком, то при поставке точек останова, алгоритм срабатывает.
скорее всего, ты где-то не учитываешь, что данные должны накопится. Т.е. существует медленный асинхронный процесс (например тот же коммуникационный порт). И при отладке по шагам данные успевают накопиться, т.к. программа выполняется очень медленно. А в нормальном режиме она выполняется быстрее чем этот самый асинхронный процесс.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 4.6.2009, 9:14
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(BRE @ 3.6.2009, 21:58) *
Сильно в алгоритм не вникал, вот что бросилось сразу в глаза:
Отдельно эта функция проверялась, она работает?

Проверялась. Работает! На самом деле ее я все-таки и переписал. Теперь все нормально работает!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 10.7.2020, 0:22