Чтение состояния порта в переменную

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Green пишет:

Irinka, а вот залетел к вам (в вашу сеть) один лишний байт из вне и что? Всё, накрылась ваша богодельня? Где начало, где конец, где данные, где КС...?

не, не начало и конец, а преамбула и,... )))

Green
Offline
Зарегистрирован: 01.10.2015

Вот и я про это же ж. Но ЕвгенийП расписал всё красиво, конечно, но нифига не практично.( Хоть по преамбуле ли, по таймауту ли - это ведь не сложно. А то как фишки со структорой или выводом - так пожалуйста, а как очевидные (практичные) вещи - так тишина.)

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

У меня проверка данных будет, сраниваться будут, к примеру,первый и последний символ.

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

sadman41
Offline
Зарегистрирован: 19.10.2016

Сравниваться с чем и для чего?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:

Сравниваться с чем и для чего?

она так не поймёт, надо по простому, дескать принято начало пакета формировать определённую последовательностью, к примеру хххyyy потом адрес устройства, данные, потом окончание пакета к примеру F6F6F6 и далее CRC (всё условно)

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

sadman41 пишет:

Сравниваться с чем и для чего?

У меня одно и то же количество байт передается, если пришли не все, значит ошибка, повтор отправки

sadman41
Offline
Зарегистрирован: 19.10.2016

А если начнете читать с середины, к примеру, то будет всегда приходить последних 3 байта из предыдущего пакета и первых три байта из следующего. Количество совпадает, а вот данные - бессмысленны. Нужна повторная отправка. Т.е. ещё обратную связь городить для перезапроса. Оно вам надо?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Вот так потихонечку и ненавязчиво склоним Иринку к написанию ПРОТОКОЛА обмена )))

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Т.е. делать такой формат?

A123DT00011001001E

A - маркер адреса

D - маркер данных

E - конец данных

Green
Offline
Зарегистрирован: 01.10.2015

Ненадо никаких маркеров. Чем они будут отличаться от данных? Лучше разделять пакеты по временной паузе. Превышена пауза - значит новый пакет, т.е. первый байт пакета (адрес).

sadman41
Offline
Зарегистрирован: 19.10.2016

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

Green
Offline
Зарегистрирован: 01.10.2015

Если данные в двоичном виде и в диапазоне от 0 до 255, то сочетание не выбрать.) В этом случае используется байт-стаффинг, как в SLIP, но это сложно для начинающего.) Если передатчик имеет свойство затыкаться, тогда и время паузы можно увеличить соответственно. Не так часто у нас синхронизация ведь теряется.) Либо же просто забить - пакет будет теряться во время затыка.

sadman41
Offline
Зарегистрирован: 19.10.2016

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Ждём, что скажет Евгений!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А причём тут я? ТС спросила как переслать, я подсказал. Других вопросов от ТС не поступало.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Я передаю по RS485, с паузами наверно будет проблематично, и дольше. Обратная связь у меня есть.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Irinka пишет:

Т.е. делать такой формат?

A123DT00011001001E

A - маркер адреса

D - маркер данных

E - конец данных

Irinka, если верить тому коду, который Вы привели в самом начале темы, Вам достаточно передать всего 1 (прописью: "один") байт данных. В этом случае принять, "начиная не с того байта" физически невозможно. Наличие ошибок в байте Вы все равно нее проверяете, следовательно, протокол вообще не нужен.

Мне кажется, в расчете на общий случай Вашу конкретную задачу чрезмерно усложнили.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

а адресат?
Уже не один байт...
Ей жеж нужно точно знать, кому, что предназначается
PS это же только В.Высоцкий раздавал своё творчество, "независимо от стипендии у кого повышенная у кого какая, чтобы каждому досталось по куску"

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

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

Для начала следует выяснить, сколько бит нужно передавать. В теме было упомянуто "четырехзначное число", но по какому основанию четырехзначное? 1011 - число четырехзначное, и F0A9 - тоже четырехзначное.

Т.е. конкретно нужно знать:

- сколько раличных адресов будут использоваться (например, адрес может быть хоть 20-значный, но если выбирать нужно будет только из двух адресов - достаточно 1 бита),

- сколько различных вариантов данных нужно передавать (например, если нам нужно передавать либо "Иванов Иван Иванович" либо "Цукерман Мойша Давидович", то, опять же, достаточно только одного бита),

- нет ли корреляции между адресом и данными (например, "Иванов..." мы всегда передаем на адрес "123456789", а "Цукерман..." - всегда на адрес "987654321").

Green
Offline
Зарегистрирован: 01.10.2015

Да, да, да. Абсолютно верно.) Я тут как то ребёнку делал табло и там получилась простейшая сеть: мастер и 2 ведомых.) На всё - про всё хватило байта. И не нужно заморачиваться с протоколами, таймаутами и пр.
 

// Простейший однобайтный формат: ACCDDDDD - адрес/команда/данные
#define ADR_MASK          B10000000     //маски полей
#define CMD_MASK          B01100000
#define DAT_MASK          B00011111

#define SLAVE1_ADR        B00000000
#define SLAVE2_ADR        B10000000

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Решила делать с маркерами:

uint8_t addres;// от 0 до 255

uint16_t text;//Формат 1000000001 (десять символов)

uint8_t crc;

Итого 4 байта.

Получается, к примеру, A 121 T 1000000001 15

Маркеры A T E как добавить сюда, в переменную uint8_t и uint16_t

 

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Зачем вам три маркера? Нужно отловить начало пакета и всё.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

sadman41 пишет:

Зачем вам три маркера? Нужно отловить начало пакета и всё.

Значит один. Как его добавить?

sadman41
Offline
Зарегистрирован: 19.10.2016

Irinka пишет:

Значит один. Как его добавить?

Может просто положить его на стороне передатчика в начало структуры, а на стороне приёмника пропускать всё, пока не будет пойман маркер и с этого момента начинать принимать пакет?

Green
Offline
Зарегистрирован: 01.10.2015

Irinka пишет:

Значит один. 


- А что такое "прокатило"?
- Значит не прокатило, вычёркиваем.)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Эx,тяжело в деревне без нагана.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Без нагана просто тяжело, хоть где.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

sadman41 пишет:

Irinka пишет:

Значит один. Как его добавить?

Может просто положить его на стороне передатчика в начало структуры, а на стороне приёмника пропускать всё, пока не будет пойман маркер и с этого момента начинать принимать пакет?

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

Иначе и наган не поможет.

Green
Offline
Зарегистрирован: 01.10.2015

qwone пишет:

Эx,тяжело в деревне без нагана.


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

sadman41
Offline
Зарегистрирован: 19.10.2016

andriano пишет:

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

Я об этом уже писал - #61, но второй раз напомнить не помешает.

Onkel
Offline
Зарегистрирован: 22.02.2016

andriano пишет:

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

Иначе и наган не поможет.

Есть 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.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Onkel пишет:

Передает по 8 байт в пакете

...

Вероятность случайного совпадения точно равна нулю.

Так не бывает.

Если 8 байт, значит, вероятность никак не может быть меньше 5.4е-20. На самом деле - гораздо больше. Могу предположить, что порядка 1.5е-8.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

Иначе и наган не поможет.

Помогает https://youtu.be/chrOu6ic6XM?t=391  - колективес  мотоцикл+маска+пистолет и уже нет вопросов , причем никаких. А на любой вопрос есть одид ответ -пуля. 

Так и здесь. Пусть 0хFF это байт начала. А если идет прием середины протокола и появляется 0хFF - то все что приняли ранее это труп или муссор. А дальше организовывается пакет где никогда не должно быть 0хFF. Если данные все равно нужен 0хFF , то передаем полубайтами. Сначала младший, потом старший.

Onkel
Offline
Зарегистрирован: 22.02.2016

andriano пишет:

Так не бывает.

Если 8 байт, значит, вероятность никак не может быть меньше 5.4е-20. На самом деле - гораздо больше. Могу предположить, что порядка 1.5е-8.

Я тестил в реальной системе (9600, 16 дивайсов, 500 м цуг) - меньше 1 сбоя (не прошла к.с.) на миллион посылок. 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Одно с другим никак не связано. От слова "совсем".

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

b707
Offline
Зарегистрирован: 26.05.2017

qwone пишет:

Так и здесь. Пусть 0хFF это байт начала. А если идет прием середины протокола и появляется 0хFF - то все что приняли ранее это труп или муссор. А дальше организовывается пакет где никогда не должно быть 0хFF. Если данные все равно нужен 0хFF , то передаем полубайтами. Сначала младший, потом старший.

это рабочий вариант, согласен - но обрабатывать данные на предмет вхождения в них 0xFF и при необходимости удалять этот байт - имхо, лишнее усложение.

Онкель правильно говорит - для надежности делаем уникальную преамбулу из нескольких байт, скажем из 3-4х. Правда его выбор значения 0xFF не кажется мне удачным, потому что длинные цепочки 0XFF довольно часто попадаются в обычных данных. Я обычно беру набор неодинаковых байт, например 0xb707 :)

Вероятность того, что в данных попадется такая же последовательность - конечно же не нулевая, но вероятность. что и CRC в конце ошибочно распознанного пакета окажется верным - настолько близка к кнулю, что позволяет рекомендовать метод для использования в бытовых устройствах :)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Если канал не загружен и нет желания мудохаться с CRC, то мой вариант проще. Onkel-ю проще. У него все отработано.Осталось включит библиотеку в проект и все.

sadman41
Offline
Зарегистрирован: 19.10.2016

У Гаммона на это счет есть такой прием: https://www.gammon.com.au/forum/?id=11428 -> Error checking protocol

Там и полубайты и контроль на лету.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Еще интересней если пакеты идут разной длины. Ну например хочется или так уж вышло. Тогда наган (0xFF) идет в конце. Типо все разговор окончен. Все что в буфере с тем и разбирайся.  Но тогда при инициализации отравляется пакет из одного нагана (0xFF). И тогда следущий пакет без накапливающих ошибок в приемном буфере. Но разумеется два нагана на один пакет уже пакет без шансов принять и обработать правильно.

sadman41
Offline
Зарегистрирован: 19.10.2016

Для пакетов разной длины ещё при телеграфе были придуманы STX/ETX.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

а 0xF6 0xF6 0xF6 0x55 0x55 как преамбула чем хуже?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

sadman41 пишет:

Для пакетов разной длины ещё при телеграфе были придуманы STX/ETX.

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

sadman41
Offline
Зарегистрирован: 19.10.2016

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

Onkel
Offline
Зарегистрирован: 22.02.2016

qwone пишет:

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

Точно. Освоить кольцевые регистры - и дело с концом. А в конце- контрольная сумма.

 

Onkel
Offline
Зарегистрирован: 22.02.2016

andriano пишет:

Одно с другим никак не связано. От слова "совсем".

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

Да понятно. Но я о том, что если бы такой сбой произошел, он обязательно повлек бы за собой еще один сбой- следующего пакета.  Поэтому мой тест говорит что ни одного неправильного пакета (или один) на миллион. Аэто значит уже можно жить. Например, передавать "жизненно важные" команды два раза, или анализировать ответ. А можно и то, и то. А По сути дело еще в том, что в 8 байтах 0xFF может быть только контрольная сумма, просто протокол такой что параметров 128, адресов 128, и параметры никогда не выставляются в 0xFF потому что 0xFF - это записано в "чистой"  ЕЕPROM. И уже дело мастера сформировать пакет так, чтобы двойной FF не встречалось. Да, в самом "родном" протоколе если контрольная сумма 0xFF , то передается 0x00.
Можно ведь как в ModBUS ASCII - там начало передачи можно выделить всегда! Правда получим увеличение длины посылки. Но за все надо платить.

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

в дискетах потери на достоверность данных в два раза больше были и ничего )))

Green
Offline
Зарегистрирован: 01.10.2015

Онкель, та дурдом какой то. Заголовок FF FF, адрес/команда 7F 7F, данные FF FF FF, КС FF.  Это макс. Но, данные не могут быть FF, КС не может быть FF - вместо них 0. Получается 0 == FF. А раз так, то 0 мы тоже не можем использовать в данных/КС. Ведь 0 это у нас FF!))) Иначе, чему верить!

Это я к тому что не бывает чудес. Или нужно жертвовать длиной пакета (заголовок, диапазон данных/кс), либо быть готовым к тому что отдельные пакеты могут быть отбракованы. Т.е., определённую кобинацию данных можно НИКОГДА не принять!

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Как всё сложно....А у меня вопрос, попроще..

Перед отпракой байта данных мне его необходимо заполнить нужной информацией.

uint8_t SMS[2]={B00000000,B00000000};

void setup() {
Serial.begin(9600);
}

void loop() {

//Перед отправкой заполняю нужные биты согласно неким условиям
bitWrite(SMS[0], 0, 1);
bitWrite(SMS[0], 1, 1);
bitWrite(SMS[0], 2, 1);
//...
bitWrite(SMS[0], 7, 1);
//End


Serial.println(SMS[0], BIN);
delay(500);

}//loop

Так будет правильно?

sadman41
Offline
Зарегистрирован: 19.10.2016

Отправкой куда?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

sadman41 пишет:

Отправкой куда?

Другой ардуине

sSerial.write((char *) & ports, sizeof(ports));