проблемы с несколькими SoftwareSerial

misterio
Offline
Зарегистрирован: 26.01.2015

Всем привет.

Столкнулся со следующей проблемой.

 

подключаю к Arduino 2 Rfid Readera работающих через UART, создаю 2 SoftwareSerial подключения, инициализирую их в setup. все вроде правильно но работает только тот порт который инициализировался последним.

Вот пример кода который накидал просто для пробы.

#include <SoftwareSerial.h>

SoftwareSerial SoftSerial(2, 3);
SoftwareSerial SoftSerial1(4, 5);

unsigned char buffer[64]; // buffer array for data recieve over serial port
int count=0;     // counter for buffer array 

unsigned char buffer1[64]; // buffer array for data recieve over serial port
int count1=0;     // counter for buffer array 


void setup()
{
  
  SoftSerial1.begin(9600);               // the SoftSerial baud rate   
  
  SoftSerial.begin(9600);                 // the SoftSerial baud rate  
  
  Serial.begin(9600);             // the Serial port of Arduino baud rate.

}

void loop()
{
  if (SoftSerial.available())              // if date is comming from softwareserial port ==> data is comming from SoftSerial shield
  {
    while(SoftSerial.available())          // reading data into char array 
    {
      buffer[count++]=SoftSerial.read();     // writing data into array
      if(count == 64)break;
    }
    Serial.write(buffer,count);            // if no data transmission ends, write buffer to hardware serial port
    clearBufferArray();              // call clearBufferArray function to clear the storaged data from the array
    count = 0;                       // set counter of while loop to zero
  }



  if (SoftSerial1.available())              // if date is comming from softwareserial port ==> data is comming from SoftSerial shield
  {
    while(SoftSerial1.available())          // reading data into char array 
    {
      buffer1[count1++]=SoftSerial1.read();     // writing data into array
      if(count1 == 64)break;
    }
    Serial.write(buffer1,count1);            // if no data transmission ends, write buffer to hardware serial port
    clearBufferArray1();              // call clearBufferArray function to clear the storaged data from the array
    count1 = 0;                       // set counter of while loop to zero
  }
  

}







void clearBufferArray()              // function to clear buffer array
{
  for (int i=0; i<count;i++)
  { 
    buffer[i]=NULL;
  }                  // clear all index of array with command NULL
}


void clearBufferArray1()              // function to clear buffer array
{
  for (int i=0; i<count1;i++)
  { 
    buffer1[i]=NULL;
  }                  // clear all index of array with command NULL
}

в таком варианте работает только SoftSerial порт. SoftSerial1 не работает.

если поменять порядок инициализации портов то и работать будет другой порт.

void setup()
{

  SoftSerial1.begin(9600);              // не будет работать
  
  SoftSerial.begin(9600);               //  будет работать
  
  Serial.begin(9600);             //  этот работает всегда
}
void setup()
{

  SoftSerial.begin(9600);                 //  не будет работать
  
  SoftSerial1.begin(9600);               //  будет работать
  
  Serial.begin(9600);             //  этот работает всегда
}

вопрос с чем это связано и как быть?

в данный момент я подключаю 2 RFID но уже есть задача с 5...7 RFID на одном устройстве. 

Araris
Offline
Зарегистрирован: 09.11.2012

Вот здесь http://arduino.ua/ru/prog/SoftwareSerial, например, написано

"Среди известных ограничений библиотеки SoftwareSerial можно перечислить следующие:
При использовании нескольких последовательных портов, в каждый момент времени только один из них может получать данные.
"

misterio
Offline
Зарегистрирован: 26.01.2015

ну так у меня они поочереди работают.

сначала опрашивается SoftSerial и если на нем есть данные то обрабатываем их, и только потом переходим к SoftSerial1.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Эта библиотека при приеме данных использует прерывание. Это прерывание только одно. Значит одновременно принимать два порта не могут. Опросить порт можно, но данные будут только псле того как он примет их. Ощущаете разницу ?

misterio
Offline
Зарегистрирован: 26.01.2015

с трудом но кажется понемного понимаю.

в общем на ардуине нет возможности запустить больше 1 UART устройства работающего на передачу через SoftwareSerial. печально. 

Coolerr
Offline
Зарегистрирован: 30.06.2014

А если инициализировать непосредственно перед использованием в лупе? То есть инициализируем опрашиваем если есть выполняем нет проскакиваем обрубаем первый инициализируем второй опрашиваем есть выполняем нет проскакиваем обрубаем второй инициализируем первый.

misterio
Offline
Зарегистрирован: 26.01.2015

Интересная мысль.

Вопрос только как обрубать? Подскажите функцию деинициализации.

Coolerr
Offline
Зарегистрирован: 30.06.2014

Serial.end

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

А что будет если данные придут когда порт отключен ? :-)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

misterio пишет:

с трудом но кажется понемного понимаю.

в общем на ардуине нет возможности запустить больше 1 UART устройства работающего на передачу через SoftwareSerial. печально. 

если только на передачу - то можно

Araris
Offline
Зарегистрирован: 09.11.2012

brokly пишет:

А что будет если данные придут когда порт отключен ? :-)

Данные, пришедшие в отключенный порт, теряются. К.О.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Ну это очевидно. Задал вопрос что бы тс задумался.

Coolerr
Offline
Зарегистрирован: 30.06.2014

Ну так как исходная задача RFID то сигнал инициирует человек и в случае непрочтения с первого раза можно попробовать второй.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Можно и третий :) или четвертый - пятый. Пока человек не охренеет... Халтура будет .

Araris
Offline
Зарегистрирован: 09.11.2012

brokly пишет:

Ну это очевидно. Задал вопрос что бы тс задумался.

Простите, я провтыкал..

KVadik
KVadik аватар
Offline
Зарегистрирован: 15.06.2014

А взять мегу что мешает?

misterio
Offline
Зарегистрирован: 26.01.2015

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

 

взять мегу не сильно спасает т.к. это максимум 5 портов (с учетом одного софтового) а нужно больше. к тому же она здоровая и дорогая.

 

потерянные данные не сильно большая проблема как мне кажется. зависит от скорости работы RFID redera. если он в секунду раз 10 будет карточку опрашивать то скорее всего пользователь не заметит проблем. надо пробовать.

KVadik
KVadik аватар
Offline
Зарегистрирован: 15.06.2014

Вы хотите более 5 риадеров повесить на один контроллер? и 10$ мега "дорогая"? А риадеры у Вас почем?

Но я бы делал не так. Я бы взял жменю атмега8 (по одному контроллеру на риадер), настроил бы его на работу с внутренним генератором (чтобы работал без кварца), далее соединил их через i2c или spi в сеть с ардуиной, ну а дальше уже работает софт.

droncs
Offline
Зарегистрирован: 02.02.2015

Решил вопрос с RC522 вот пример можно и больше ридеров повесить....

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define SS_PIN1 5
MFRC522 mfrc522(SS_PIN, 0); // Create MFRC522 instance.
MFRC522 mfrc523(SS_PIN1, 0); // Create MFRC523 instance.
unsigned long uidDec, uidDecTemp;

boolean Red1 = false;
boolean Red2 = false;
boolean Blue1 = false;
boolean Blue2 = false;

void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
mfrc523.PCD_Init(); // Init MFRC523 card
Serial.println(«Waiting for card...»);
}

void loop() {
byte status;
byte byteCount;
byte buffer[2]; // длина массива (16 байт + 2 байта контрольная сумма)
byteCount = sizeof(buffer);
uidDec = 0;

status = mfrc522.PICC_RequestA(buffer, &byteCount);
if (mfrc522.PICC_ReadCardSerial()) {
for (byte i = 0; i < mfrc522.uid.size; i++) {
uidDecTemp=mfrc522.uid.uidByte[i];
uidDec=uidDec*256+uidDecTemp;
}
if ((uidDec==46015106) && (Red1==false)){
Serial.println(«Red Card logged on Rider 1»);
Red1=true;
Red2=false;
}
if ((uidDec==3546663646) && (Blue1==false)){
Serial.println(«Blue Card logged on Rider 1»);
Blue1=true;
Blue2=false;
}
}
status = mfrc523.PICC_RequestA(buffer, &byteCount);
if (mfrc523.PICC_ReadCardSerial()) {
for (byte i = 0; i < mfrc523.uid.size; i++) {
uidDecTemp=mfrc523.uid.uidByte[i];
uidDec=uidDec*256+uidDecTemp;
}
if ((uidDec==46015106) && (Red2==false)){
Serial.println(«Red Card logged on Rider 2»);
Red2=true;
Red1=false;
}
if ((uidDec==3546663646) && (Blue2==false)){
Serial.println(«Blue Card logged on Rider 2»);
Blue2=true;
Blue1=false;
}
}
}
 
droncs
Offline
Зарегистрирован: 02.02.2015

Попробуй так.

if(Serial1.available()){
26     Serial.println("Test1");
27     reader1Blink = millis()+500;
28     while(Serial1.available()) Serial1.read();//purge buffer
29   }//if(Serial1)

Или так

http://arduino.ru/forum/apparatnye-voprosy/mega-25602xrdm-6300-ili-2xrc5...

Grenader
Offline
Зарегистрирован: 07.03.2015

misterio пишет:

подключаю к Arduino 2 Rfid Readera работающих через UART, создаю 2 SoftwareSerial подключения, инициализирую их в setup. все вроде правильно но работает только тот порт который инициализировался последним.

вопрос с чем это связано и как быть?

Посмотрите здесь описание библиотеки SoftSerial.

Перед тем как считывать данные с софтового порта, его необходимо перевести в режим ожидания данных функцией SoftSerial.listen()

misterio
Offline
Зарегистрирован: 26.01.2015

Все пере пробовал. Ни чего не помогло.

В итоге сделал на каждый ридер свою нану. Громоздко и дорого но работает.

exolon
Offline
Зарегистрирован: 20.05.2015

столкнулся с тоже проблеммой 2 программных порта на атмега 328, лучше конечно использовать аппаратный и программный но увы плату протравил и спаял не подумав, путём проб смог добится работы 2 устройств

recvL.listen();
  delay(28);
      while(recvL.available()>0)     
          primL = recvL.read();
   
 
 recvR.listen();
  delay(28);
     while(recvR.available()>0)       
          primR = recvR.read();

оказалось что нужне ещё некое время на отработку прерываний

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

попробуйте так

recvR.end ();
recvL.begin(9600);
//....................выполняем код
recvL.end ();
recvR.begin(9600);
//.................выполняем код

и скорость больше 19200 лучше не использовать

exolon
Offline
Зарегистрирован: 20.05.2015

это работает через раз и тоже требует задержки во времяни, в предыдущей версии 28 милисикунд, стабильно получает пакеты

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

от использования "listen" я отказался, так как переодически получал кракозябры

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

Есть задержка звука при запуске 2-х МП3 плееров (только передача по TX). Код приложен. 

#include <SoftwareSerial.h>
SoftwareSerial portL(9, 12); // 12 идет на RX,  9 не подключен
SoftwareSerial portR(8, 11);

volatile int count;
int t = 30;

void setup() {
  TCCR1A = 0;
  TCCR1C = 0;
  TCCR1B = (1 << WGM12);
  TCCR1B = (1 << CS11);
  OCR1A  = 100;
  TIMSK1 |= (1 << OCIE1A);

  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);

  count = 0;

  portL.begin(9600);
  portR.begin(9600);

}

void loop() {
  while (1) {}
}

ISR (TIMER1_COMPA_vect) {
  count++;
  TCNT1 = 0;
  int hh = 24 * t / 60;
  OCR1A = trunc(1000000 / hh);
  if (count > 30)
  {
    count = 0;
    SendLR();

  }
}
void SendLR() {
  int g1 = 0;
  int g2 = 0;
  int SML1 = 0xAA + 0x07 + 0x02 + g1 + 2;
  int SMR1 = 0xAA + 0x07 + 0x02 + g2 + 2;
  portL.write(0xAA);
  portR.write(0xAA);

  portL.write(0x07);
  portR.write(0x07);

  portL.write(0x02);
  portR.write(0x02);

  portL.write(g1);
  portR.write(g2);

  portL.write(2);
  portR.write(2);

  portL.write(SML1);
  portR.write(SMR1);
}

 

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

А если запараллелить вход MP3-плееров - они стартанут в одно и то же время или у них есть ещё разнообразная внутренняя задержка?

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

Сейчас проверю. Спасибо за подсказку. 

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

Задержка-то она всегда будет уже только на том основании, что МК с библиотекой софтсериал блокируется в цикле передачи по одному из виртуальных UART. Вопрос только в том, насколько её удастся сократить.

dim3740
dim3740 аватар
Offline
Зарегистрирован: 25.03.2015

Форматирование памяти МП3 плеера и перезапись файлов решили проблему. 

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

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