Конференция "WinAPI" » Потоки и колучение данных с ком-порта [D7, WinXP]
 
  • Alex_C (02.02.11 17:35) [0]
    Есть задача: получение телеметрии от оборудования по ком- порту. Причем как можно чаще. Для этой цели я использую отлельный поток и в цикле


      while not Terminated...
      <посылаю комманду оборудованию на получение данных>


    От ком-порта я получаю данные и должен их обработать.
    Вопрос: как лучше реализовать, чтобы пока полученные данные от ком-порта не обработались, следующая комманда позылки запроса телеметрии не выполнялась?

    Я делаю так:
    в потоке

      while not Terminated do
      begin
         DataGet := False;
          <посылаю комманду оборудованию на получение данных>
         while not DataGet do
             Application.ProcessMessages;
         // Здесь же и идет останов от таймера
       end;



    В основной программе:

    Ф-ция, вызываемая при приеме данных из ком-порта:

        <проверяем данные на валидность, и если все верно> then
            DataGet := True
        else
            DataGet := False;



    Идея понятна. Но что то меня терзают смутные сомнения в ее правильности. :)
  • KilkennyCat © (02.02.11 17:45) [1]
    если как можно чаще, то вообще-то не надо ждать обработки данных.
    пусть они постоянно получаются в потоке и накапливаются.
    а основной поток занимается обработкой.
    в противном случае смысла в потоках как-то маловато становится.
    и еще:

    > <проверяем данные на валидность, и если все верно> then
    >         DataGet := True
    >     else
    >         DataGet := False;

    проще и красивше:
    DataGet :=  <проверяем данные на валидность>;

  • Alex_C (02.02.11 18:15) [2]

    > если как можно чаще, то вообще-то не надо ждать обработки
    > данных.


    Я тоже над этим думал, но вот в чем проблема:
    телеметрия считывается не с одной комманды, а в зависимости от оборудования от 1 до ... комманд (имеется ввиду посылка комманды оборудованию на ком порт).
    Хочется создать универсальную программу для считывания телеметрии с датчиков от разных фирм, просто указывая, с какогй марки датчика считываем данные.
    Я не смог придумать сносного алгоритма, как таким образом считывать данные?
    Вот мы постоянно посылаем комманду на получение телеметрии. Постоянно приходят с ком-потра данные. Мы их заносив в буфер - тут все понятно.
    Непонятно - как декодировать.
    Потому как есть датчика, которые имея несколько комманд получения телеметрии, в ответ шлют определенное кол-во байт информации. Вот и вся валидность...
  • KilkennyCat © (02.02.11 20:46) [3]

    > Непонятно - как декодировать.
    > Потому как есть датчика, которые имея несколько комманд
    > получения телеметрии, в ответ шлют определенное кол-во байт
    > информации. Вот и вся валидность...

    это должно быть в даташите на датчик.
  • Slym © (03.02.11 07:30) [4]
    в этом же потоке и обрабатывай, в основной поток только результат отдавай...
    Application.ProcessMessages; - в потоке ерунда

    Alex_C   (02.02.11 18:15) [2]
    просто указывая, с какогй марки датчика считываем данные

    дык жестко не прописывай строку запроса, а формируй ее на основе настроечных данных, ответ парсь также по настройкам
  • Alex_C (03.02.11 10:18) [5]

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


    Вот эта мысля у меня уже давно в голове бродит: но как?
    Данные с ком порта я получаю в основном потоке - по событию прихода данных. Считывать их в самом потоке после посылки данных в порт?
    Т.е. алгоритм потока должен выглядеть так:


       while True do
       begin
          SendCommandToComPort(<Послали комманду запроса>);
          while <пока не вышел таймаут ожидания> do
          begin
             if WaitingData > 0 then // Если есть данные в ком порту
             begin
                ReadBytes(<Считываем данные>);
                <Если данные валидны> then
                begin
                   DecodeData; <- Здесь мы декодированные данные отдаем программе
                   Break;
                end;
             end;
          end;
       end;



    Как такой вариант?
  • KilkennyCat © (03.02.11 11:12) [6]

    > Slym ©   (03.02.11 07:30) [4]
    >
    > в этом же потоке и обрабатывай, в основной поток только
    > результат отдавай...

    и получаем хрень, если время обработки превысит тз "как можно чаще".
    и вообще, смысл тогда? можно все в основном сделать, фигли там остается-то на готовые результаты.
  • Slym © (03.02.11 11:27) [7]
    KilkennyCat ©   (03.02.11 11:12) [6]
    1. Девайс шлет данные по запросу, т.е. нет непрерывного потока данных для обработки которого нужна машина реального времени
    2. Зачем просить еще когда предыдущий кусок не проглотил...
    3. Alex_C   (03.02.11 10:18) [5] пойдет
  • KilkennyCat © (03.02.11 12:34) [8]

    > Slym ©   (03.02.11 11:27) [7]

    1. в этом случае да, но в тз висит "как можно чаще". т.е. приближаемся к непрерывному потоку.
    2. опять же, исходя из тз. может, датчик меряет температуру, и нужна полная картина в динамике, тогда, проглотил или нет, данные нужно получить.

    в противном случае, повторюсь, нет нужды в потоке. отправили запрос, получили данные, обработали, и заново... какой смысл в потоке?
  • Slym © (03.02.11 12:41) [9]
    KilkennyCat ©   (03.02.11 12:34) [8]
    какой смысл в потоке?

    не подвешивать гуй
  • KilkennyCat © (03.02.11 13:38) [10]

    >  Slym ©   (03.02.11 12:41) [9]

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

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

    чтобы упростить работу себе, я тупо сделал главную прогу, которая тупо считывала с файла данные, обрабатывала и т.д. Потом смотрела снова файл...
    так я определил для себя промежуточный формат данных.
    по получении датчика, я написал небольшого резидента, который опрашивал датчик и скидывал в тот самый файл... в уже нужном мне формате.
    переход на любой другой датчик не вызывал проблем никаких, не требовал пересбора всего проекта.
  • GreyWolf © (03.02.11 21:35) [11]
    1. ProcessMessages не нужно вызывать не в основном потоке
    2. Можно предложить вариант с двумя дополнительными потоками: один занимается опросом датчиков и получением ответов, пересылает ответы второму доп. потоку, тот их обрабатывает и пересылает результат в главный поток. Так, как мне кажется, будет наибольшая скорость обработки и удобство чтения кода (разделение кода, отвечающего за разные вещи, между разными потоками (классами))
  • Alex_C (03.02.11 21:41) [12]

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


    В общем сегодня реализовал этот вариант. Результат - просто класс :) Алгоритм - как я описывал выше (естественно он получился куда как сложнее, но идея ясна.)
    Совет для тех, у кого такая же задача как и у меня - делать так, как предложено. По ходу это единственно верный путь. Перепробовал и остальные - результат куда как хуже.
  • Alex_C (03.02.11 21:44) [13]

    > Можно предложить вариант с двумя дополнительными потоками:
    >  один занимается опросом датчиков и получением ответов,
    > пересылает ответы второму доп. потоку, тот их обрабатывает
    > и пересылает результат в главный поток.


    Не будет. Сам посуди - нам все равно прийдется эти два потока сихронизировать, чтоб они друг от друга не "убежали". Это и лишнии проблемы, и скорости нет.
    А с одним потоком скорость практически получается в режиме реально времени. Сегодня опробовал!
  • KilkennyCat © (03.02.11 22:39) [14]
    большая ошибка. не будет тут реального времени, никоим образом, когда и получение и обработка в одном потоке. более того, есть риск потери информации.

    > По ходу это единственно верный путь. Перепробовал и остальные
    > - результат куда как хуже.

    просто не умеешь.

    > Сам посуди - нам все равно прийдется эти два потока сихронизировать,
    >  чтоб они друг от друга не "убежали". Это и лишнии проблемы,
    >  и скорости нет.

    не понимаешь идеологии. Хотя GreyWolf предложил классический общий вариант, именно с такого и надо было начинать, усложнение или упрощение уже зависит от тз.
  • GreyWolf © (03.02.11 23:16) [15]

    > Alex_C   (03.02.11 21:44) [13]

    Будет:) Передача сообщения другому потоку делается асинхронно. То есть примерно так:
    В доп. потоке 1, работающем с COM портом:

    while true do
    begin
     1.1. Опросить_следующий_нуждающийся_в_опросе_датчик
     1.2. Выделить память под структуру, содержащую результат опроса, и скопировать туда данные, полученные в буфер в п.1.1
     1.3. Асинхронно отправить укзатель на эту структуру в доп. поток 2
    end;


    В доп. потоке 2, обрабатывающем данные опроса


    while true do
    begin
     2.1. Получить указатель на следующие в очереди данные, отправленные в 1.3
     2.2. Обработать эти данные
     2.3. Асинхронно отправить результат в главный поток
     2.4 Освободить память, выделенную в 1.2
    end;



    Тогда если есть четыре датчика A, B, C, D, у которых период опроса у каждого - 50 мс, а период обработки - 10, 20, 100, 60 мс соответственно, то результирующий период опроса будет составлять максимум из периода опроса и периода обработки, в этом случае - Max(200, 190) = 200 мс.

    Если это все делать в одном потоке и не заморачиваться на асинхронных событиях приема и передачи данных, (и соотв. разбивки алгоритма обработки на машину состояний с периодическим выходом из этого алгоритма для проверки возникновения событиий приема и передачи данных), то результирующий период опроса будет равен _сумме_ периодов опроса и обработки, т.е. в этом случае 390 мс.

    А учитывая современный тренд в сторону все большего кол-ва ядер, можно и дальше оптимизировать под несколько потоков обработки данных.
  • Германн © (04.02.11 06:44) [16]

    >
    > Alex_C   (02.02.11 17:35)
    >
    > Есть задача: получение телеметрии от оборудования по ком-
    >  порту. Причем как можно чаще. Для этой цели я использую
    > отлельный поток и в цикле
    >
    >
    >   while not Terminated...
    >   <посылаю комманду оборудованию на получение данных>

    Бред.
    В данной задаче пригоден только асинхронный способ общения с внешним железом. А значит никакие доппотоки не нужны и даже мешают.
    Хотя, чисто теоретически, если грамотно разделить "общение" и "анализ", то можно достичь максимально возможной частоты получения информации от внешнего устройства.
  • Вариант (04.02.11 09:05) [17]

    > Германн ©   (04.02.11 06:44) [16]

    Бред.

    > В данной задаче пригоден только асинхронный способ общения
    > с внешним железом. А значит никакие доппотоки не нужны и
    > даже мешают.


    Бред - это когда бред пишешь без аргументов. Чем тебе мешает доп. поток?
    Можно ли организовать работу в основном потоке с COM портом?  Да можно, , но намного ли это проще? Выигрыш от этого один - нет необходимости в синхронизации между потоками. А хорошо ли это масштабируется? Что будет если портов будет больше чем 1,2, 3 или 10 или еще больше?
    Рекомендую почитать Рихтер Дж., Кларк Д.Д. - "Программирование серверных приложений"  Главу 2 "Ввод-вывод и межпотоковое
    взаимодействие "
  • Grz (20.01.16 02:50) [18]
    Удалено модератором
  • Grz (20.01.16 02:54) [19]
    Удалено модератором
  • кгшзх © (20.01.16 13:51) [20]
    Чем тебе мешает доп. поток?

    тем что если чтение данных будет асинхронное, то в доппотоке придется крутить тупейший цикел ожидания, который ничего не будет делать.
  • Nouser © (20.01.16 14:13) [21]

    > если чтение данных будет асинхронное

    а это как?
  • Игорь Шевченко © (20.01.16 17:55) [22]
    кгшзх ©   (20.01.16 13:51) [20]

    На дату ветки посмотри :)
 
Конференция "WinAPI" » Потоки и колучение данных с ком-порта [D7, WinXP]
Есть новые Нет новых   [118234   +3][b:0][p:0.002]