purebasic.info

PureBasic forum
Текущее время: Ср окт 17, 2018 10:13 pm

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 45 ]  На страницу Пред.  1, 2, 3  След.
Автор Сообщение
СообщениеДобавлено: Пт июн 22, 2018 7:42 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 49
Благодарил (а): 35 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Всем привет!
У меня такая проблема.
Есть многопоточное приложение, которое параллельно опрашивает несколько приборов через последовательные порты (СОМ-порты). Опрос реализован в безопасных потоках. Приложение юникодное, создано в PB 5.60 на Windows 7 и работает на Windows XP SP3. Опрос происходит не стабильно: чем меньше период опроса, тем больше ошибок. Если опрашивать с периодом порядка 100 мс, то ошибок практически нет.
Раньше я писал эту программу на PB 5.0 в Windows 7, приложение было простое (НЕ юникодное), все хорошо работало на Windows XP. Периоды опроса при этом были порядка 10 мс.

Код компилируется нормально.
В чем может быть дело? Может в Windows XP и юникодном приложении?


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пт июн 22, 2018 7:48 pm 
Не в сети
МОДЕРАТОР

Зарегистрирован: Вт дек 05, 2006 8:46 am
Сообщений: 6384
Благодарил (а): 20 раз.
Поблагодарили: 198 раз.
Пункты репутации: 48
fil@tov писал(а):
все хорошо работало

Не могу не полюбопытствовать, а что сподвигло переписать приложение?

_________________
read-only


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб июн 23, 2018 5:18 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 49
Благодарил (а): 35 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
kvitaliy писал(а):
Не могу не полюбопытствовать, а что сподвигло переписать приложение?


Да вот, решил перейти на более новую версию PB 5.60. В последних версиях PB можно создавать только юникодные приложения, если я правильно понимаю...


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб июн 23, 2018 7:57 pm 
Не в сети
МОДЕРАТОР

Зарегистрирован: Вт дек 05, 2006 8:46 am
Сообщений: 6384
Благодарил (а): 20 раз.
Поблагодарили: 198 раз.
Пункты репутации: 48
fil@tov писал(а):
Да вот, решил перейти на более новую версию PB 5.60.

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

fil@tov писал(а):
В последних версиях PB можно создавать только юникодные приложения, если я правильно понимаю...

Это да.

_________________
read-only


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Вт июн 26, 2018 8:18 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 49
Благодарил (а): 35 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Похоже понял в чем дело!
Все дело в проверке входного буфера порта при опросе с помощью ф-и AvailableSerialPortInput(#SerialPort).
Алгоритм опроса одного прибора такой:
1) отправляю запрос прибору
2) делаю паузу после запроса
3) проверяю входной буфер порта на наличие данных: AvailableSerialPortInput(#SerialPort)
4) читаю данные из порта в память: ReadSerialPortData(#SerialPort , *Buffer , Length)
5) обработка данных

Если выполнять пункт 3 с помощью AvailableSerialPortInput(#SerialPort), то нужно делать паузу после запроса порядка 100 мс. При паузе порядка 10 мс данные в порт не поступают (ф-я AvailableSerialPortInput возвращает ноль). Почему?

P.S.
Приборов несколько, задействовано несколько последовательных портов. Опрос реализован в разных потоках.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пн окт 01, 2018 3:17 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 49
Благодарил (а): 35 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Всем привет!
У меня такой вопрос: поддерживает ли ф-я AvailableSerialPortInput(#SerialPort) многопоточность?

p.s. проблему описывал в предыдущем сообщении


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пн окт 01, 2018 3:44 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11299
Благодарил (а): 4 раз.
Поблагодарили: 436 раз.
Да поддерживает. Вот к примеру программа использующая AvailableSerialPortInput. http://purebasic.mybb.ru/viewtopic.php?id=475
Работает в потоке и сбоев не наблюдается. Надеюсь в настройках компилятора включена поддержка многопоточности?

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пн окт 01, 2018 7:29 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 49
Благодарил (а): 35 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Пётр писал(а):
Да поддерживает. Вот к примеру программа использующая AvailableSerialPortInput. http://purebasic.mybb.ru/viewtopic.php?id=475
Работает в потоке и сбоев не наблюдается. Надеюсь в настройках компилятора включена поддержка многопоточности?


Интересный пример, спасибо!
Да, в настройках компилятора включена поддержка многопоточности.
У меня 3 потока (работают с 3-мя СОМ-портами). В каждом проверяю входной буфер соответствующего порта функцией AvailableSerialPortInput, наблюдаю сбои. Убираю из потоков проверку входного буфера - все работает без сбоев.
Не пойму в чем может быть дело?


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пн окт 01, 2018 8:37 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11299
Благодарил (а): 4 раз.
Поблагодарили: 436 раз.
Аналог AvailableSerialPortInput.
Код:
1
2
3
4
5
6
7
8
9
10
Procedure ComInBytes(hCOM)
  Protected Status.COMSTAT
  Protected x=0, r=0
 
  If ClearCommError_(hCOM, @x, @Status)
    r = Status\cbInQue
  EndIf
 
  ProcedureReturn r
EndProcedure

hCOM можно получить функцией SerialPortID. Желательно это делать раз после открытия порта. Если по прежнему будет работать с ошибками, значит дело не в AvailableSerialPortInput.

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Вт окт 02, 2018 6:06 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 49
Благодарил (а): 35 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Спасибо! Попробую этот аналог!


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Ср окт 03, 2018 9:05 pm 
Не в сети
ассистент

Зарегистрирован: Ср мар 30, 2016 9:45 pm
Сообщений: 18
Благодарил (а): 0 раз.
Поблагодарили: 4 раз.
Попалась на глаза статейка про схожую проблему, может поможет разобраться в чем дело: https://norseev.ru/2017/10/31/%D1%81%D1 ... commerror/


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб окт 06, 2018 7:38 am 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 49
Благодарил (а): 35 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Попробовал аналог ф-и AvailableSerialPortInput(), всё то же самое: стабильный опрос приборов получается только при минимальной паузе после запроса 100 мс. Если поставить паузу, например, 10 мс, то возникают сбои... Хотелось бы, чтобы опрос происходил побыстрее, т.к. у меня 3 прибора подключены параллельно и опрашиваются в одном потоке.
Получается, что дело в приборах??

Но тут возникает один парадокс, на мой взгляд. Попробовал скомпилировать этот код в версии PB 5.00, работает также. Но если убрать проверку входного буфера порта (убрать AvailableSerialPortInput()) и сразу читать данные с помощью ReadSerialPortData(), то программа работает без сбоев даже при паузе после запроса 5 мс. При этом, даже если приборы выключены, и в порт ничего не приходит, то программа не виснет. В версии PB 5.62 такое не прокатывает, так как программа блокируется на функции чтения при отсутствии данных во входном буфере порта.
Интересно, что за парадокс такой?

Вот кусок кода без проверки входного буфера
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Repeat                                                                     ;бесконечный цикл опроса
    If countCI5003>2                                                         ;проверяем номер прибора (максимальный номер на входе цикла = число приборов-1)
      countCI5003=0                                                          ;если номер прибора превышает максимальный, то присваиваем ему 0
    EndIf  
    countCI5003=countCI5003+1                                                ;изменение номера прибора начиная с 0
;Отправляем запрос
    ;В один и тот же момент, может только один поток работать с Restore и Read, поэтому отказываемся от Restore и Read, а данные из DataSection будем считывать по указателю на метку.
    Protected x.a=0                                                         ;переменная для хранения текущего байта из zapros
    Protected i.a=0
    Protected xxCI5003.a=0
    For i=0 To 11                                                            ;цикл формирования пакета и отправки его в порт (байт за байтом)
      x=PeekA(?zapros_CI5003+i)                                               ;считываем данные из DataSection по указателю на метку
      Select i
        Case 0 To 7,9,10                                                     ;формируемые посылки будут отличаться только адресом и CRC (8 и 11 быйты соответственно)
          TX_CI5003(i)=x
        Case 8
          Select countCI5003
            Case 1
              TX_CI5003(i)=Adr1
            Case 2
              TX_CI5003(i)=Adr2
            Case 3
              TX_CI5003(i)=Adr3
          EndSelect    
        Case 11
          TX_CI5003(i)=CreateCRC_CI5003()  
      EndSelect  
      xxCI5003=TX_CI5003(i)  
      ;Debug Hex(xxCI5003)
      WriteSerialPortData(#SerialPort_CI5003, @xxCI5003, 1)                   ;отправляем в порт "атый" байт
    Next i                                                                   ;следующий байт...
      ;Debug ""
    Delay(Delay1_CI5003)                                                     ;пауза после запроса
    GetSystemTime_(t_CI5003)                                                 ;фиксируем в глобальной переменной (.Time) время прихода пакета с измеряемой величиной (для журнала)
    For i=0 To 18                                                            ;обнуляем массив приема
      RX_CI5003(i)=0
    Next i
;Читаем ответ
    *paketCI5003=AllocateMemory(19)                                          ;выделяем 19 байт оперативной памяти RAM
    If ReadSerialPortData(#SerialPort_CI5003, *paketCI5003, 19)              ;читаем принятый пакет из порта в память RAM
      ;Debug Hex(PeekA(*paketCI5003+3))
      For i=0 To 18                                                          ;читаем побайтно пакет из памяти RAM в массив приема
        RX_CI5003(i)=PeekA(*paketCI5003+i)
      Next i
    EndIf
    FreeMemory(*paketCI5003)                                                 ;освобождаем память
;Действуем



А вот с проверкой входного буфера
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Repeat                                                                       ;бесконечный цикл опроса
    If countCI5003>2                                                           ;проверяем номер прибора (максимальный номер на входе цикла = число приборов-1)
      countCI5003=0                                                            ;если номер прибора превышает максимальный, то присваиваем ему 0
    EndIf  
    countCI5003=countCI5003+1                                                  ;изменение номера прибора начиная с 0
                                                                               ;Отправляем запрос. В один и тот же момент, может только один поток работать с Restore и Read, поэтому отказываемся от Restore и Read, а данные из DataSection будем считывать по указателю на метку.
    Protected x.a=0                                                            ;переменная для хранения текущего байта из zapros
    Protected i.a=0
    Protected xxCI5003.a=0
    For i=0 To 11                                                              ;цикл формирования пакета и отправки его в порт (байт за байтом)
      x=PeekA(?zapros_CI5003+i)                                                ;считываем данные из DataSection по указателю на метку
      Select i
        Case 0 To 7,9,10                                                       ;формируемые посылки будут отличаться только адресом и CRC (8 и 11 быйты соответственно)
          TX_CI5003(i)=x
        Case 8
          Select countCI5003
            Case 1
              TX_CI5003(i)=Adr1
            Case 2
              TX_CI5003(i)=Adr2
            Case 3
              TX_CI5003(i)=Adr3
          EndSelect    
        Case 11
          TX_CI5003(i)=CreateCRC_CI5003()  
      EndSelect  
      xxCI5003=TX_CI5003(i)  
      ;Debug Hex(xxCI5003)
      WriteSerialPortData(#SerialPort_CI5003, @xxCI5003, 1)                    ;отправляем в порт "атый" байт
    Next i                                                                     ;следующий байт...
      ;Debug ""
    Delay(Delay1_CI5003+1)                                                     ;пауза после запроса
    GetSystemTime_(t_CI5003)                                                   ;фиксируем в глобальной переменной (.Time) время прихода пакета с измеряемой величиной (для журнала)
    If AvailableSerialPortInput(#SerialPort_CI5003)
      For i=0 To 18                                                            ;обнуляем массив приема
        RX_CI5003(i)=0
      Next i
                                                                               ;Читаем ответ
      *paketCI5003=AllocateMemory(19)                                          ;выделяем 19 байт оперативной памяти RAM
      If ReadSerialPortData(#SerialPort_CI5003, *paketCI5003, 19)              ;читаем принятый пакет из порта в память RAM
        ;Debug Hex(PeekA(*paketCI5003+3))
        For i=0 To 18                                                          ;читаем побайтно пакет из памяти RAM в массив приема
          RX_CI5003(i)=PeekA(*paketCI5003+i)
        Next i
      EndIf
      FreeMemory(*paketCI5003)                                                 ;освобождаем память
                                                                               ;Действуем



Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб окт 06, 2018 1:28 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11299
Благодарил (а): 4 раз.
Поблагодарили: 436 раз.
COM порт интегрированный в системную плату, или переходник USB-UART?
Если переходик, то может дело в его драйверах? Можно попробовать с другой микросхемой.

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб окт 06, 2018 5:11 pm 
Не в сети
доцент

Зарегистрирован: Пн мар 30, 2015 5:48 pm
Сообщений: 49
Благодарил (а): 35 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Пётр писал(а):
COM порт интегрированный в системную плату, или переходник USB-UART?
Если переходик, то может дело в его драйверах? Можно попробовать с другой микросхемой.


У меня несколько приборов общаются с ПК, использую 8-портовый преобразователь USB в RS-232
https://www.moxa.ru/shop/usb/metal/uport-1610-8/

Есть 8-портовый преобразователь USB в RS-232/422/485.
https://www.moxa.ru/shop/usb/metal/uport-1650-8/
Может его попробовать?

Попробую еще напрямую к ПК подключиться.
Пётр, если проблема в USB-хабе, то ее можно как-то решить не исключая хаб?


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Сб окт 06, 2018 5:26 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11299
Благодарил (а): 4 раз.
Поблагодарили: 436 раз.
Я не про USB хаб, а про драйвер виртуального COM порта. Как этот преобразователь определяется в диспетчере задач?
Вполне возможно что он состоит и 8-ми портового USB хаба и 8 микросхем типа FT232 или PL2303.

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 45 ]  На страницу Пред.  1, 2, 3  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 11


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group (блог о phpBB)
Сборка создана CMSart Studio
Русская поддержка phpBB