Вот и я про это же ж. Но ЕвгенийП расписал всё красиво, конечно, но нифига не практично.( Хоть по преамбуле ли, по таймауту ли - это ведь не сложно. А то как фишки со структорой или выводом - так пожалуйста, а как очевидные (практичные) вещи - так тишина.)
У меня проверка данных будет, сраниваться будут, к примеру,первый и последний символ.
Дак если будет лишний байт, как Вы гвоорите, то проверка по CRC есть, и если первого раза данные отправлены, но получены неверно, будет повторная отправка и т.п.
она так не поймёт, надо по простому, дескать принято начало пакета формировать определённую последовательностью, к примеру хххyyy потом адрес устройства, данные, потом окончание пакета к примеру F6F6F6 и далее CRC (всё условно)
А если начнете читать с середины, к примеру, то будет всегда приходить последних 3 байта из предыдущего пакета и первых три байта из следующего. Количество совпадает, а вот данные - бессмысленны. Нужна повторная отправка. Т.е. ещё обратную связь городить для перезапроса. Оно вам надо?
Ненадо никаких маркеров. Чем они будут отличаться от данных? Лучше разделять пакеты по временной паузе. Превышена пауза - значит новый пакет, т.е. первый байт пакета (адрес).
Передатчик может и заткнуться на некоторое время и потом дослать пакет, если неудачно написан ;) В принципе маркеры-то - вещь неплохая, во многих сенсорах встречаю. Только надо понять, что в преамбуле (если кто-то привык к этому слову) не должны встречаться сочетания, которые есть в остальных данных пакета. А далее все просто - размер известен, структура разложится на переменные автоматически...
Если данные в двоичном виде и в диапазоне от 0 до 255, то сочетание не выбрать.) В этом случае используется байт-стаффинг, как в SLIP, но это сложно для начинающего.) Если передатчик имеет свойство затыкаться, тогда и время паузы можно увеличить соответственно. Не так часто у нас синхронизация ведь теряется.) Либо же просто забить - пакет будет теряться во время затыка.
Ну, вобщем, в сенсорах просто два байта хидера и никаких извращений с формированием пауз. Подозреваю, что причиной тому - потенциальная возможность разогнать поток данных так, что и пауз не останется. Впрочем, выбирать не нам. Варианты озвучены.
Irinka, если верить тому коду, который Вы привели в самом начале темы, Вам достаточно передать всего 1 (прописью: "один") байт данных. В этом случае принять, "начиная не с того байта" физически невозможно. Наличие ошибок в байте Вы все равно нее проверяете, следовательно, протокол вообще не нужен.
Мне кажется, в расчете на общий случай Вашу конкретную задачу чрезмерно усложнили.
а адресат?
Уже не один байт...
Ей жеж нужно точно знать, кому, что предназначается
PS это же только В.Высоцкий раздавал своё творчество, "независимо от стипендии у кого повышенная у кого какая, чтобы каждому досталось по куску"
Я ориентировался на исходный пост темы, если на самом де6ле нужно что-то другое, то конкретное решение для этого другого случая можно попытаться сделать как в общем виде (и это наверняка займет гораздо больше ресурсов), так и в конкретно "заточенном" на данный случай.
Для начала следует выяснить, сколько бит нужно передавать. В теме было упомянуто "четырехзначное число", но по какому основанию четырехзначное? 1011 - число четырехзначное, и F0A9 - тоже четырехзначное.
Т.е. конкретно нужно знать:
- сколько раличных адресов будут использоваться (например, адрес может быть хоть 20-значный, но если выбирать нужно будет только из двух адресов - достаточно 1 бита),
- сколько различных вариантов данных нужно передавать (например, если нам нужно передавать либо "Иванов Иван Иванович" либо "Цукерман Мойша Давидович", то, опять же, достаточно только одного бита),
- нет ли корреляции между адресом и данными (например, "Иванов..." мы всегда передаем на адрес "123456789", а "Цукерман..." - всегда на адрес "987654321").
Да, да, да. Абсолютно верно.) Я тут как то ребёнку делал табло и там получилась простейшая сеть: мастер и 2 ведомых.) На всё - про всё хватило байта. И не нужно заморачиваться с протоколами, таймаутами и пр.
Может просто положить его на стороне передатчика в начало структуры, а на стороне приёмника пропускать всё, пока не будет пойман маркер и с этого момента начинать принимать пакет?
Может просто положить его на стороне передатчика в начало структуры, а на стороне приёмника пропускать всё, пока не будет пойман маркер и с этого момента начинать принимать пакет?
Только перед этим обязательно необходимо удостовериться, что ни один из оставшихся байтов нашего формата ни при каких условиях не может принять значение равное значению выбранного нами маркера.
Только перед этим обязательно необходимо удостовериться, что ни один из оставшихся байтов нашего формата ни при каких условиях не может принять значение равное значению выбранного нами маркера.
Я об этом уже писал - #61, но второй раз напомнить не помешает.
Только перед этим обязательно необходимо удостовериться, что ни один из оставшихся байтов нашего формата ни при каких условиях не может принять значение равное значению выбранного нами маркера.
Иначе и наган не поможет.
Есть ModBus, DMX? и полно похожих протоколов. Я использую протокол AdBus, исторически сложилось, это протокол системы сигнализации Adicon в американских тюрьмах, но в российских нетюрьмах тоже работает. Передает по 8 байт в пакете
0xFF 0xFF - старт
Адрес (0-127)
Команда (0-127)
Дата0
Дата1
Дата 2
CS -Контрольная сумма.
Полученные байты пишутся в кольцевой регистр, и по получению каждого байта анализируются на то что первые байты- 0xFF и последний байт =контрольной сумме. Как совпало - прописываем данные. Вероятность случайного совпадения точно равна нулю.
Можно делать протоколы на этой идее и меньше - в систему управления, если команд и (или) параметров мало, то можно просто FF FF data CS или FF FF data0 data1 CS.
Только перед этим обязательно необходимо удостовериться, что ни один из оставшихся байтов нашего формата ни при каких условиях не может принять значение равное значению выбранного нами маркера.
Иначе и наган не поможет.
Помогает https://youtu.be/chrOu6ic6XM?t=391 - колективес мотоцикл+маска+пистолет и уже нет вопросов , причем никаких. А на любой вопрос есть одид ответ -пуля.
Так и здесь. Пусть 0хFF это байт начала. А если идет прием середины протокола и появляется 0хFF - то все что приняли ранее это труп или муссор. А дальше организовывается пакет где никогда не должно быть 0хFF. Если данные все равно нужен 0хFF , то передаем полубайтами. Сначала младший, потом старший.
Так и здесь. Пусть 0хFF это байт начала. А если идет прием середины протокола и появляется 0хFF - то все что приняли ранее это труп или муссор. А дальше организовывается пакет где никогда не должно быть 0хFF. Если данные все равно нужен 0хFF , то передаем полубайтами. Сначала младший, потом старший.
это рабочий вариант, согласен - но обрабатывать данные на предмет вхождения в них 0xFF и при необходимости удалять этот байт - имхо, лишнее усложение.
Онкель правильно говорит - для надежности делаем уникальную преамбулу из нескольких байт, скажем из 3-4х. Правда его выбор значения 0xFF не кажется мне удачным, потому что длинные цепочки 0XFF довольно часто попадаются в обычных данных. Я обычно беру набор неодинаковых байт, например 0xb707 :)
Вероятность того, что в данных попадется такая же последовательность - конечно же не нулевая, но вероятность. что и CRC в конце ошибочно распознанного пакета окажется верным - настолько близка к кнулю, что позволяет рекомендовать метод для использования в бытовых устройствах :)
Если канал не загружен и нет желания мудохаться с CRC, то мой вариант проще. Onkel-ю проще. У него все отработано.Осталось включит библиотеку в проект и все.
Еще интересней если пакеты идут разной длины. Ну например хочется или так уж вышло. Тогда наган (0xFF) идет в конце. Типо все разговор окончен. Все что в буфере с тем и разбирайся. Но тогда при инициализации отравляется пакет из одного нагана (0xFF). И тогда следущий пакет без накапливающих ошибок в приемном буфере. Но разумеется два нагана на один пакет уже пакет без шансов принять и обработать правильно.
Никакая преамбула не хуже, если она не встречается в допустимых данных. Другое дело что на 6 байт данных эквивалентной длины преамбула избыточна, вобщем-то.
Одно с другим никак не связано. От слова "совсем".
Вы говорите о вероятности аппаратного сбоя, а я - о вероятности случайно сформировать пакет, который будет распознан как валидный.
Да понятно. Но я о том, что если бы такой сбой произошел, он обязательно повлек бы за собой еще один сбой- следующего пакета. Поэтому мой тест говорит что ни одного неправильного пакета (или один) на миллион. Аэто значит уже можно жить. Например, передавать "жизненно важные" команды два раза, или анализировать ответ. А можно и то, и то. А По сути дело еще в том, что в 8 байтах 0xFF может быть только контрольная сумма, просто протокол такой что параметров 128, адресов 128, и параметры никогда не выставляются в 0xFF потому что 0xFF - это записано в "чистой" ЕЕPROM. И уже дело мастера сформировать пакет так, чтобы двойной FF не встречалось. Да, в самом "родном" протоколе если контрольная сумма 0xFF , то передается 0x00.
Можно ведь как в ModBUS ASCII - там начало передачи можно выделить всегда! Правда получим увеличение длины посылки. Но за все надо платить.
Онкель, та дурдом какой то. Заголовок FF FF, адрес/команда 7F 7F, данные FF FF FF, КС FF. Это макс. Но, данные не могут быть FF, КС не может быть FF - вместо них 0. Получается 0 == FF. А раз так, то 0 мы тоже не можем использовать в данных/КС. Ведь 0 это у нас FF!))) Иначе, чему верить!
Это я к тому что не бывает чудес. Или нужно жертвовать длиной пакета (заголовок, диапазон данных/кс), либо быть готовым к тому что отдельные пакеты могут быть отбракованы. Т.е., определённую кобинацию данных можно НИКОГДА не принять!
Irinka, а вот залетел к вам (в вашу сеть) один лишний байт из вне и что? Всё, накрылась ваша богодельня? Где начало, где конец, где данные, где КС...?
не, не начало и конец, а преамбула и,... )))
Вот и я про это же ж. Но ЕвгенийП расписал всё красиво, конечно, но нифига не практично.( Хоть по преамбуле ли, по таймауту ли - это ведь не сложно. А то как фишки со структорой или выводом - так пожалуйста, а как очевидные (практичные) вещи - так тишина.)
У меня проверка данных будет, сраниваться будут, к примеру,первый и последний символ.
Дак если будет лишний байт, как Вы гвоорите, то проверка по CRC есть, и если первого раза данные отправлены, но получены неверно, будет повторная отправка и т.п.
Сравниваться с чем и для чего?
Сравниваться с чем и для чего?
Сравниваться с чем и для чего?
У меня одно и то же количество байт передается, если пришли не все, значит ошибка, повтор отправки
А если начнете читать с середины, к примеру, то будет всегда приходить последних 3 байта из предыдущего пакета и первых три байта из следующего. Количество совпадает, а вот данные - бессмысленны. Нужна повторная отправка. Т.е. ещё обратную связь городить для перезапроса. Оно вам надо?
Вот так потихонечку и ненавязчиво склоним Иринку к написанию ПРОТОКОЛА обмена )))
Т.е. делать такой формат?
A123DT00011001001E
A - маркер адреса
D - маркер данных
E - конец данных
Ненадо никаких маркеров. Чем они будут отличаться от данных? Лучше разделять пакеты по временной паузе. Превышена пауза - значит новый пакет, т.е. первый байт пакета (адрес).
Передатчик может и заткнуться на некоторое время и потом дослать пакет, если неудачно написан ;) В принципе маркеры-то - вещь неплохая, во многих сенсорах встречаю. Только надо понять, что в преамбуле (если кто-то привык к этому слову) не должны встречаться сочетания, которые есть в остальных данных пакета. А далее все просто - размер известен, структура разложится на переменные автоматически...
Если данные в двоичном виде и в диапазоне от 0 до 255, то сочетание не выбрать.) В этом случае используется байт-стаффинг, как в SLIP, но это сложно для начинающего.) Если передатчик имеет свойство затыкаться, тогда и время паузы можно увеличить соответственно. Не так часто у нас синхронизация ведь теряется.) Либо же просто забить - пакет будет теряться во время затыка.
Ну, вобщем, в сенсорах просто два байта хидера и никаких извращений с формированием пауз. Подозреваю, что причиной тому - потенциальная возможность разогнать поток данных так, что и пауз не останется. Впрочем, выбирать не нам. Варианты озвучены.
Ждём, что скажет Евгений!
А причём тут я? ТС спросила как переслать, я подсказал. Других вопросов от ТС не поступало.
Я передаю по RS485, с паузами наверно будет проблематично, и дольше. Обратная связь у меня есть.
Т.е. делать такой формат?
A123DT00011001001E
A - маркер адреса
D - маркер данных
E - конец данных
Irinka, если верить тому коду, который Вы привели в самом начале темы, Вам достаточно передать всего 1 (прописью: "один") байт данных. В этом случае принять, "начиная не с того байта" физически невозможно. Наличие ошибок в байте Вы все равно нее проверяете, следовательно, протокол вообще не нужен.
Мне кажется, в расчете на общий случай Вашу конкретную задачу чрезмерно усложнили.
а адресат?
Уже не один байт...
Ей жеж нужно точно знать, кому, что предназначается
PS это же только В.Высоцкий раздавал своё творчество, "независимо от стипендии у кого повышенная у кого какая, чтобы каждому досталось по куску"
Я ориентировался на исходный пост темы, если на самом де6ле нужно что-то другое, то конкретное решение для этого другого случая можно попытаться сделать как в общем виде (и это наверняка займет гораздо больше ресурсов), так и в конкретно "заточенном" на данный случай.
Для начала следует выяснить, сколько бит нужно передавать. В теме было упомянуто "четырехзначное число", но по какому основанию четырехзначное? 1011 - число четырехзначное, и F0A9 - тоже четырехзначное.
Т.е. конкретно нужно знать:
- сколько раличных адресов будут использоваться (например, адрес может быть хоть 20-значный, но если выбирать нужно будет только из двух адресов - достаточно 1 бита),
- сколько различных вариантов данных нужно передавать (например, если нам нужно передавать либо "Иванов Иван Иванович" либо "Цукерман Мойша Давидович", то, опять же, достаточно только одного бита),
- нет ли корреляции между адресом и данными (например, "Иванов..." мы всегда передаем на адрес "123456789", а "Цукерман..." - всегда на адрес "987654321").
Да, да, да. Абсолютно верно.) Я тут как то ребёнку делал табло и там получилась простейшая сеть: мастер и 2 ведомых.) На всё - про всё хватило байта. И не нужно заморачиваться с протоколами, таймаутами и пр.
Решила делать с маркерами:
uint8_t addres;// от 0 до 255
uint16_t text;//Формат 1000000001 (десять символов)
uint8_t crc;
Итого 4 байта.
Получается, к примеру, A 121 T 1000000001 E 15
Маркеры A T E как добавить сюда, в переменную uint8_t и uint16_t
Зачем вам три маркера? Нужно отловить начало пакета и всё.
Зачем вам три маркера? Нужно отловить начало пакета и всё.
Значит один. Как его добавить?
Значит один. Как его добавить?
Может просто положить его на стороне передатчика в начало структуры, а на стороне приёмника пропускать всё, пока не будет пойман маркер и с этого момента начинать принимать пакет?
Значит один.
- А что такое "прокатило"?
- Значит не прокатило, вычёркиваем.)
Эx,тяжело в деревне без нагана.
Без нагана просто тяжело, хоть где.
Значит один. Как его добавить?
Может просто положить его на стороне передатчика в начало структуры, а на стороне приёмника пропускать всё, пока не будет пойман маркер и с этого момента начинать принимать пакет?
Только перед этим обязательно необходимо удостовериться, что ни один из оставшихся байтов нашего формата ни при каких условиях не может принять значение равное значению выбранного нами маркера.
Иначе и наган не поможет.
Эx,тяжело в деревне без нагана.
Так и с наганом тяжело. Пару раз было желание прихватить с собой, что бы от диких собак отстреливаться...
Так тяжелый, гад. Прям, карман оттягивает.(
Только перед этим обязательно необходимо удостовериться, что ни один из оставшихся байтов нашего формата ни при каких условиях не может принять значение равное значению выбранного нами маркера.
Я об этом уже писал - #61, но второй раз напомнить не помешает.
Только перед этим обязательно необходимо удостовериться, что ни один из оставшихся байтов нашего формата ни при каких условиях не может принять значение равное значению выбранного нами маркера.
Иначе и наган не поможет.
Есть ModBus, DMX? и полно похожих протоколов. Я использую протокол AdBus, исторически сложилось, это протокол системы сигнализации Adicon в американских тюрьмах, но в российских нетюрьмах тоже работает. Передает по 8 байт в пакете
0xFF 0xFF - старт
Адрес (0-127)
Команда (0-127)
Дата0
Дата1
Дата 2
CS -Контрольная сумма.
Полученные байты пишутся в кольцевой регистр, и по получению каждого байта анализируются на то что первые байты- 0xFF и последний байт =контрольной сумме. Как совпало - прописываем данные. Вероятность случайного совпадения точно равна нулю.
Можно делать протоколы на этой идее и меньше - в систему управления, если команд и (или) параметров мало, то можно просто FF FF data CS или FF FF data0 data1 CS.
Передает по 8 байт в пакете
...
Вероятность случайного совпадения точно равна нулю.
Так не бывает.
Если 8 байт, значит, вероятность никак не может быть меньше 5.4е-20. На самом деле - гораздо больше. Могу предположить, что порядка 1.5е-8.
Иначе и наган не поможет.
Помогает https://youtu.be/chrOu6ic6XM?t=391 - колективес мотоцикл+маска+пистолет и уже нет вопросов , причем никаких. А на любой вопрос есть одид ответ -пуля.
Так и здесь. Пусть 0хFF это байт начала. А если идет прием середины протокола и появляется 0хFF - то все что приняли ранее это труп или муссор. А дальше организовывается пакет где никогда не должно быть 0хFF. Если данные все равно нужен 0хFF , то передаем полубайтами. Сначала младший, потом старший.
Так не бывает.
Если 8 байт, значит, вероятность никак не может быть меньше 5.4е-20. На самом деле - гораздо больше. Могу предположить, что порядка 1.5е-8.
Я тестил в реальной системе (9600, 16 дивайсов, 500 м цуг) - меньше 1 сбоя (не прошла к.с.) на миллион посылок.
Одно с другим никак не связано. От слова "совсем".
Вы говорите о вероятности аппаратного сбоя, а я - о вероятности случайно сформировать пакет, который будет распознан как валидный.
Так и здесь. Пусть 0хFF это байт начала. А если идет прием середины протокола и появляется 0хFF - то все что приняли ранее это труп или муссор. А дальше организовывается пакет где никогда не должно быть 0хFF. Если данные все равно нужен 0хFF , то передаем полубайтами. Сначала младший, потом старший.
это рабочий вариант, согласен - но обрабатывать данные на предмет вхождения в них 0xFF и при необходимости удалять этот байт - имхо, лишнее усложение.
Онкель правильно говорит - для надежности делаем уникальную преамбулу из нескольких байт, скажем из 3-4х. Правда его выбор значения 0xFF не кажется мне удачным, потому что длинные цепочки 0XFF довольно часто попадаются в обычных данных. Я обычно беру набор неодинаковых байт, например 0xb707 :)
Вероятность того, что в данных попадется такая же последовательность - конечно же не нулевая, но вероятность. что и CRC в конце ошибочно распознанного пакета окажется верным - настолько близка к кнулю, что позволяет рекомендовать метод для использования в бытовых устройствах :)
Если канал не загружен и нет желания мудохаться с CRC, то мой вариант проще. Onkel-ю проще. У него все отработано.Осталось включит библиотеку в проект и все.
У Гаммона на это счет есть такой прием: https://www.gammon.com.au/forum/?id=11428 -> Error checking protocol
Там и полубайты и контроль на лету.
Еще интересней если пакеты идут разной длины. Ну например хочется или так уж вышло. Тогда наган (0xFF) идет в конце. Типо все разговор окончен. Все что в буфере с тем и разбирайся. Но тогда при инициализации отравляется пакет из одного нагана (0xFF). И тогда следущий пакет без накапливающих ошибок в приемном буфере. Но разумеется два нагана на один пакет уже пакет без шансов принять и обработать правильно.
Для пакетов разной длины ещё при телеграфе были придуманы STX/ETX.
а 0xF6 0xF6 0xF6 0x55 0x55 как преамбула чем хуже?
Для пакетов разной длины ещё при телеграфе были придуманы STX/ETX.
Никакая преамбула не хуже, если она не встречается в допустимых данных. Другое дело что на 6 байт данных эквивалентной длины преамбула избыточна, вобщем-то.
Тем более. Тогда эта тема не о чем. ТС-ше надо просто подтянуть знания, а не открывать тему о старом и известном.
Точно. Освоить кольцевые регистры - и дело с концом. А в конце- контрольная сумма.
Одно с другим никак не связано. От слова "совсем".
Вы говорите о вероятности аппаратного сбоя, а я - о вероятности случайно сформировать пакет, который будет распознан как валидный.
Да понятно. Но я о том, что если бы такой сбой произошел, он обязательно повлек бы за собой еще один сбой- следующего пакета. Поэтому мой тест говорит что ни одного неправильного пакета (или один) на миллион. Аэто значит уже можно жить. Например, передавать "жизненно важные" команды два раза, или анализировать ответ. А можно и то, и то. А По сути дело еще в том, что в 8 байтах 0xFF может быть только контрольная сумма, просто протокол такой что параметров 128, адресов 128, и параметры никогда не выставляются в 0xFF потому что 0xFF - это записано в "чистой" ЕЕPROM. И уже дело мастера сформировать пакет так, чтобы двойной FF не встречалось. Да, в самом "родном" протоколе если контрольная сумма 0xFF , то передается 0x00.
Можно ведь как в ModBUS ASCII - там начало передачи можно выделить всегда! Правда получим увеличение длины посылки. Но за все надо платить.
в дискетах потери на достоверность данных в два раза больше были и ничего )))
Онкель, та дурдом какой то. Заголовок FF FF, адрес/команда 7F 7F, данные FF FF FF, КС FF. Это макс. Но, данные не могут быть FF, КС не может быть FF - вместо них 0. Получается 0 == FF. А раз так, то 0 мы тоже не можем использовать в данных/КС. Ведь 0 это у нас FF!))) Иначе, чему верить!
Это я к тому что не бывает чудес. Или нужно жертвовать длиной пакета (заголовок, диапазон данных/кс), либо быть готовым к тому что отдельные пакеты могут быть отбракованы. Т.е., определённую кобинацию данных можно НИКОГДА не принять!
Как всё сложно....А у меня вопрос, попроще..
Перед отпракой байта данных мне его необходимо заполнить нужной информацией.
Так будет правильно?
Отправкой куда?
Отправкой куда?
Другой ардуине
sSerial.write((
char
*) & ports,
sizeof
(ports));