2 софт-сериала попеременно (Leo или UNO)

ivpo
Offline
Зарегистрирован: 07.01.2014

Здравствуйте

Подскажите, есть ли всё-таки возможность каким-то образом использовать два softserial по очереди на платах Leonardo или UNO?

Альтернативные библиотеки? Модифицированная родная библиотека? Какая-нибудь хитрость, позволяющая переключать между собой SS ?

Кажется, перепробовал уже все.

Заранее огромное спасибо

 

Olvin
Offline
Зарегистрирован: 01.08.2018

ivpo пишет:

Здравствуйте

Подскажите, есть ли всё-таки возможность каким-то образом использовать два softserial по очереди на платах Leonardo или UNO?

Альтернативные библиотеки? Модифицированная родная библиотека? Какая-нибудь хитрость, позволяющая переключать между собой SS ?

Кажется, перепробовал уже все.

Заранее огромное спасибо

 

Не увидел аналога метода Serial.end(); возможно, SoftwareSerial.begin() переключает на заданный порт. Пробовали уже?

ivpo
Offline
Зарегистрирован: 07.01.2014

Пробовал. Увы, не переключает. Видимо инициализация происходит только в самом начале.

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

почему бы не взять плату с двумя-тремя сериалами? Например STM32F103 - по флешу, оперативке, тактовой частоте  превосходит Уно в 4 -10 раз, при этом  дешевле Уно чуть ли не вдвое

ivpo
Offline
Зарегистрирован: 07.01.2014

Увы, в рамках данного проекта не могу :(

ivpo
Offline
Зарегистрирован: 07.01.2014

А сложно ли реализовать работу UART в отдельной функции на GPIO? Без прерываний. Может кто-то так делал уже?

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

ivpo пишет:

А сложно ли реализовать работу UART в отдельной функции на GPIO? Без прерываний.

А как Вы себе это представляете?

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

Насколько по-очереди нужно? Часто/быстро менять надо их?

Я для периодических запусков по запросу не стесняюсь создавать объект и уничтожать прямо в функции, которая с UART работает. Сколько угодно софтсериалов получается. Softwire модифицировал таким образом, что специальная функция configure() просто выполняет часть begin() с переинициализацией входов/выходов. 

ivpo
Offline
Зарегистрирован: 07.01.2014

Чтение состояний GPIO в цикле и расшифровка всего этого добра...

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

ivpo пишет:

Чтение состояний GPIO в цикле и расшифровка всего этого добра...

все это ради того, чтоб плату нормальную не покупать? :)

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

ivpo пишет:

Чтение состояний GPIO в цикле и расшифровка всего этого добра...

Ну ладно, прочитали, расшифровали, а дальше что?

Какой толк от контроллера, если он кроме чтения и расшифровки входящей информации больше ничем не сможет заниматься?

ivpo
Offline
Зарегистрирован: 07.01.2014

Так он этим будет заниматься ровно то время, которое мне нужно. Это определенная стадия программы, секунд на 10-15.

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

ivpo пишет:

Так он этим будет заниматься ровно то время, которое мне нужно. Это определенная стадия программы, секунд на 10-15.

А как Вы собираетесь контролировать эти 10-15 секунд? Боюсь, что прерывания (все!) придется отключить, т.е. millis() не будет.

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

А если удалять ненужный сериал совсем, деструктор не почистит?

Попробуйте и нам скажите.

ivpo
Offline
Зарегистрирован: 07.01.2014

Каким образом? SoftwareSerial.end() не помогает (кстати, он и не документирован, хотя компилятор не ругается).

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

Ну, вот так попробуйте что ли: swSerial.~SoftwareSerial()... 

ivpo
Offline
Зарегистрирован: 07.01.2014

Не-а :(

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

Ну, не знаю, у меня работает всё. Создаю, уничтожаю.

ivpo
Offline
Зарегистрирован: 07.01.2014

А вы не могли бы скинуть код? Был бы очень признателен. 

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

Мне не жалко. Всё в таком стиле:

int8_t getPZEM004Metric(const uint8_t _rxPin, const uint8_t _txPin, uint8_t _metric, const char* _ip, uint8_t* _dst) {
  int8_t rc = RESULT_IS_FAIL;
...

  SoftwareSerial swSerial(_rxPin, _txPin);
  swSerial.begin(PZEM_UART_SPEED);
...

  swSerial.~SoftwareSerial(); 
  return rc;
}

 

ivpo
Offline
Зарегистрирован: 07.01.2014

Да нет, работать-то оно работает - компилятор не ругается. Вот только уничтожай - не уничтожай - два SS у меня не работают. Даже если с одного только отправляю, а со второго - только слушаю.

ivpo
Offline
Зарегистрирован: 07.01.2014

Подскажите - а будет ли работать такая схема:

SS - один, но RX приходит с одного устройства (его слушаю), а TX уходит на третье (туда отправляю)?

 

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

Ну так я спрашивал - вам как их надо? Вот по-очереди именно таким способом у меня опрашиваются разные датчики, висящие на своих softserial-ах.

А ежели вам они нужны в системе одновременно, то производителем рекомендована функция listen() для переключения между инстансами.

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

Будет, почему нет-то? Буфера разные у RX/TX. Главное - самому помнить, что куда и откуда. А то у вас вон уже второе куда-то пропало.

ivpo
Offline
Зарегистрирован: 07.01.2014

Вот не переключает. Не работают у меня SS попеременно. Закрываю (end), уничтожаю - без разницы.

Может это быть связано со следующими моментами? 

1) Одно из устройств - esp8266, через делитель. В одиночном режиме все работает.

2) Это устройство шлет в uart постоянно, а не по запросу.

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

Могу только это подкинуть: https://forum.arduino.cc/index.php?topic=442387.0

Не думаю, что проблема связана именно с ESP.

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

Вы меня заинтриговали! 

Посмотрел код.

Нормально там всё работоает в двумя, хоть с 10-ю объектами.

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

Значит, послле "begin" активен тот, который последним вызывал begin - он сидит на прерывании. Чтобы сменить активный объект, нужно вызвать метод listen() после этого вызова, активным станет тот, чей метод listen вызывался.

Просто посмотрите текст SoftwareSerial, там всё понятно.

ivpo
Offline
Зарегистрирован: 07.01.2014

Вот мой код. Он не работает с listen, без него, а также с вариантами уничтожения объектов.

Принимает от ss1 только один раз, после этого - затык.

Железо: Leo (точнее Iskra Neo), сверху - GPRS-шилд на SIM800, который работает по Serial1. И подключен Serial-USB.

Хотя голый Leo (без шилда) показывает тоже самое.

#include <SoftwareSerial.h>

long ts = 0;
long ts2 = 0;
byte stage = 0;

void setup() {
  Serial.begin(9600);
  ts = millis();
  ts2 = millis();
}

void loop() {

  if (millis() - ts > 1000) {
    Serial.println(".");
    ts = millis();
  }

  if (millis() - ts2 > 20000) {

    // этап 1
    if (stage == 0) {
      SoftwareSerial ss1(8, 9); // RX, TX
      ss1.begin(9600);
      // ss1.listen() - не работает с ним и без него
      // delay(28)    - не работает с ним и без него

      long temp_ts = millis();
      while (millis() - temp_ts < 10000) {
        if (ss1.available()) {
          char c = ss1.read();
          Serial.write(c);
        }
      }

      // ss1.~SoftwareSerial(); - не работает с ним и без него
      ss1.end();
    }

    // этап 2
    if (stage == 1) {
      SoftwareSerial ss2(10, 11); // RX, TX
      ss2.begin(9600);
      // ss2.listen() - не работает с ним и без него
      // delay(28)    - не работает с ним и без него

      long temp_ts = millis();

      // здесь может идти приемная часть или просто отправка данных:
      while (millis() - temp_ts < 10000) {
        if (ss2.available()) {
          char c = ss2.read();
          Serial.write(c);
        }
      }

      // ss2.~SoftwareSerial(); - не работает с ним и без него
      ss2.end();
    }

    // возврат к этапу 0
    stage++;
    if (stage > 1) {
      stage = 0;
    };
    ts = millis();
  }
}

 

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

Neo у меня нет.

Могу завтра подготовить работающий пример на Uno, если интересно. Надо?

ivpo
Offline
Зарегистрирован: 07.01.2014

Очень интересно!

Буду оч благодарен!

Logik
Offline
Зарегистрирован: 05.08.2014

ivpo пишет:

Вот мой код. Он не работает с listen, без него, а также с вариантами уничтожения объектов.

Принимает от ss1 только один раз, после этого - затык.

Ну а ссылку из #25 чего не осилили? Там жеж в первом же ответе все разжевано. Нету даже одного полноценного uart на софт сириале. Оно впринципе не может одновременно работать на передачу и прием. Даже одно устройство. Те недоразумения где оно какбы работает - чисто диалоговые, гарантирующие что эти два процесса никогда не пересекутся. И то недообследованые недоразумения ;) А уж ежели "Это устройство шлет в uart постоянно, а не по запросу." - так вобще какой там софтсириал, он еще и основной цикл тормознет так что не пошевелится.

ivpo
Offline
Зарегистрирован: 07.01.2014

Ссылку 25 осилил ещё до этой ветки.

AltSoftSerial - странная штука. Жесткие ограничения по пинам.

NeoSWSerial - не работает с Leo (32u4). На гитхабе есть какие-то любительские корректировки, чтобы она работала с 32u4, но у меня так и не стало компилироваться.

Логически я не очень понимаю, почему нельзя переключаться с одного SS на другой, если я прибиваю предыдущий, открывая новый (на других пинах). Кто там чего в постоянном режиме шлет в SS, который закрыт - какая разница? Но по какому-то недоразумению SS нормально закрыть нельзя (или я столкнулся с ещё какими-то очень тонкими глюками).

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

 

 

 

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

ivpo, SoftSerial в основном рассчитан на 328, у которого аппаратный - только единственный, зато на всех пинах есть pcint. На Меге, например, он уже не работает, т.к. у нее pcint - не на всех. Да, как-то и не очень нужно, ибо есть 4 аппаратных. А как на других контроллерах - надо смотреть по дэйташиту. Если на пине нет никакого прерывания, SoftSerial на нем не организовать.

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

ivpo
Offline
Зарегистрирован: 07.01.2014

Эх, согласен. Золотые слова :)

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

ivpo пишет:

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

Эх, согласен. Золотые слова :)

а я еще в начале дискуссии это говорил....

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

Вот это нормально работает на UNO. Я только что проверил. В первый софтовый сериал постоянно шлются текстовые единицы ('1'), а во второй постоянно валятся двойки.

#include <SoftwareSerial.h>

SoftwareSerial ss1(8, 9), ss2(10, 11); // RX, TX

void setup(void) {
	Serial.begin(57600);
	ss1.begin(9600);
	ss2.begin(9600);
	Serial.println("Fun begins");
}

void read10bytesFromSS(SoftwareSerial & ss) {
	ss.listen();
	for (int8_t i=0; i < 10; i++) {
		while(! ss.available());
		Serial.write(ss.read());
	}
	Serial.println();
}

void loop() {
	read10bytesFromSS(ss1);
	read10bytesFromSS(ss2);
}

результат

Fun begins
111111111
2222222222
1111111111
2222222222
1111111111
2222222222
1111111111
2222222222

У меня нет Iskra Neo, потому не обессудьте. Но обязательно проверьте так ли там распаяны порты как в леонардо. В леонардо RX софтсериала имеет право быть только на порте B (на пинах 8-11). У Вас, вроде всё так, но как пины с портами соответсвуют - совместимо с леонардо или нет - этого я не знаю.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

ivpo пишет:

использовать два softserial по очереди на платах Leonardo или UNO?

Альтернативные библиотеки? 

Зачем альтернативные? Читаем строку №2 родного SoftSerial.h

Multi-instance software serial library for Arduino/Wiring

Нормально она работает, если аккуратно listen переключать.

ivpo
Offline
Зарегистрирован: 07.01.2014

Спасибо огромное! Проверю у себя на Искре и на Уне.