Камрады, столкнулся с такой проблемой. Подключаю 2 устройства по SoftwareSerial. Вот код: Код (C++): // TRANSMITTER #include <Arduino.h> #include <SoftwareSerial.h> SoftwareSerial serialHC06(9, 10); // RX, TX SoftwareSerial serialE32(11, 12); // RX, TX E32_RX -> PIN_12 Nano, E32_TX -> PIN_11 Nano String buffer_string; void setup() { Serial.begin(9600); serialHC06.begin(9600); serialE32.begin(9600); Serial.setTimeout(50); serialHC06.setTimeout(50); serialE32.setTimeout(50); Serial.println("TRANSMITTER ready!"); } void loop() { // Если есть данные в Serial if (Serial.available()) { buffer_string = Serial.readString(); // выводим в serial сообщение Serial.print("get message from Serial: " + buffer_string); serialHC06.print("get message from Serial: " + buffer_string); } // Если есть данные от блютуз if (serialHC06.available()) { buffer_string = serialHC06.readString(); // выводим в serial сообщение Serial.print("get message from serialHC06: " + buffer_string); } // Если есть данные по радио if (serialE32.available()) { buffer_string = serialE32.readString(); // выводим в serial сообщение Serial.print("get message from serialE32: " + buffer_string); } } Проблема следующая при передаче данных с этих устройств - с одного из них данные принимаются, а с другого нет. Причем по отдельности всё работает. Проблемы при совместной работе. С помощью научного тыка и такой-то матери выяснил проблемное место. Если я меняю местами строки Код (C++): serialHC06.begin(9600); serialE32.begin(9600); тогда то устройство, которое объявлено последним - работает нормально, а первое нет. Уточню: если serialE32.begin(9600); объявлено последним, то с него данные принимаются, а с serialHC06 - нет. И наоборот. Причем передача данных работает в обоих случаях. В чем может быть причина?
Разобрался с этой проблемой(( поспешил тему создать. Эта библиотека при приеме данных использует прерывание. Это прерывание только одно. Значит одновременно принимать два порта не могут.
Скорее всего serialNNNN.begin(9600) использует какой-то общий ресурс, типа прерывания, и приписывает его к тем или иным входным пинам. Он(оно) задействован только в процессе "ловли" входящих данных. Тут решение - либо искать более "умную" библиотеку SoftSerial-а, либо поочередно открывать-закрывать порты. ПС. Ну вот мы сошлись в мыслях.
да, сейчас пытаюсь найти альтернативу SoftwareSerial. Пока что-то не очень получается(( Поочередное открытие и закрытие - не очень хочу делать - данные будут теряться. Ну или буду пробовать на HardwareSerial подключиться - что тоже пляски с бубнами будут((
попытался настроить работу с библиотекой NeoSWSerial. Тоже 2 порта не работают(( по отдельности всё отлично. И совместно с SoftwareSerial не компилируется
Зачем?Сам же говорил что для этого надо поступить в ЛЭТИ на бюджет,отучиться и закончить с красным дипломом. Долго блин! Лучше готовую библиотеку.
Без двух аппаратных Сериалов - ваша задача не решаема. Аппаратный сериал - это самостоятельный контроллер внутри процессора, независимый от его ядра. Он сам обрабатывает процесс, а ядру выдает готовые данные (когда оно потребует). А СофтСериал - это работает само ядро. Обработать два одновременно приходящих процесса - оно физически не может. Просто потому что возникает временнОй конфликт. Поэтому Паровоз гонит пургу.
А долго ли его написать? Нужна пара программных таймеров и пара буферов ввода-вывода и всё. Два софтовых сериала готовы.
на забугорном форуме нашел: What's really needed is the ability to check on multiple pins when an interrupt comes along from the start bit. Then you'd have to set up pointers to the appropriate data structures. It would be complicated, but possible. Немного не понял, про какие пины идет речь и про прерывание не совсем понял. Т.е. когда приходят данные по Serial вызывается прерывание и в этот момент нужно проверить значение порта какого-нибудь , который укажет на какой пин пришли данные? или это сообщение вообще не про это?
всё, победил я его))) воспользовался библиотекой AltSoftSerial. Там только ограничение - нужно RX устройства присоединить на 9 пин на ардуино, а TX устройства на 8 пин на ардуино. Таким образом у меня сейчас так: Код (C++): #include<Arduino.h> #include<SoftwareSerial.h> #include<AltSoftSerial.h> AltSoftSerial serialHC06; SoftwareSerial serialE32(11, 12); // RX, TX E32_RX -> PIN_12 Nano, E32_TX -> PIN_11 Nano по обоим устройствам данные передаются в обе стороны
прерывание нужно для того старта приёма. Прием/передача начинается с прижатия линии к нулю на 2 (или 2.5 - не понмю точно) интервала передачи одного символа. После чего необходимо считать первый бит, через едининый интервал второй бит и так все восемь битов. Далее идёт бит чётности (при наличии) и стоп бит. Ничего сложного. Таким образом можно организовать хоть сколько софтовых сериалов. Пока ног хватит. А если не хватит, то сдвиговый регистр в помощь.
Вероятно потому что это ВЫ проверяете каналы - ПО ОЧЕРЕДИ. Но когда два девайса самостоятельно и ОДНОВРЕМЕННО пошлют данные ? Данные одного из них (тот кто начал позднее) - потеряются. ПС. Однако спасибо за альтернативную библиотеку. Сохраню про запас, хоть по логике, ОДНОМОМЕНТНОЙ многоканальности она не даст. Натыкался когда-то на вашу проблему. Но большой нужды тогда не было решать загадку. Вышел из положения открыванием-закрыванием портов.
ничего никуда не потеряется. Считывать значения PIN регистра со скоростью 9600 Гц для МК с тактовой частотой в 20 МГц - это как забег спринтера и черепахи.
Вообще-то в СофтСериале есть функция выбора портов без их открытия-закрытия. Чето я про нее забыл. Может она нужна ТС-у. Вот же классика из примеров. Код (C++): /* Software serial multiple serial test Receives from the two software serial ports, sends to the hardware serial port. In order to listen on a software port, you call port.listen(). When using two software serial ports, you have to switch ports by listen()ing on each one in turn. Pick a logical time to switch ports, like the end of an expected transmission, or when the buffer is empty. This example switches ports when there is nothing more to read from a port The circuit: Two devices which communicate serially are needed. * First serial device's TX attached to digital pin 10(RX), RX to pin 11(TX) * Second serial device's TX attached to digital pin 8(RX), RX to pin 9(TX) Note: Not all pins on the Mega and Mega 2560 support change interrupts, so only the following can be used for RX: 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 Not all pins on the Leonardo support change interrupts, so only the following can be used for RX: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI). created 18 Apr. 2011 modified 19 March 2016 by Tom Igoe based on Mikal Hart's twoPortRXExample This example code is in the public domain. */ #include <SoftwareSerial.h> // software serial #1: RX = digital pin 10, TX = digital pin 11 SoftwareSerial portOne(10, 11); // software serial #2: RX = digital pin 8, TX = digital pin 9 // on the Mega, use other pins instead, since 8 and 9 don't work on the Mega SoftwareSerial portTwo(8, 9); void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // Start each software serial port portOne.begin(9600); portTwo.begin(9600); } void loop() { // By default, the last initialized port is listening. // when you want to listen on a port, explicitly select it: portOne.listen(); Serial.println("Data from port one:"); // while there is data coming in, read it // and send to the hardware serial port: while (portOne.available() > 0) { char inByte = portOne.read(); Serial.write(inByte); } // blank line to separate data from the two ports: Serial.println(); // Now listen on the second port portTwo.listen(); // while there is data coming in, read it // and send to the hardware serial port: Serial.println("Data from port two:"); while (portTwo.available() > 0) { char inByte = portTwo.read(); Serial.write(inByte); } // blank line to separate data from the two ports: Serial.println(); }
на этот пример я натыкался, когда искал решение. Но посчитал, что в этом случае пакеты от второго устройства могут потеряться, пока будет вестись прием от первого устройства