Официальный сайт компании Arduino по адресу arduino.cc
Структура через последовательный порт
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Пт, 06/10/2017 - 09:36
Добрый день!
У меня Ардуино мега и нано. Сначала заставил простым вещам , мигать светодиодом .
мастер:
#include <SoftwareSerial.h> #define DIR 8 // переключатель прием\передача SoftwareSerial RS485 (7, 6); // RX, TX struct namer{ char one; char two[6]= "Maxim"; int a; }; void setup(){ Serial.begin(9600); RS485.begin(4800); // SoftwareSerial pinMode(DIR, OUTPUT); digitalWrite(DIR, HIGH); // включаем передачу } void loop(){ namer onetwo; byte id = random(1, 3); RS485.write(id); // отправляем первый байт, в нем ID RS485.println(onetwo.two); Serial.print(id); Serial.print(" "); Serial.print(id); Serial.print(onetwo.two); delay(500); }
слейв
#include <SoftwareSerial.h> #define DIR 8 // переключатель прием\передача #define ID 1 // номер ардуины struct namer{ char one; char two[6]={0}; int a; }; SoftwareSerial RS485 (7, 6); // RX, TX void setup(){ Serial.begin(9600); RS485.begin(4800); // SoftwareSerial pinMode(DIR, OUTPUT); pinMode(3, OUTPUT); digitalWrite(DIR, LOW); // включаем прием } void loop(){ namer onetwo; if (RS485.available() > 0) { byte id = RS485.read(); // читаем байт, в нем для кого этот пакет if (id == ID){ // и если пакет пришел нам //digitalWrite(3, HIGH); // мигнем диодом // digitalWrite(3, LOW); RS485.readBytes(onetwo.two,5); digitalWrite(3, HIGH); // мигнем диодом delay(100); digitalWrite(3, LOW); Serial.print(" "); Serial.print(id); Serial.print(" "); Serial.print(onetwo.two); Serial.print(" "); } else RS485.flush(); // если не нам, очищаем буфер } }
Но в итоге мне надо передать стуктуру, мучаюсь, ничего не получается... Подскажите как это делать? Желательно с примерами
На структуру умеете взять указатель? Приведите его к типу uint8_t* и пробегитесь по памяти, начиная с него, на дистанцию размера структуры. Т.е. представьте его массивом, который можно побайтно передавать. На другой стороне примите в массив и посмотрите на него через указатель на вашу структуру (namer или number?).
Скромное имхо:
У Вас слейв Нано? Если да, то строчку
SoftwareSerial RS485 (7, 6);
// RX, TX
Надо заменить на, скажем ,
SoftwareSerial RS485 (2, 6);
// RX, TX
И подавать сигнал именно на 2й пин. SoftwareSerial работает по прерыванию, поэтому RX надо определять либо на 2й , либо на 3й пин.
И зачем на Меге использовать SoftwareSerial, если там и так UART портов навалом!
Первый совет точно такой же, как написал sadman41.
Но если хотите выпендриться и сделать правоверно-ООПно, то определите в своей структуре метод для вывода в поток, а потом просто пихайте её в поток обычным Serial.print. Как это делается, с примерами, можно посмотреть вот здесь.
RX надо определять либо на 2й , либо на 3й пин.
Да, нет, он работает с PCINT, а эти прерывания на любом пине есть.
А можите этот участок кода набросать ?
Да, нет, он работает с PCINT, а эти прерывания на любом пине есть.
Внимания на это не обращал, но сейчас глянул в исходник - действительно на доступные PCINT-ы вешается. Выходит так, что SoftSerial отвлекает МК на любое внешнее изменение любого пина и дает оверхед.
Типо того ? код просто в кодблоксе написан, не под ардуино.
А читать Serial.read просто? А куда? В массив? но как его потом чатать ?
Или в мастере я привожу структуру к указателя на uint8_t*, передаю в цикле каждый байт, а читаю в uint8_t массив[sizeof(структура)] и потом привожу его к указателю структуры и уже разыменовывыю: структура-> данные.
Примерно так, навскидку:
Скармливать любой наследник Stream, например:
Получать:
DIYMan, Вы вернёте флаг, что структура прочитана не тогда, когда прочитан последний её байт, а только тогда, когда в сериал придёт какой-то следующий после структуры байт. А если не придёт?
м.б.
Ну, предположите, что структура имеет длину 1 байт. Тогда справа от >= у Вас ноль, т.е. Вы вообще ничего читать не будете.
Ну да, писал навскидку, поправить - дело полминуты ;) Достаточно поменять проверку и чтение местами:
Отталкиваясь от твоего примера, родил вот такой код, мастер отправляет, слев читает, но читает криво, так что в переменной структуры походу перезаписываются данные все время, или я куда да то вылезаю.... посмотрите пожалуйста, устал, голова уже пухнет))А на работе еще отвлекают))
Мастер:
Короче не судите строго, я запутался.
Натыкайте в приемник Serial.print-ов и посмотрите - те ли байты и в том ли порядке доходят, в котором отправляются.
Ковыряюсь, ничего не выходит. Подумал тут, а как слейв будет понимать с какого бита считать начало структуры? у меня в этом и проблема, что каждый раз он в разную переменную записывает значения. Может в структуру поместить какой нибудь стартовый бит типо byte start=-1? У меня подозрения что из за этого слей не понимает когда ему надо читать начинать и читает когда может, а мастер потоком шлет структуру за структурой.
Естественно, нужен какой-то способ синхронизации. Выбирайте такой символ или последовательность, которая не будет встречаться в нормальных данных. Ловите его/ee, начинаете читать пакет.
А есть пример какой нибудь организации структуры для таких целей? Может вообще на битовые поля переключится? Как правильно просто хочется знать? Пилить велосипед полезно, но не всегда хорошо. Заранее спасибо.
Проблема тут:
Хинт - почему вы уверены, что в буфере приёма БОЛЬШЕ 1 байта?
А есть пример какой нибудь организации структуры для таких целей? Может вообще на битовые поля переключится? Как правильно просто хочется знать? Пилить велосипед полезно, но не всегда хорошо. Заранее спасибо.
Для каких "таких целей"? Это не TCP/IP, пакет не стандартизирован. Физические уровни RS485 вам обеспечил, то, что выше - каждый пилит по своей нужде. Общие принципы есть, а генерализованного решения я пока не встречал. Велосипед и всякие структуры вам, для вашего термоядерного реактора не нужен. Его ответ проще для обработки в обычном массиве иметь.
RX надо определять либо на 2й , либо на 3й пин.
Да, нет, он работает с PCINT, а эти прерывания на любом пине есть.
В Меге - не на любом. Но там, как справедливо было отмечено выше, есть аппараные порты, коими и следует пользоваться.
Да я понимаю что не нужно, я ради интереса)
Вроде получилось отправлять-читать структуру, но слейв изредка на пару пакетов вштопор уходит, и заполняет структуру ерундой, потом востанавливается и все ок. Код ниже. Вдруг кто что увидит.
Мастер:
Слейв:
Лично я бы цикл чтения for()-ом не организовывал, конечно. А так - для защиты от неприятных сбоев при приеме вам неплохо бы CRC пихать в конец. И проверять ее при приеме. По ней выносить решение - доверять пришедшим данным или нет.