Стартовый бит и функция контрольной суммы
- Войдите на сайт для отправки комментариев
Добрый день!
Я новичек и ни как не пойму какой стартовый бит выбрать?
при моей структуре пакета:
struct packet_arduino_pomp //пакет Arduino nano { char start_byte;//в коротком пакете равен -32 byte temp_pomp;//температура охлаждения byte on_of_pomp;//on-off насоса (1 или 0) byte tmp;//пока не трогаем byte crv;//пока не трогаем };
стартовый бит должен быть не меньше 400, так как остальные значение могут быть в этом диапозоне, поэтому и пытаюсь отрицательное значение записхнуть. С отрицательными значениями он не хочет работать. А просто символ выбирать я считаю не корректно, но с ним работает. Посоветуйте какой стартовый бит правильно выбрать?
Теперь с контрольной суммой. Посоветуйте мне пожалуйста на один байт формулу подчета контрольной суммы? В гуглах что то сложно все.
Мой код (прошу о критике):
Мастер:
#include <SoftwareSerial.h> #define DIR 8 // переключатель прием\передача #define BUT 49 SoftwareSerial RS485 (7, 6); // RX, TX struct packet_big //пакет PC { char start_byte;//в длинном пакете равен -12 byte temp_pomp;//температура охлаждения byte on_of_pomp;//on-off насоса (1 или 0) byte ex_temp_reactor;//текущая температура в реакторе byte current_temp_reactor;//выставленная температура в реакторе byte timer_ex;//таймер byte tmp;//пока не трогаем byte crv;//пока не трогаем }; struct packet_arduino_pomp //пакет Arduino nano { char start_byte;//в коротком пакете равен -32 byte temp_pomp;//температура охлаждения byte on_of_pomp;//on-off насоса (1 или 0) byte tmp;//пока не трогаем byte crv;//пока не трогаем }; packet_big one={'H',0,0,0,0,0,0,0}; packet_arduino_pomp one_pomp = {'C',0,0,0,0}; byte buttonState=0; void setup() { Serial.begin(9600);//на PC RS485.begin(9600); // SoftwareSerial на Arduino nano pinMode(BUT, INPUT); pinMode(DIR, OUTPUT); } void loop() { buttonState = digitalRead(BUT); //кнопка digitalWrite(DIR, LOW); // включаем прием byte* ptr28 = (byte* )&one; byte *ptr_pomp =(byte*)&one_pomp; //прием с PC данных всех команд, включая информацию о температуре с реактора if (Serial.available()>sizeof(ptr28)) //возможно установить колличество байт { for (size_t i = 0; i < sizeof(packet_big)-1; i++) { byte buf_big = Serial.read(); if (buf_big == 'H')//это проверяет стартовый байт. { i = 0; ptr28[i] = buf_big ; continue;//пропускаем } ptr28[i] = buf_big ; } } //возможно нужно повторно записать стартовый бит. //прием с ардуино nano данных о вкл/ вкл насоса и температуры охлаждения if (RS485.available()>sizeof(ptr_pomp)) //возможно установить колличество байт { for (size_t i = 0; i < sizeof(packet_arduino_pomp)-1; i++) { byte buf_pump = RS485.read(); if (buf_pump == 'C')//это проверяет стартовый байт. { i = 0; ptr_pomp[i] = buf_pump;//если да, записываем вначало continue;//пропускаем } ptr_pomp[i] = buf_pump; } } if (buttonState == HIGH) //вкл/выкл от кнопки { if(one.on_of_pomp==0)//если выключен , то перезаписываем в пакете (включаем) one.on_of_pomp=1; else if(one.on_of_pomp==1)//если включен, то перезаписываем в пакете (выключаем) one.on_of_pomp=0; } // запись данных из пакета от PC в пакет от ардуино и наобарот. one.temp_pomp = one_pomp.temp_pomp; one_pomp.on_of_pomp = one.on_of_pomp; digitalWrite(DIR, HIGH); // включаем передачу Serial.write(ptr28,sizeof(packet_big)); //передаем на PC RS485.write(ptr_pomp,sizeof(packet_arduino_pomp));//передаем на Arduino nano }
Слейв:
#include <SoftwareSerial.h> #define DIR 8 // переключатель прием\передача #define ON 1 // вкл. насос #define OFF 0 // вкл. насос struct packet_arduino_pomp { char start_byte;//в коротком пакете равен -32 byte temp_pomp; byte on_of_pomp; byte tmp;//пока не трогаем byte crv;//пока не трогаем }; static packet_arduino_pomp one = {'C',0,0,0,0};;//пакет с данными byte temp_pomp = 0;//переменная для хранения температуры SoftwareSerial RS485 (7, 6); // RX, TX void setup() { Serial.begin(9600); RS485.begin(9600); // SoftwareSerial pinMode(DIR, OUTPUT); pinMode(3, OUTPUT); } void loop() { byte* ptr28 = (byte* )&one; digitalWrite(DIR, LOW); // включаем прием delay(100); if (RS485.available()>sizeof(ptr28)) { Serial.println("ON"); for (size_t i = 0; i < sizeof(packet_arduino_pomp); i++) { byte buf = RS485.read(); if (buf == 'C')//это проверяет стартовый байт. { i = 0;// если да, обнуляем счетчик ptr28[i] = buf; Serial.println(ptr28[i]); continue;//пропускаем } ptr28[i] = buf; Serial.println(ptr28[i]); } Serial.println("END"); } if(one.on_of_pomp==ON) // включим клапан { digitalWrite(3, HIGH); // включим клапан } else if (one.on_of_pomp==OFF) digitalWrite(3, LOW); //тут обработка датчика температуры вместо random // temp_pomp = 55; one.temp_pomp=55;//записываем значение температуры охлаждения в пакет на отправку digitalWrite(DIR, HIGH); // включаем передачу RS485.write(ptr28,sizeof(packet_arduino_pomp)); //отправляем }
Пока плохо работает, поэтому подумал начать со структуры пакета.
Суть такая: Один пакет (большой, который несет всю информацию) будет между Ардуино Мега и PC(написана программа на Qt), второй пакет маленький , между Ардуино нано и Мега ( несет информацию о включение-выключение насоса и температуре с датчика). Пока хочу сделать чтобы мега управляла нано ( с кнопки отправляла сигнал о включении насоса), а нано в ответку отправляла данные о температуре. Дальше мега собирает все данные , записывает в пакет для PC и отправляет. А PC читает, и если изменения какие то внесены с PC, заполняет этот же пакет и отправляет обратно... мега читает, расчленяет его и отправлет нано ...и т.д.
Тоесть мастером будет Pc, но если его отлючить от Меги, хочу чтобы она самостоятельная была( позже сделать экранчик с кнопаками).
Посмотрите , может какие то грубые ошибки найдете, я только учусь)
Заранее спасибо!
определитесь с терминами.
Бит не может быть ни отрицательным, ни "больше 400". Бит - это только 0 или 1. Судя по контексту у вас имеется в виду байт. Так вот, байт тоже не может быть более 400, его максимальное значение 255.
Насчет того, может ли char быть отрицательными - недавно была огромная дискуссия. Я не хочу вызвать флейм вновь, но советовал бы вам рассматривать char как синоним byte - то есть с диапазоном 0-255
Самая простая контрольная сумма - просто 8-битное побайтное сложение всех данных в пакете, за исключением самой суммы.
Код не смотрел, если с ним у вас проблемы - формулируйте вопросы яснее.
Да, пардон, всегда путаюсь -бит-байт.
Смысл считать данные всего пакета, если пакет меняется. Нужно же статичное значение ?
Еще одно небольшое добавление - разберитесь, как компьютер представляет отрицательные числа. Знаковое -32 и беззнаковое 223 в двоичном коде выглядят одинаково, так что если вы пытаетесь с помощью отрицательных чисел задать "уникальное" значение стартового байта - затея обречена на провал. Ничего "уникального" в значении -32 для компьютера нет.
Смысл считать данные всего пакета, если пакет меняется. Нужно же статичное значение ?
Контрольная сумма используется, как раз чтобы отследить изменение данных в пакете.
Все все, я что то не выспался))) Тогда какой стартовый бит лучше выбрать? с контрольной суммой я понял, ок. Может два стартновых байта, чтобы точно все ок?
Да, пардон, всегда путаюсь -бит-байт.
не путайся. Бит это байт минус налоги.
Все все, я что то не выспался))) Тогда какой стартовый бит лучше выбрать? с контрольной суммой я понял, ок. Может два стартновых байта, чтобы точно все ок?
Можно и больше. Я так понимаю, что для вас главное, чтобы получившаяся последовательность не встречалась в данных. Иногда для этого приходится дополнительно кодировать данные, чтобы исключить появление в них управляющих кодов, типа заголовка пакета.
Типо стартовый байт =210, а все данные делим на 2, а про приему умножаем? Но как же потяря точности ? Делим, получается с запятой значение, оно в байтовой переменной обрязается, а когда умножается, полчается другое значение?
Типо стартовый байт =210, а все данные делим на 2, а про приему умножаем? Но как же потяря точности ? Делим, получается с запятой значение, оно в байтовой переменной обрязается, а когда умножается, полчается другое значение?
Это не единственный метод. Как вариант - все данные, кроме 210, передаем как есть, а 210 заменяем на пару байт 210-210. Тогда при приеме одинарный 210 - это заголовок пакета, а двойной - это данные. (правда, надо следить, чтобы второй байт пакета не был 210 - но это обычно проще, чем перекодировать все данные)
Ничего не понял, псевдокод можите набросать пожалуйста?
Смысл в том, что вы перекодируете не все данные в пакете, а только значение 210.
Или вообще его исключаете. Например, возьмем стартовый байт 255. Значения в пакете в диапазоне 0-254 передаются как есть, а вместо 255 передаем 254. Потеря точности мизерна, стартовый байт уникален.
Если все еще непонятно, псевдокод пусть кто другой накропает - я на работе, знаете ли, нет времени :)
Зачем такие сложности при таком простом обмене? Реализуйте подобие интерфейса общения и все. Т.е. сначала идет команда и ждете ответа, сравниваете црц. Например, отправляете с меги на нано 0х10, нано получается байт и переходит в режим ожидания пакета известного размера. Все последующие байты считаются данными. Когда все получено считаем црц. Мега так же сидит и ждет команды, нано выдает 0х10 мега переходит в режим приема данных и т.д. Даже если размер структуры будет не известен (а у вас он известен) то можно первым байтом выдавать размер.
Пока набросал с двумя стартовыми битами. Не думаю что высока вероятность попадания подряд таких чиселю. Посмотрите коД, я правильно мыслю?
Это Слейв.
Просто я на будущее, дальше надо будет подключить к меге китайский контроллер температуры, который общается по своему протоколу, так как пока его нет, хотелось бы сделать по максисуму работы.
Для посчета контрольной суммы структура пакета должна быть такой.
а глобальная CRC8 нахрена?
и вапще, откройте для себя avr\crc16.h там всё есть
Как я понял это член структуры, а дальше метод. Хорошо спасибо) По стартовым битам не совсем уродски я сделал?
А по контрольной сумме я правильно понимаю, приходит пакет, я его считываю, потом подставляю в ту же формулу данные которые я принял и сверяю с принятой контрольной суммой, если они разные , этот пакет пропускаю, жду другого ? Правильно?
Где вы видите глобальную CRC8. Она же лежит в пакете . Не нравится CRC8 пусть будет CRC16. Немного аналогии. К вам домой пришла посылка. Вопрос как проверить вскрывали посылку или нет. Разумеется проверить упаковку. Упаковка , как это знучит не странно, приходит с посылкой, а не лежит глобально на почте. Вот контрольная сумма это и есть упаковка. Если она верна, то пакет верен. Итак привожу итоги. В любом пакете должна быть сама информация , контрольная сумма и две функции упаковать (подсчитать и записать контрольную сумму) и проверка самой контрольной суммы. Если в пакет перед отправкой вы засунули информацию, то должны дать команду упаковать. А если получили свежий пакет, то проверить упаковку. Если упаковка "вскрыта", то требуйте новый пакет.
ПС:упрощенно где то так
Товарищи, танцевал с бубном весь вечер. Нано принемает пакеты и читает их от Меги, но проблема в том, что когда нано прочитала, она отправляет обратно пакет с внесенными изменениями. И в Мастере(Мега) не хочет читаться ничего. Прошу помочь, сам не вижу ошибки.
Мастер (Аржуино Мега):
Слейв:
Вместо CRC8 CRC16 вполне можно было ограничится просто суммой 8 или 16 битной, там на несколько процентов ухудшается распознование ошибок, а код проще намного. В DCON так сделано.
И это не CRC (она сложнее), а просто контрольная сумма
CRC8 = data1 + data2 + data3 +...
Не могу понять принцип , в том плане, где ставить delay. Может в этом причина. То ли нано не отправляет пакет, потому что в меге в if:
не входит. Я убирал условие, все равно ни одного байта не приходит. А отправляет он исправно, нано исправно принимает.....
Может есть какие то идеи или я что то грубо не вижу и не знаю.....
delay в таких вещах вообще нигде не нужен. Забудетесь, начнете в код с SoftSerial делеи лепить и порастеряете все, что вам шлют.
Самый простой способ упорядочить в голове этот алгоритм в данном случае - использовать "машину состояний". Она отлично справляется с анализом входящего пакета на лету.
А так.. вы же сами понимаете, где ошибки - комментируете даже:
Типо написать Case конечный автомат, с несколькими состаяними : Прием пакета, первый стартовый бит, второй стартовый бит, принятие информации, проверка контрольной суммы? По образу :http://www.devexp.ru/2011/02/konechnye-avtomaty-v-c/
А по поводу проверки контрольной суммы, у меня вообще стоит:
Если меняю на
То ересь начинает приходить и прием спатыкаться начинает.
Вопрос то в другом, почему мега ничего не принемает, вообще ничего.
А если delay убрать, то нано вообще ничего не принемает. Короче я в отчаянии, мне еще Мегу надо к Qt проге подрубить, которая уже есть.....
Просто по логике, вроде все просто. Мега шлет пакет, нано ждет пакет, принемает его. Делает действия в зависимости от содержания пакета, записывает в него свои данные и отправляет. В это время Мега ждет приема, принемает, записывает значения в пакет для Pc и отправляет.
И зачем конечный автомат , тут же пакет коротки и не проще ли его так как я сделал прочитать, в цикле?
У вас на слэйве 51й строкой открывается if и закрывается на 81 (код из поста 20) а потом вы смотрите что там с клапанами в пакете, который возможно даже не получили. Потом передаете пакет и возвращаетесь в начало луп где снова задаете указатель на структуру ждете 200мс и по кругу. Это так и задумано? )
То что не проверил получил ли я пакет или нет, да, исправлю, внесу это в if который начинается на 51 строке. А дальше что не так? Вы хотите сказать что этот указатель глабально надо обьявить?
А если delay убрать, то нано вообще ничего не принемает.
Очень странно, данные не должны пропадать, они лежат в буфере пока не считают их... то же самое с передачей данных.
Почему Мега ни чего не принимает , вот в чем вопрос. Все красивости я допилю потом(конечне автоматы и т.д.), когда будет более менее работать код. А на данный момент подозрения что я не в том порядке что то делаю и канал занимается мегой, но на отправку, а нано не успевает запихнуть ничего в него. Возможно такое?
Сейчас для интереса попробовал мега+уно. Сначала с софтверными сериала и там затыки были периодически, на аппаратных сериалах все четко идет. Зачем вы на меге используете софтверный порт когда там 4ре аппаратных, ну и на нано можно использовать аппаратный, а отлаживаться по софтверному или через мегу отлаживаться.
Вечером попробую контакты перекинуть! Спасибо большое!
Я просто думал что какаяразница и сделал на софтверном сериале. Но не первый раз слышу что разница есть....
Да и тем более я не на те пины закинул:
Среди известных ограничений библиотеки SoftwareSerial можно перечислить следующие:
Это не танцы с бубном, а клоуны в цирке. Изучите как устроена Сетевая модель OSI. Вы решаете на Канальном уровне то что должно решаться на Сетевом уровне. Проще говоря у вас нет Сетевого уровня. От туда все проблемы.
А можно поконкретнее...
Я немного перепутал. Прикладной уровень- это вы программе пишете строчку похожую Serial.print("sdsfsf"), или Led.ON(): И так далее. Представительский уровень это все упаковывается в пакет в котором откуда, куда, что передать(что сделать), время отправления и контрольная сумма. Сеансовый уровень это отправка пакета через посредников получателю(почта - отдел работы с клиентом) Общение с клентом служебными пакетами и получение , отправление главного пакета. Транспортный , сетевой ,канальный скорее объедены тоже самое но обмен идет через посредников минуя клиентов. Прикладной это уже железо и работа с ним.
Это вообще не по теме. Человек контакты перепутал, а вы читаете громоздкий академический курс по сетевой модели, который кроме университетов никому даром не нужен, так как далек от жизни. Все равно что начать с того что гравитация Луны притягивает электроны сильнее, чем гравитация Марса и это нужно точно расчитать :)
Обычно упрощают всё до нижнего уровня (железо) и верхнего уровня (программа), тут этого достаточно.
Даже в Википедии есть упоминание:
Пока комитеты ISO спорили о своих стандартах, за их спиной менялась вся концепция организации сетей и по всему миру внедрялся протокол TCP/IP.
…
И вот, когда протоколы ISO были наконец реализованы, выявился целый ряд проблем:
…
Сейчас даже самые ярые сторонники этих протоколов признают, что OSI постепенно движется к тому, чтобы стать маленькой сноской на страницах истории компьютеров. — Эви Нэмет
Он поможет вам привести мысли в порядок. А то bool функция, возвращающая -1 попахивает неэвклидовой геометрией.
Понятно,тупеет народ, а тупому быдлу фундаментальные знания ни к чему. Сеть она многослойная. И разумеется терминология расплывчатая.
Или наоборот, умнее, и народ сходу отсекает демагогию. Практик сделал устройство, с телефона управляет поливом теплицы и всё работает. Тут приходит демагог и начинает, где у вас прикладной уровень, а где представительский? :)
Знаем мы таких практиков. Каждый раз новая тема :помогите новичку , ему нужно
сделать миньетнаписать скетч . Он блин практик, а демагогии в виде ,как писать код ему не нужны, даже если у него скеч спизженый на просторах инета не работает.у него скеч спизженый на просторах инета не работает.
я же запретил пиздить нерабочие скетчи. ¯\_(ツ)_/¯
Поменял пины на меге, все равно не пашет. Нано принемает все хорошо, а вот мега принемать ни единого пакета не хочет. Еще раз приведу код, я там кое что изменил.
qwone- я таких спецов как Вы , на "Х.. вертел", код не ворованый, в том то и дело. Если какашки лезут, прошу какашки извергать в других темах или лучше у себя дома.
Возвращаясь к теме, не могу понять нано не отправляет или мега не принемает. Без delay не работает, прием в штопор уходит.
Мега:
Нано:
Все заработало, после плясками с delay, расставил , все ок.