PDA

Просмотр полной версии : Свободное чтение RS-485



Raikkonen
26.05.2022, 20:40
Добрый день всем!
Имею устройство, которое 24/7 без смс и регистрации отправляет по 485 портику на скорости света 115200 посылку вида:

байт FF
байт 03 (типа его адрес)
байт CC (типа функция)
16 байт данных
байт контрольной суммы CRC
байт FF
байт FF

итого 22 байта.

я уже все это получаю и разбираю следующим кодом:



PROGRAM com_read_prg
VAR
com_settings: COMSETTINGS;
com_service_fb: COM_SERVICE;
com_port_num: PORTS := 0;
com_port_ready: BOOL;

bytes_read: DWORD;
buffer: ARRAY [1..50] OF BYTE;
package: ARRAY [1..22] OF BYTE;
p_pointer: POINTER TO ARRAY [1..22] OF BYTE;
i,ii: INT;
weight: weight_package;
p1: POINTER TO BYTE;
END_VAR


IF com_service_fb.ready=FALSE THEN
com_settings.Port:=com_port_num;
com_settings.dwBaudRate:=115200;
com_settings.byParity:=0;
com_settings.dwTimeout:=0;
com_settings.byStopBits:=0;
com_settings.dwBufferSize:=0;
com_settings.dwScan:=0;
com_service_fb(Enable:=TRUE, Settings:=com_settings, Task:=OPEN_TSK);
com_port_ready:=FALSE;
ELSE
com_service_fb.Enable:=FALSE;
com_port_ready:=TRUE;
END_IF

IF com_port_ready THEN
bytes_read := SysComRead(com_settings.Port,ADR(buffer[1]),50,0); (*каждый цикл читаем 50 байт данных потому что в них я точно найду нужные мне 22 байта*)
IF bytes_read > 0 THEN (*если что-то нашли*)
FOR i:=1 TO 28 DO (*то начинаем искать совпадение*)
IF (buffer[i] = 16#FF) AND (buffer[i+1] = 16#03) AND (buffer[i+2] = 16#CC) AND (*не парюсь ищу совпадение по началу и концу которые всегда одинаковые*)
(buffer[i+20] = 16#FF) AND (buffer[i+21] = 16#FF) THEN
p_pointer := ADR (buffer[i]); (* если нашли то при помощи указателя*)
package := p_pointer^; (*копируем найденное в массив ровно на 22 байта, это я потом чтобы контрольную сумму считать*)

p1 := ADR(weight.ch1); (* weight - это структура тупо из 8 UINT, поэтому я свой массив перевожу в уинт чтобы далее его использовать*)
FOR ii:=4 TO 19 DO
p1^ := package[ii];
p1 := p1+1;
END_FOR

EXIT;
END_IF

END_FOR
END_IF
END_IF



И у меня возникло несколько вопросов:
1. Так как скорость 115200, я думаю считывая по 50 байт каждый цикл (50 мсек), мне кажется рано или поздно случится переполнение буфера?

Я не очень понимаю как этот буфер устроен.
2. Не понимаю - я читаю данные из конца или из начала этого буфера?
3. Вроде как прочитанные данные из буфера стираются, это так или не очень?

Анализируя данные в буфере я обратил внимание что посылки бывают кусками, хотя по факту я на 100000000000000% уверен что они всегда ровненькие и одинаковые
4. Почему в буфере могут быть обрывки? это потому что я своими 50 байтами там оставляют объедки от них?


Ну и самый главный вопрос - если у кого-то есть бесплатные идеи по оптимизации - готов бесплатно их выслушать =)
Или в целом концепция как лучше поступить в моей ситуации - просто слушать эти 22 байта

keysansa
26.05.2022, 22:13
Для этого, в спецификации Serial порта предусмотрены дополнительные линии (DTR, DSR). Если интерфейс устройства предусматривает полный протокол (8 линий), то у вас не возникнет проблем переполнения.

Rake Runner
26.05.2022, 22:20
Если интерфейс устройства предусматривает полный протокол (8 линий), то у вас не возникнет проблем переполнения.

Я вижу, вы человек высокой культуры.

keysansa
26.05.2022, 22:28
Ох, опростоволосился... )
ЗЫ. Но то, что люди покритиковали, а не предложили свое решение - мне тоже нравится )

keysansa
26.05.2022, 22:32
Что является разделением пакетов - сигнатура пакета или пауза между ?

Тоже покритикую, тогда.
Валенок, вы не видите сигнатуры:

байт FF
байт 03 (типа его адрес)
байт CC (типа функция)
16 байт данных
байт контрольной суммы CRC
байт FF
байт FF

keysansa
26.05.2022, 22:33
https://mishka-knizhka.ru/skazki-dlay-detey/russkie-narodnye-skazki/russkie-volshebnye-skazki/podi-tuda-ne-znaju-kuda-prinesi-to-ne-znaju-chto/
п#2

Отлично. Только это не мне, а автору нужно цитировать, раз это предложение )

Валенок
26.05.2022, 22:34
Валенок, вы не видите сигнатуры:
3 раза подряд по 255 - вижу. Даете зуб что в данных их гарантированно нет ?

Raikkonen
27.05.2022, 12:50
Вопрос про то что есть ли пауза и есть ли FF в данных:
1. пауз ни каких нет, просто без остановки фигачит
2. опытным путем выявлено что максимальное значение может быть 65534, то есть FF FF не будет, будет только FF FE
3. никаких линий больше нет, я имею ввиду RTS CTS и всякие там которые еще человек выше писал

В целом пост направлен на то, что может кто подскажет более изящное решение, потому что мое мне кажется деревянным.
И я переживаю за переполнение. И не понимаю из конца или из начала буфера я беру данные

Raikkonen
27.05.2022, 20:32
искать 3 (именно три) последовательных 255 и от этого синхронизироватся - после 3-его 255 (не 1-ого и не 2-ого) проверять 03, CC и следущих в конце (по получению нужного кол-ва) 2-х 255.
Я приложил код, так и сделано - ищет FF 03 CC и через 20 байт FF FF.

Что на счет переполнения буфера? и из конца или начала я их беру когда использую команду "Read"

Raikkonen
27.05.2022, 22:25
не так.
IF (buffer[i] = 16#FF) AND (buffer[i+1] = 16#03) AND (buffer[i+2] = 16#CC) AND (buffer[i+20] = 16#FF) AND (buffer[i+21] = 16#FF) THEN

Перестановка мест слагаемых, я так понимаю?



считывать всё возможное а не хватать иногда куски. Хотя "и так пойдет" имеет право на жизнь видимо. Хозяин - барин


А как считывать все что есть то?
Это измерение веса. Вес измерять чаще чем раз в 20 сек смысла нет.
Я хочу просто быть уверенным в:
1. Не наступит переполнения буфера
2. Я получаю последние данные, а не те что дольше всех в буфере

И так как я не понимаю как устроен буфер - не знаю.

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

keysansa
28.05.2022, 11:03
3 раза подряд по 255 - вижу. Даете зуб что в данных их гарантированно нет ?

Сигнатура не обязательно должна быть уникальной.
FF может встречаться в пакете. Но вы должны по первому FF начать формирование пакета, по получению FFFF (или по превышению длинны, таймауту) прекратить. Это именно сигнатура пакета.

keysansa
28.05.2022, 11:11
Я приложил код, так и сделано - ищет FF 03 CC и через 20 байт FF FF.

Что на счет переполнения буфера? и из конца или начала я их беру когда использую команду "Read"

Делаете буфер, в 100 байт, например.
1. Читаете порт, пока не встретите FF
2. По его получению, начинаете заполнять буфер.
3. По получению FFFF (FFFE) - прекращаете заполнять буфер, переходите к №5
4. Если за 100 байт FFFF не встречен, переходите на №1
5. Рассчитываете CRC.
6. если совпадает с указанным в пакете, переходите №7, иначе №1
7. Разбираете остальные данные пакета.

keysansa
28.05.2022, 12:37
Это измерение веса. Вес измерять чаще чем раз в 20 сек смысла нет.
Я хочу просто быть уверенным в:
1. Не наступит переполнения буфера
2. Я получаю последние данные, а не те что дольше всех в буфере

И так как я не понимаю как устроен буфер - не знаю.


1. Проверяете, что вы считали с порта байт, столько же, либо меньше, чем длинна буфера (в моем примере буфер = 100байт).
2. Буфер порта обычно 1500-1600 байт. Можете раз в 200 мс выполнить приведенный мной алгоритм, но раз вам не важны все данные, а только самые свежие, надо будет добавить пункт 0 - Сброс буфера COM порта (Flush). 200ms при потребности данных в 1s выбран для того, что бы иметь запас по времени (пропуск пакета, пакеты передаются с ошибкой).

Raikkonen
28.05.2022, 21:51
но раз вам не важны все данные, а только самые свежие, надо будет добавить пункт 0 - Сброс буфера COM порта (Flush)
А что за флуш? в сисКомЛиб нема такого

Ваш пример точно такой же как мой в глобальном смысле.

Я так и не пойму:
1. ждет меня переполнение или нет?
2. я данные командой Read беру самые новые из буфера или самые старые?

keysansa
04.06.2022, 12:38
А что за флуш? в сисКомЛиб нема такого

Clear bufer. Возможно в данной библиотеке он по другому называется.
Как "лайфхак" - закрыть и открыть порт заново. При этом обчно буфер очищается.
Или в вашем случае, открывать порт каждый раз перед опросом. Да, возможно в начале будет "хвост" какой-то посылки, но следующую вы точно отловите.



Ваш пример точно такой же как мой в глобальном смысле.

Не совсем. Вы стараетесь считывать каждое сообщение от весов, я же предлагаю, "выдёргивать" пакет из потока, именно тогда, когда вам необходимо.



Я так и не пойму:
1. ждет меня переполнение или нет?
2. я данные командой Read беру самые новые из буфера или самые старые?


1. При подходе, который я вам предложил, не будет.
2. Даже если очистка буфера не предусмотрена в команде Com.Open (в чем я сомневаюсь, общепринята практика очистки буфера при открытии порта), вы получите данные не старше, чем глубина буфера.

keysansa
04.06.2022, 12:40
Я прошу прощения, забыл спросить, у вас дозирование или взвешивание?

Samel
20.06.2022, 12:12
Какой интервал между посылками?
50 мс цикл может быть маловат!
Я бы сдела кольцевой буфер, указатель чтения и записи.
И ходил бы по ниму искал пакеты

keysansa
20.06.2022, 13:10
Какой интервал между посылками?
50 мс цикл может быть маловат!
Я бы сдела кольцевой буфер, указатель чтения и записи.
И ходил бы по ниму искал пакеты

ТС боится, что из за скорости передачи 115200 он не сможет обработать все посылки.

Samel
20.06.2022, 13:13
ТС боится, что из за скорости передачи 115200 он не сможет обработать все посылки.

Эту проблему решит уменьшение времени цикла и кольцевой буфер. 115200 это гдето 520 байт в 50 мс

keysansa
20.06.2022, 13:21
Эту проблему решит уменьшение времени цикла и кольцевой буфер. 115200 это гдето 520 байт в 50 мс

А зачем вообще кольцевой буфер? Почему не хватит обычного?

Samel
20.06.2022, 13:25
Есть вероятность чтения нескольких пакетов за раз и они могут быть не полными. А так ты по указателю записи пишешь в колцевой буфер функцией Read.

Samel
20.06.2022, 13:31
bytes_read := SysComRead(com_settings.Port,ADR(buffer[1]),50,0);
FOR i:=1 TO bytes_read DO
bufferR[pWr] := buffer[i]; (*нужно еще сделать проверку на затирание данных(Полный буфер)*)
pWr := pWr + 1;
if pWr > XXX THEN p Wr := 0;
end_IF;
END_FOR

IF pWr <> pRd THEN (*В буфере есть данные *))
...


Но и нужно правильно подобрать время цикла и размер буфера чтения и кольцевого!

keysansa
20.06.2022, 13:43
Есть вероятность чтения нескольких пакетов за раз и они могут быть не полными. А так ты по указателю записи пишешь в колцевой буфер функцией Read.

Берем обычный буфер, который вмещает 2 пакета. И 100% ловим 1 минимум.
ЗЫ. Если хватает быстродействия контроллера.

Samel
20.06.2022, 13:45
Берем обычный буфер, который вмещает 2 пакета. И 100% ловим 1 минимум.

А второй? Тут все зависит насколько нужна актуальность данных, и есть ли посторонний мусор на шине)
Если запрос<>ответ - 100% обычный буфер.
А вот если слушаем порт - я бы рекомендовал кольцевой.

melky
20.06.2022, 13:57
Samel а второй и третий порванный :)
Суть простая, что предлагает keysansa чтение 2-ного количества байт, внутри которого на 100% будет полный ответ. Начали сессию, нашли цельный буфер, распихали данные, новая сессия....

Samel
20.06.2022, 14:06
Samel а второй и третий порванный :)
Суть простая, что предлагает keysansa чтение 2-ного количества байт, внутри которого на 100% будет полный ответ. Начали сессию, нашли цельный буфер, распихали данные, новая сессия....

Я предлагаю универсальное решение. А то потом выясняется, что размер пакета не фиксированный, мусор на шине и тд.

keysansa
20.06.2022, 14:06
Samel а второй и третий порванный :)
Суть простая, что предлагает keysansa чтение 2-ного количества байт, внутри которого на 100% будет полный ответ. Начали сессию, нашли цельный буфер, распихали данные, новая сессия....

Спасибо. Но это вариант для ТС (возможны пропуски пакета, что бы не отставать по времени, я предлагал сбрасывать буфер порта), если возникает ситуация, что нельзя пропустить ни один пакет - тут только работа по прерыванию. По получению очередного байта, проверяем его на соответствие пакету и далее, принимаем решение. В ранних контроллерах был доступен режим DMA к буферу COM порта, там не надо было свой буфер, дополнительный, создавать. 1500 байт хватало для всех случаев. Но потом стали передавать данные в виде строки... И понеслось ))

keysansa
20.06.2022, 14:07
Я предлагаю универсальное решение. А то потом выясняется, что размер пакета не фиксированный, мусор на шине и тд.

Кольцевой буфер тоже должен помещать пакет полностью. Иначе он не будет работать.

ЗЫ. В случае с переменной длинной пакета - его все равно придется считать. Проще 10*х заложить, сегодня память дешевая.
ЗЫЫ. Мусор на шине не влияет на длинну буфера, нет пакета в буфере - очищаем, пишем ошибку и работаем заново.

Samel
20.06.2022, 14:09
Кольцевой буфер тоже должен помещать пакет полностью. Иначе он не будет работать.

И не один! :)

Samel
20.06.2022, 14:10
В задаче не хватает нескольких переменных:
1. Частота пакетов.
2. Требуемая актуальность данных.

keysansa
20.06.2022, 14:12
И не один! :)

Нет, с кольцевым - достаточно длинны на 1 пакет. Работать с ним сложнее просто. Не сильно, но с точки зрения циклической программы - сложнее.

keysansa
20.06.2022, 14:14
В задаче не хватает нескольких переменных:
1. Частота пакетов.
2. Требуемая актуальность данных.

1. 115200/~20.
2. Я задал вопрос ТС - у него взвешивание или дозирование. Молчит.

Samel
20.06.2022, 14:16
Нет, с кольцевым - достаточно длинны на 1 пакет. Работать с ним сложнее просто. Не сильно, но с точки зрения циклической программы - сложнее.

Один. Это если минимальное время цикла и нет мусора.
Такие беседы нужно за бокалом пенного в баре :)
Я думаю тему можно закрывать.

Raikkonen
21.06.2022, 14:51
Тут оно не надо. Тут что-то там/как-нибудь/и так сойдет.

Как его забанить в этой теме?

Raikkonen
21.06.2022, 14:52
1. 115200/~20.
2. Я задал вопрос ТС - у него взвешивание или дозирование. Молчит.

Был в отпуске. У меня дозирование.

Я не пойму самого главного - когда я использую Read - я из начала или из конца буфера читаю?

Raikkonen
21.06.2022, 14:58
Я предлагаю универсальное решение. А то потом выясняется, что размер пакета не фиксированный, мусор на шине и тд.

Если можете - ответьте на 4 вопроса из 1 сообщения темы, пожалуйста.....
я могу любые буферы обработки сам написать, я скорее не могу нормальной инфы о СисКомЛиб найти.

Samel
21.06.2022, 16:09
Был в отпуске. У меня дозирование.

Я не пойму самого главного - когда я использую Read - я из начала или из конца буфера читаю?

Из начала. Как-то глупа из конца читать :)

Samel
21.06.2022, 16:20
И у меня возникло несколько вопросов:
1. Так как скорость 115200, я думаю считывая по 50 байт каждый цикл (50 мсек), мне кажется рано или поздно случится переполнение буфера?

Я не очень понимаю как этот буфер устроен.
2. Не понимаю - я читаю данные из конца или из начала этого буфера?
3. Вроде как прочитанные данные из буфера стираются, это так или не очень?

Анализируя данные в буфере я обратил внимание что посылки бывают кусками, хотя по факту я на 100000000000000% уверен что они всегда ровненькие и одинаковые
4. Почему в буфере могут быть обрывки? это потому что я своими 50 байтами там оставляют объедки от них?
1. Все зависит от частоты посылок от устройства. Но за 50 мс может прилететь 115200/10/20 байт.
2. С начала буфера.
3. Данные вычитываются один раз.
4. Смотри 1 вопрос.

Raikkonen
22.06.2022, 11:24
Из начала. Как-то глупа из конца читать :)
Ну в целом да, получается это очередь а не стек.
А как тогда мне лучше производить чтение чтобы получать данные ближе к последним?
В одном цикле можно делать много чтений?
типа:


while SysComRead(com_settings.Port,ADR(buffer[1]),50,0) > 0 do
(*не важно какая обработка*)
end_while


??

Samel
22.06.2022, 11:31
Ну в целом да, получается это очередь а не стек.
А как тогда мне лучше производить чтение чтобы получать данные ближе к последним?
В одном цикле можно делать много чтений?
типа:


while SysComRead(com_settings.Port,ADR(buffer[1]),50,0) > 0 do
(*не важно какая обработка*)
end_while


??

Ну это не корректно. Такое чтение превратит буфер в мусор.

Raikkonen
22.06.2022, 11:32
Ну это не корректно. Такое чтение превратит буфер в мусор.

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

Samel
22.06.2022, 11:41
А я планировал читать по двукратному объему информации, и как только считал меньше чем нужно - беру предыдущий кусок, который содержит в себе 2х инфы, где точно есть нужный мне пакет.

А где хранится что считал раньше? Простая задача очень усложняется! В этой задаче главный вопрос цикл вызова функции Read!

melky
22.06.2022, 11:44
Если есть какой-то функционал остановки опроса и известен конец, то да, можно считывать с Х байта, ловить конец, проверять весь ли пакет попал в чтение и либо уже дочитывать новый пакет, либо разбирать полученное.

з.ы. подозреваю, что на ПЛК так быстро такие вещи не сделать, проще читать 2х пакета и искать начало и конец., надо прикинуть будет ли в этом случае коллизии, но вроде не должны. Либо два пакета будут полными, либо будет 1 обрезок + полный + 2 обрезок.

Samel
22.06.2022, 11:51
Если есть какой-то функционал остановки опроса и известен конец, то да, можно считывать с Х байта, ловить конец, проверять весь ли пакет попал в чтение и либо уже дочитывать новый пакет, либо разбирать полученное.

з.ы. подозреваю, что на ПЛК так быстро такие вещи не сделать, проще читать 2х пакета и искать начало и конец., надо прикинуть будет ли в этом случае коллизии, но вроде не должны. Либо два пакета будут полными, либо будет 1 обрезок + полный + 2 обрезок.

А какие проблемы сделать это на ПЛК. Читай из буфера с циклом 5 мс, формируй свой буфер и ходи по ниму ищи свой пакет

melky
22.06.2022, 12:02
Samel честно не знаю можно ли. например в RapidScada разработчик по моей просьбе дорабатывал код остановки опроса, можно посмотреть у него в исходниках. Но вот под силу такое ПЛК, который кроме опроса еще должен заниматься кучей других дел ? На ПК то это в потоке отдельном работает.... А то тоже была с подобным проблема, потому что в протоколе не было фиксированной длины данных, пакеты из-за этого могли быть разной длины и не поддавались рассчету.

Samel
22.06.2022, 12:12
Samel честно не знаю можно ли. например в RapidScada разработчик по моей просьбе дорабатывал код остановки опроса, можно посмотреть у него в исходниках. Но вот под силу такое ПЛК, который кроме опроса еще должен заниматься кучей других дел ? На ПК то это в потоке отдельном работает.... А то тоже была с подобным проблема, потому что в протоколе не было фиксированной длины данных, пакеты из-за этого могли быть разной длины и не поддавались рассчету.

У меня никогда не было проблем разбирать пакеты разной длины.
Скорость, частота посылок, предпологаемы объем данных -> время цикла задачи

melky
23.06.2022, 09:39
Валенок если правильно понял, то что-то было связано с Виндовым кодом работы с портом (NET Framework), нужно задать размер обязательно, и если мы задаем размер заведомо больше, чтобы все влезло, а пакет короткий по факту, привет Timeout.... По этому остановка была софтовая...

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

Если ПЛК аналогично может читать и сразу проверять, то отлично, можно реализовать по аналогии.
Как-то мне в голову не придет, реализовывать протокол Allen Bradley на ПЛК, там застрелиться проще... :)

Sergey666
28.06.2022, 16:14
Как-то мне в голову не придет, реализовывать протокол Allen Bradley на ПЛК, там застрелиться проще... :)

А можно подробнее, в целях повышения образованности, что это за протокол "Allen Bradley"???

melky
28.06.2022, 18:12
Sergey666 DF1 (тоже RS485), переменная длина пакета, два вида контрольных сумм, при этом отличается состав пакета для проверки контрольной суммы и многое другое.
Хотя если их ПЛК вполне справляется с задачей, то возможно и другой справится, но боюсь там это реализовано на уровне прошивки самого ПЛК а не программы.

keysansa
28.06.2022, 18:21
Был в отпуске. У меня дозирование.

Я не пойму самого главного - когда я использую Read - я из начала или из конца буфера читаю?

Буфер=очередь, стек, FIFO, FILO почитайте. Обязательно.

keysansa
28.06.2022, 18:35
Ну в целом да, получается это очередь а не стек.
А как тогда мне лучше производить чтение чтобы получать данные ближе к последним?
В одном цикле можно делать много чтений?
типа:


while SysComRead(com_settings.Port,ADR(buffer[1]),50,0) > 0 do
(*не важно какая обработка*)
end_while


??

У вас дозирование. Вам надо реагировать на изменение веса как можно чаще. Это при взвешивании, можно себе позволить небольшую паузу.
Выделяйте для обмена отдельный поток, с минимальным временем цикла там только опрашивайте, и присваивайте глобальную переменную: "текущая масса". Если не успеваете, надо взять процессор помощнее или снизить частоту посылок. Чем чаще вы узнаете вес при дозировании, тем лучше.


(*не важно какая обработка*)
Важно. Тут максимум - string -> int.

Samel
30.06.2022, 09:29
Кратко и по существу :)

keysansa
02.07.2022, 18:49
Чаще чем всё - не получится, но тута это не нужно - как-нить/что-нить выдернуть и так пойдет. Говорилось. Угрожали забанить ))

А все и не надо. Необходимо, что бы время реакции системы было в 2-3 раза больше, чем поток дозирования в отношении к допустимой точности дозирования.


Здесь их нет если только не про задачи, но манипуляции с кнопочками калькулятора подсказывают что и без всяких задач - без проблем. Даже всё, несмотря на.

Задачи запускаются отдельным потоком.

keysansa
02.07.2022, 18:50
Чаще чем всё - не получится, но тута это не нужно - как-нить/что-нить выдернуть и так пойдет. Говорилось. Угрожали забанить ))

А все и не надо. Необходимо, что бы время реакции системы было в 2-3 раза больше, чем поток дозирования в отношении к допустимой точности дозирования.


Здесь их нет если только не про задачи, но манипуляции с кнопочками калькулятора подсказывают что и без всяких задач - без проблем. Даже всё, несмотря на.

Задачи запускаются отдельным потоком.


Лично я не совсем тут понял - что это.

Чаще всего, весовые терминалы отправляют "plain" данные, в виде строки.

keysansa
02.07.2022, 22:14
Разброд и шатания :

или
?

Вы не чувствуете разницы между "как можно чаще" и "все"? Или у вас "разброд и шатание" сегодня?
Чем чаще вы снимаете данные с АЦП тензодатчика (ограничено скоростью преобразования АЦП), чем чаще вы получите данные в контроллере, и тем быстрее сможете отреагировать на заданный вес (ограничено скоростью контроллера, временем срабатывания исполнительных устройств, количеством материала, который уже невозможно остановить).
Конечно, если дозировать 2гр/мин при допустимой точности в +/-2 кг, можно и не торопиться. В дозу попадём. Видимо вы в таких условиях и работаете. Но у меня скорости дозирования выше. А так же требования к точности.





Это - напрягает.
И вы уже в курсе "допустимой точности дозирования" ?
Где здесь потоки ?



Написал чуть выше, поток в моем примере - 2гр/мин, точность +/- 2 кг. Я считаю, что разбираюсь, пишите аргументы, если не согласны.



Тут не нужно гадать - "максимум","чаще всего" и т.п. Тут всё чётко:

Вы видимо много пенистого взяли. )




и что там в данных вроде как пофиг


16 байт данных - там актуальное значение веса. Вы думаете Int (float) 16 байт занимает или string?


Где здесь потоки ?

Как вы думаете на контроллерах реализуются несколько "задач" с разными циклами?

Samel
02.07.2022, 23:39
Тема превращается во флуд, пора закрывать!!! Нельзя принимать/обрабатывать данные чаще чем они приходят!!! Скорость 115200 размер пакета 22 байта - итого пакет отправляется/принимается за 2 мс, а ещё между пакетами по-любому есть время тишины. Так что 5 мс цикл программы решает все проблем!!! А в 110/160 в 5 мс можно запихнуть огого!!!!
Тема закрыта!

keysansa
02.07.2022, 23:42
Тема превращается во флуд, пора закрывать!!! Нельзя принимать/обрабатывать данные чаще чем они приходят!!! Скорость 115200 размер пакета 22 байта - итого пакет отправляется/принимается за 2 мс, а ещё между пакетами по-любому есть время тишины. Так что 5 мс цикл программы решает все проблем!!! А в 110/160 в 5 мс можно запихнуть огого!!!!
Тема закрыта!

То, что вы не понимаете, что тут обсуждается, не значит, что это флуд.

Samel
02.07.2022, 23:48
Добрый день всем!
Имею устройство, которое 24/7 без смс и регистрации отправляет по 485 портику на скорости света 115200 посылку вида:

байт FF
байт 03 (типа его адрес)
байт CC (типа функция)
16 байт данных
байт контрольной суммы CRC
байт FF
байт FF

итого 22 байта.

я уже все это получаю и разбираю следующим кодом:



PROGRAM com_read_prg
VAR
com_settings: COMSETTINGS;
com_service_fb: COM_SERVICE;
com_port_num: PORTS := 0;
com_port_ready: BOOL;

bytes_read: DWORD;
buffer: ARRAY [1..50] OF BYTE;
package: ARRAY [1..22] OF BYTE;
p_pointer: POINTER TO ARRAY [1..22] OF BYTE;
i,ii: INT;
weight: weight_package;
p1: POINTER TO BYTE;
END_VAR


IF com_service_fb.ready=FALSE THEN
com_settings.Port:=com_port_num;
com_settings.dwBaudRate:=115200;
com_settings.byParity:=0;
com_settings.dwTimeout:=0;
com_settings.byStopBits:=0;
com_settings.dwBufferSize:=0;
com_settings.dwScan:=0;
com_service_fb(Enable:=TRUE, Settings:=com_settings, Task:=OPEN_TSK);
com_port_ready:=FALSE;
ELSE
com_service_fb.Enable:=FALSE;
com_port_ready:=TRUE;
END_IF

IF com_port_ready THEN
bytes_read := SysComRead(com_settings.Port,ADR(buffer[1]),50,0); (*каждый цикл читаем 50 байт данных потому что в них я точно найду нужные мне 22 байта*)
IF bytes_read > 0 THEN (*если что-то нашли*)
FOR i:=1 TO 28 DO (*то начинаем искать совпадение*)
IF (buffer[i] = 16#FF) AND (buffer[i+1] = 16#03) AND (buffer[i+2] = 16#CC) AND (*не парюсь ищу совпадение по началу и концу которые всегда одинаковые*)
(buffer[i+20] = 16#FF) AND (buffer[i+21] = 16#FF) THEN
p_pointer := ADR (buffer[i]); (* если нашли то при помощи указателя*)
package := p_pointer^; (*копируем найденное в массив ровно на 22 байта, это я потом чтобы контрольную сумму считать*)

p1 := ADR(weight.ch1); (* weight - это структура тупо из 8 UINT, поэтому я свой массив перевожу в уинт чтобы далее его использовать*)
FOR ii:=4 TO 19 DO
p1^ := package[ii];
p1 := p1+1;
END_FOR

EXIT;
END_IF

END_FOR
END_IF
END_IF



И у меня возникло несколько вопросов:
1. Так как скорость 115200, я думаю считывая по 50 байт каждый цикл (50 мсек), мне кажется рано или поздно случится переполнение буфера?

Я не очень понимаю как этот буфер устроен.
2. Не понимаю - я читаю данные из конца или из начала этого буфера?
3. Вроде как прочитанные данные из буфера стираются, это так или не очень?

Анализируя данные в буфере я обратил внимание что посылки бывают кусками, хотя по факту я на 100000000000000% уверен что они всегда ровненькие и одинаковые
4. Почему в буфере могут быть обрывки? это потому что я своими 50 байтами там оставляют объедки от них?


Ну и самый главный вопрос - если у кого-то есть бесплатные идеи по оптимизации - готов бесплатно их выслушать =)
Или в целом концепция как лучше поступить в моей ситуации - просто слушать эти 22 байта
Мне казалось что обсуждалось это. Так на эти вопросы ответы уже даны! Все остальное флуд

keysansa
03.07.2022, 00:12
Это не вам, а ТС решать ))

Валенок
03.07.2022, 15:08
Ну пофлудим


..чем чаще вы получите данные в контроллере, и тем быстрее сможете отреагировать на заданный вес ..
..
Кто-то с этим спорит ? Ранее сказано - "Чаще чем всё - не получится" - чтo-то не так ? теперь получится ?


.. можно и не торопиться. В дозу попадём. Видимо вы в таких условиях и работаете..
Ну ? Что-то как-то выдернем и так пойдет. Не ? Ведь - да :

.. Вес измерять чаще чем раз в 20 сек смысла нет...
но

.
Я хочу просто быть уверенным в:
1. Не наступит переполнения буфера
2. Я получаю последние данные, а не те что дольше всех в буфере..
Получая всё - получается максимум уверености. А юзать можно и раз в год коли чаще смысла нет.




Написал чуть выше, поток в моем примере - 2гр/мин, точность +/- 2 кг. Я считаю, что разбираюсь, пишите аргументы, если не согласны.

Про пример - понятно. А тута точно всё точно ?

..Необходимо, что бы время реакции системы было в 2-3 раза больше, чем поток дозирования в отношении к допустимой точности ...



16 байт данных - там актуальное значение веса. Вы думаете Int (float) 16 байт занимает или string?

Я думаю ? Оно мне надо ? Стынет же. 16 байт - это просто данные. Про это - есть.
А Вы накой-то додумываете. Может и угадали ..:




PROGRAM com_read_prg
VAR
...
package: ARRAY [1..22] OF BYTE;
p_pointer: POINTER TO ARRAY [1..22] OF BYTE;
...
weight: weight_package;
p1: POINTER TO BYTE;
END_VAR
...
p_pointer := ADR (buffer[i]);
package := p_pointer^; (*копируем найденное в массив ровно на 22 байта...*)
...
p1 := ADR(weight.ch1); (* weight - это структура тупо из 8 UINT, поэтому я свой массив перевожу в уинт...*)
FOR ii:=4 TO 19 DO
p1^ := package[ii];
p1 := p1+1;
END_FOR
..


А может и нет )) Только время на гадания тратили.



Как вы думаете на контроллерах реализуются несколько "задач" с разными циклами?
Где здесь потоки ? (2й раз) Прямых данных от ТС нет, но раздел про ПЛК110[М02] а не абстрактные "контроллеры"


ps


Вы видимо много пенистого взяли. )

Бывает - много 8( ??? Вы точно не с планеты эльфов ? Всегда мало !!

keysansa
04.07.2022, 22:12
Кто-то с этим спорит ? Ранее сказано - "Чаще чем всё - не получится" - чтo-то не так ? теперь получится ?


Боже, наконец-то я понял, что вы хотели написать ) Так бы сразу и сказали, чаще, чем остальной ввод/вывод (а то - никогда не говори никогда - какое-то )) ). Про Овен - не знаю, но в других системах это возможно, про прерыванию АЦП (готовность данных), остальной В/В при этом мне не нужен, нужен только 1 выход, который управляет потоком. Остальной ввод/вывод может работать гораздо медленнее.



Ну ? Что-то как-то выдернем и так пойдет. Не ? Ведь - да :

На этапе проектирования часто кажется, что хватит...




Про пример - понятно. А тута точно всё точно ?

Начинается... Цепляемся к мелочам. Хороший подход. "Время реакции меньше" - лучше звучит? На мой взгляд - нет.






Я думаю ? Оно мне надо ? Стынет же. 16 байт - это просто данные. Про это - есть.
А Вы накой-то додумываете. Может и угадали ..:

Вам непонятно было, что я имею ввиду под фразой "там преобразование string - int". Я объяснил. Перечитайте.
Не хотите тратить время - не тратьте.




Где здесь потоки ? (2й раз) Прямых данных от ТС нет, но раздел про ПЛК110[М02] а не абстрактные "контроллеры"

Я уже объяснил, почитайте мое предыдущее сообщение. У ТС это нет, это только мое предложение (в сообщении через одно до этого).


ЗЫ.


Бывает - много 8( ??? Вы точно не с планеты эльфов ? Всегда мало !!
[/QUOTE]
Мне пиво тоже нравится. Именно тем, что слишком много его не выпить - в отличие от водки, которая при превышении нормы - просится наружу, пиво - тупо не лезет ))) Но когда оно уже не лезет - это много.