Стартовый бит и функция контрольной суммы
- Войдите на сайт для отправки комментариев
Добрый день!
Я новичек и ни как не пойму какой стартовый бит выбрать?
при моей структуре пакета:
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 мега переходит в режим приема данных и т.д. Даже если размер структуры будет не известен (а у вас он известен) то можно первым байтом выдавать размер.
Пока набросал с двумя стартовыми битами. Не думаю что высока вероятность попадания подряд таких чиселю. Посмотрите коД, я правильно мыслю?
Это Слейв.
#include <SoftwareSerial.h> #define DIR 8 // переключатель прием\передача #define ON 1 // вкл. насос #define OFF 0 // вкл. насос struct packet_arduino_pomp //пакет Arduino nano { byte start_byte_one;//в коротком пакете равен 212 byte start_byte_two;//в коротком пакете равен 211 byte temp_pomp;//температура охлаждения byte on_of_pomp;//on-off насоса (1 или 0) byte tmp;//пока не трогаем byte crv;//пока не трогаем }; static packet_arduino_pomp one = {212,211,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"); byte buf_pump = RS485.read(); if (buf_pump == 212) { buf_pump = RS485.read(); if (buf_pump == 211) { ptr28[0] = 212; ptr28[1] = buf_pump; Serial.println(ptr28[0]); Serial.println(ptr28[1); for (size_t i = 2; i < sizeof(packet_arduino_pomp)-1; i++) { buf_pump = RS485.read(); ptr28[i] = buf_pump; Serial.println(ptr28[i]); } Serial.println("END"); } } /*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)); //отправляем }Просто я на будущее, дальше надо будет подключить к меге китайский контроллер температуры, который общается по своему протоколу, так как пока его нет, хотелось бы сделать по максисуму работы.
Для посчета контрольной суммы структура пакета должна быть такой.
struct packet_arduino_pomp {//пакет Arduino nano byte start_byte_one;//в коротком пакете равен 212 byte start_byte_two;//в коротком пакете равен 211 byte temp_pomp;//температура охлаждения byte on_of_pomp;//on-off насоса (1 или 0) byte tmp;//пока не трогаем byte crv;//пока не трогаем //-- byte CRC8;//контрольная сумма byte get_CRC() { byte CRC = 0; /*подсчитать конрольную сумму*/ CRC8 = CRC; return CRC; } };а глобальная CRC8 нахрена?
и вапще, откройте для себя avr\crc16.h там всё есть
Как я понял это член структуры, а дальше метод. Хорошо спасибо) По стартовым битам не совсем уродски я сделал?
А по контрольной сумме я правильно понимаю, приходит пакет, я его считываю, потом подставляю в ту же формулу данные которые я принял и сверяю с принятой контрольной суммой, если они разные , этот пакет пропускаю, жду другого ? Правильно?
Где вы видите глобальную CRC8. Она же лежит в пакете . Не нравится CRC8 пусть будет CRC16. Немного аналогии. К вам домой пришла посылка. Вопрос как проверить вскрывали посылку или нет. Разумеется проверить упаковку. Упаковка , как это знучит не странно, приходит с посылкой, а не лежит глобально на почте. Вот контрольная сумма это и есть упаковка. Если она верна, то пакет верен. Итак привожу итоги. В любом пакете должна быть сама информация , контрольная сумма и две функции упаковать (подсчитать и записать контрольную сумму) и проверка самой контрольной суммы. Если в пакет перед отправкой вы засунули информацию, то должны дать команду упаковать. А если получили свежий пакет, то проверить упаковку. Если упаковка "вскрыта", то требуйте новый пакет.
ПС:упрощенно где то так
struct pasket { byte data1; byte data2; byte data3; //--- byte CRC8;//контрольная сумма /*упаковать*/ void pask() { CRC8 = data1 + data2 + data3; } /*проверка упаковки*/ bool test pask() { if (CRC8 == (data1 + data2 + data3)) return 0; //ОК return -1; // ошибка } };Товарищи, танцевал с бубном весь вечер. Нано принемает пакеты и читает их от Меги, но проблема в том, что когда нано прочитала, она отправляет обратно пакет с внесенными изменениями. И в Мастере(Мега) не хочет читаться ничего. Прошу помочь, сам не вижу ошибки.
Мастер (Аржуино Мега):
#include <SoftwareSerial.h> #define DIR 8 // переключатель прием\передача #define BUT 49 SoftwareSerial RS485 (7, 6); // RX, TX struct packet_big //пакет PC { byte start_byte_one;//в длинном пакете равен 254 byte start_byte_two;//в длинном пакете равен 232 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 { byte start_byte_one;//в коротком пакете равен 212 byte start_byte_two;//в коротком пакете равен 211 byte temp_pomp;//температура охлаждения byte on_of_pomp;//on-off насоса (1 или 0) byte tmp;//пока не трогаем byte CRC8;//пока не трогаем /*упаковать*/ void pask() { CRC8 = (start_byte_one + start_byte_two + temp_pomp+on_of_pomp+tmp)/10; } /*проверка упаковки*/ bool test_pask() { if (CRC8 == (start_byte_one + start_byte_two + temp_pomp+on_of_pomp+tmp)/10) return 0; //ОК return -1; // ошибка } }; packet_big one= {254,232,0,0,0,0,0,0,0}; packet_arduino_pomp one_pomp = {212,211,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); //кнопка byte* ptr28 = (byte* )&one; byte *ptr_pomp =(byte*)&one_pomp; 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; } one_pomp.on_of_pomp = one.on_of_pomp; digitalWrite(DIR, HIGH); // включаем передачу // Serial.write(ptr28,sizeof(packet_big)); //передаем на PC one_pomp.pask(); RS485.write(ptr_pomp,sizeof(packet_arduino_pomp));//передаем на Arduino nano delay(200); digitalWrite(DIR, LOW); // включаем прием //прием с PC данных всех команд, включая информацию о температуре с реактора if (Serial.available()>sizeof(packet_big)) //возможно установить колличество байт { byte buf_big = Serial.read(); if (buf_big == 254) { buf_big = Serial.read(); if (buf_big == 232) { ptr28[0] = 254; ptr28[1] = buf_big; for (size_t i = 2; i < sizeof(packet_big); i++) { buf_big = Serial.read(); ptr28[i] = buf_big ; } } } } //возможно нужно повторно записать стартовый бит. //прием с ардуино nano данных о вкл/ вкл насоса и температуры охлаждения if (RS485.available()) //возможно установить колличество байт { byte buf_pump = RS485.read(); if (buf_pump == 212) { buf_pump = RS485.read(); if (buf_pump == 211) { Serial.println('a'); for (size_t i = 2; i < sizeof(packet_arduino_pomp); i++) { buf_pump = RS485.read(); ptr_pomp[i] = buf_pump; if(i==sizeof(packet_arduino_pomp)-1) { if(one_pomp.test_pask()) { i=0; } } } } } } /* Serial.println("ON"); for(size_t i = 0; i < sizeof(packet_arduino_pomp); i++) { Serial.println(ptr_pomp[i]); } Serial.println("END");*/ // запись данных из пакета от PC в пакет от ардуино и наобарот. // one.temp_pomp = one_pomp.temp_pomp; }Слейв:
#include <SoftwareSerial.h> #define DIR 8 // переключатель прием\передача #define ON 1 // вкл. насос #define OFF 0 // вкл. насос struct packet_arduino_pomp //пакет Arduino nano { byte start_byte_one;//в коротком пакете равен 212 byte start_byte_two;//в коротком пакете равен 211 byte temp_pomp;//температура охлаждения byte on_of_pomp;//on-off насоса (1 или 0) byte tmp;//пока не трогаем byte CRC8;//пока не трогаем /*упаковать*/ void pask() { CRC8 = (start_byte_one + start_byte_two + temp_pomp+on_of_pomp+tmp)/10; } /*проверка упаковки*/ bool test_pask() { if (CRC8 == (start_byte_one + start_byte_two + temp_pomp+on_of_pomp+tmp)/10) return 0; //ОК return -1; // ошибка } }; static packet_arduino_pomp one = {212,211,0,0,0,0};//пакет с данными byte temp_pomp = 0;//переменная для хранения температуры SoftwareSerial RS485 (2, 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(200); if (RS485.available()) { byte buf_pump = RS485.read(); if (buf_pump == 212) { buf_pump = RS485.read(); if (buf_pump == 211) { ptr28[0] = 212; ptr28[1] = buf_pump; for (size_t i = 2; i < sizeof(packet_arduino_pomp); i++) { buf_pump = RS485.read(); ptr28[i] = buf_pump; if(i==sizeof(packet_arduino_pomp)-1) { if(one.test_pask()) { i=0; } } } } } Serial.println("ON"); for(size_t i = 0; i < sizeof(packet_arduino_pomp); i++) { Serial.println(ptr28[i]); } Serial.println("END"); } one.temp_pomp=55;//записываем значение температуры охлаждения в пакет на отправку if(one.on_of_pomp==ON) // включим клапан { digitalWrite(3, HIGH); // включим клапан } else if (one.on_of_pomp==OFF) digitalWrite(3, LOW); //тут обработка датчика температуры вместо random // temp_pomp = 55; digitalWrite(DIR, HIGH); // включаем передачу RS485.write(ptr28,sizeof(packet_arduino_pomp)); //отправляем }Вместо CRC8 CRC16 вполне можно было ограничится просто суммой 8 или 16 битной, там на несколько процентов ухудшается распознование ошибок, а код проще намного. В DCON так сделано.
И это не CRC (она сложнее), а просто контрольная сумма
CRC8 = data1 + data2 + data3 +...Не могу понять принцип , в том плане, где ставить delay. Может в этом причина. То ли нано не отправляет пакет, потому что в меге в if:
не входит. Я убирал условие, все равно ни одного байта не приходит. А отправляет он исправно, нано исправно принимает.....
Может есть какие то идеи или я что то грубо не вижу и не знаю.....
delay в таких вещах вообще нигде не нужен. Забудетесь, начнете в код с SoftSerial делеи лепить и порастеряете все, что вам шлют.
Самый простой способ упорядочить в голове этот алгоритм в данном случае - использовать "машину состояний". Она отлично справляется с анализом входящего пакета на лету.
А так.. вы же сами понимаете, где ошибки - комментируете даже:
bool test_pask() { ... return -1; // ошибка }Типо написать Case конечный автомат, с несколькими состаяними : Прием пакета, первый стартовый бит, второй стартовый бит, принятие информации, проверка контрольной суммы? По образу :http://www.devexp.ru/2011/02/konechnye-avtomaty-v-c/
А по поводу проверки контрольной суммы, у меня вообще стоит:
if(one.test_pask()) { i=0; }Если меняю на
if(!one.test_pask()) { i=0; }То ересь начинает приходить и прием спатыкаться начинает.
Вопрос то в другом, почему мега ничего не принемает, вообще ничего.
А если 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 не работает, прием в штопор уходит.
Мега:
#include <SoftwareSerial.h> #define DIR 8 // переключатель прием\передача #define BUT 49 struct packet_big //пакет PC { byte start_byte_one;//в длинном пакете равен 254 byte start_byte_two;//в длинном пакете равен 232 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 { byte start_byte_one;//в коротком пакете равен 212 byte start_byte_two;//в коротком пакете равен 211 byte temp_pomp;//температура охлаждения byte on_of_pomp;//on-off насоса (1 или 0) byte tmp;//пока не трогаем byte CRC8;//пока не трогаем /*упаковать*/ void pask() { CRC8 = (start_byte_one + start_byte_two + temp_pomp + on_of_pomp + tmp) / 10; } /*проверка упаковки*/ bool test_pask() { if (CRC8 == (start_byte_one + start_byte_two + temp_pomp + on_of_pomp + tmp) / 10) return 0; //ОК return -1; // ошибка } }; packet_big one = {254, 232, 0, 0, 0, 0, 0, 0, 0}; packet_arduino_pomp one_pomp = {212, 211, 0, 0, 0, 0}; byte buttonState = 0; void setup() { Serial.begin(9600);//на PC Serial2.begin(9600); // SoftwareSerial на Arduino nano pinMode(BUT, INPUT); pinMode(DIR, OUTPUT); } void loop() { digitalWrite(DIR, HIGH); // включаем передачу buttonState = digitalRead(BUT); //кнопка byte* ptr28 = (byte* )&one; byte *ptr_pomp = (byte*)&one_pomp; 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; } one_pomp.on_of_pomp = one.on_of_pomp; // Serial.write(ptr28,sizeof(packet_big)); //передаем на PC one_pomp.pask(); Serial2.write(ptr_pomp, sizeof(packet_arduino_pomp)); //передаем на Arduino nano delay(100); digitalWrite(DIR, LOW); // включаем прием //прием с PC данных всех команд, включая информацию о температуре с реактора if (Serial.available() > sizeof(packet_big)) //возможно установить колличество байт { byte buf_big = Serial.read(); if (buf_big == 254) { buf_big = Serial.read(); if (buf_big == 232) { ptr28[0] = 254; ptr28[1] = buf_big; for (size_t i = 2; i < sizeof(packet_big); i++) { buf_big = Serial.read(); ptr28[i] = buf_big ; } } } } //возможно нужно повторно записать стартовый бит. //прием с ардуино nano данных о вкл/ вкл насоса и температуры охлаждения if (Serial2.available() >= sizeof(packet_arduino_pomp)) { byte buf_pump = 0; for (size_t i = 0; i < sizeof(packet_arduino_pomp); i++) { Serial.println("1"); if (i == 0 && (buf_pump = Serial2.read()) != 212) { Serial.println("2"); i = 0; continue; } if (i == 1 && (buf_pump = Serial2.read()) != 211) { Serial.println("3"); i = 0; continue; } if (i >= 2) { Serial.println("4"); buf_pump = Serial2.read(); ptr_pomp[i] = buf_pump; if (i == sizeof(packet_arduino_pomp) - 1) { Serial.println("5"); if (one_pomp.test_pask()) //проверяем контрольную сумму { Serial.println("6"); i = 0; continue; } } } } Serial.println("ON"); for (size_t i = 0; i < sizeof(packet_arduino_pomp); i++) { Serial.println( ptr_pomp[i]); } Serial.println("END"); } // запись данных из пакета от PC в пакет от ардуино и наобарот. // one.temp_pomp = one_pomp.temp_pomp; }Нано:
#include <SoftwareSerial.h> #define DIR 8 // переключатель прием\передача #define ON 1 // вкл. клапан #define OFF 0 // вкл. клапан struct packet_arduino_pomp //пакет Arduino nano { byte start_byte_one;//в коротком пакете равен 212 byte start_byte_two;//в коротком пакете равен 211 byte temp_pomp;//температура охлаждения byte on_of_pomp;//on-off насоса (1 или 0) byte tmp;//пока не трогаем byte CRC8;//пока не трогаем /*упаковать*/ void pask() { CRC8 = (start_byte_one + start_byte_two + temp_pomp+on_of_pomp+tmp)/10; } /*проверка упаковки*/ bool test_pask() { if (CRC8 == (start_byte_one + start_byte_two + temp_pomp+on_of_pomp+tmp)/10) return 0; //ОК return -1; // ошибка } }; static packet_arduino_pomp one = {212,211,0,0,0,0};//пакет с данными byte temp_pomp = 0;//переменная для хранения температуры SoftwareSerial RS485 (2, 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); // включаем прием if (RS485.available()>= sizeof(packet_arduino_pomp)) { byte buf_pump=0; for (size_t i = 0; i < sizeof(packet_arduino_pomp); i++) { Serial.println("1"); if(i==0&&(buf_pump = RS485.read())!=212) { Serial.println("2"); i=0; continue; } if(i==1&&(buf_pump = RS485.read())!=211) { Serial.println("3"); i=0; continue; } if(i>=2) { Serial.println("4"); buf_pump = RS485.read(); ptr28[i] = buf_pump; if(i==sizeof(packet_arduino_pomp)-1) { Serial.println("5"); if(one.test_pask())//проверяем контрольную сумму { Serial.println("6"); i=0; continue; } } } } Serial.println("ON"); for(size_t i = 0; i < sizeof(packet_arduino_pomp); i++) { 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); } one.temp_pomp = 55;//записываем значение температуры охлаждения в пакет на отправку one.pask();//формируем контрольную сумму digitalWrite(DIR, HIGH); // включаем передачу RS485.write(ptr28,sizeof(packet_arduino_pomp)); }Все заработало, после плясками с delay, расставил , все ок.