• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Синхронизация данных приходящих по SoftwareSerial

SeyranG

New member
по моей команде некая железка начинает отправлять в Serial пакеты размером 1544 байт с частотой 4 Гц. Начало пакета это 2 байта 0х5А. Мне надо каждый пакет перенаправить по сети клиенту. Что бы я ни делал, но не попадаю в пакеты, они постоянно плывут. Вот мой код в лупе:
C++:
void loop()
{
  WiFiClient client = server.available();
  bool startBuffer = false;
  if (client) {   
    if(client.connected()){
      Serial.println("Client Connected");
    }
    byte inBuf[1544];
    while(client.connected()){ 
      if(!dataStreamStarted){
        espSerial.begin(115200);
        uint8_t runCmd[] = {0xA5, 0x35, 0x02, 0xDC};
        espSerial.write((byte*)&runCmd, sizeof(runCmd));
          //тут сразу пытаюсь начать читать буфер, чтобы забрать первые 1544 байт
        if(espSerial.readBytes((byte*)&inBuf, sizeof(inBuf))){           
          Serial.println("Bufer resived .....");
          client.write((byte*)&inBuf, sizeof(inBuf));
        }
        dataStreamStarted = true;
      }else{
        uint i = 0;       
        while (espSerial.available()) {
          if(!startBuffer){
            byte bBuf = espSerial.read();
            if(bBuf == 0x5A){ //тут опять пытаюсь поймать начало буфера
              startBuffer = true;
            }else{
              Serial.println(inBuf[0]);
            }
          }else{
            if(espSerial.readBytes((byte*)&inBuf, sizeof(inBuf))){           
                Serial.println("Bufer resived .....");
                client.write((byte*)&inBuf, sizeof(inBuf));
            }
          }         
        }     
      }
    }
    client.stop();
    espSerial.stopListening();
    dataStreamStarted = false;
    Serial.println("Client disconnected");   
  }
я даже согласен на потерю некоторых пакетов, по хорошему хватит даже 2х пакетов в секунду. Может кто решал подобную задачу, а то я уже не знаю как еще попасть в этот буфер...
 

aZholtikov

Active member
Может кто решал подобную задачу, а то я уже не знаю как еще попасть в этот буфер...
Возможно скажу глупость, но я бы сделал так (все в loop):

Постоянно проверяем в буфере Serial наличие "стартового" байта.
Только при его появлении начинаем считывать в буфер следующие байты в заданном количестве.
После считывания "закидываем" в очередь (std::queue) этот буфер.
Проверяем очередь на непустоту. Если есть что-то - только тогда проверяем подключение клиента и отправляем данные. Если нет подключения с первого раза - выходим. Очередь может быть большая... При следующем цикле отправим. А пока еще "пакетик" примем... :)

Ну как то так... И главное без Serial.println()...
 

pvvx

Активный участник сообщества
Для работы вашего кода требуется убрать все Serial.printXX и отключить все LOG/DEBUG.
И где отдача времени на обработку WiFi?
Если делать по правильному, чтобы у вас всё работало, тогда внутренний буфер espSerial должен превышать размер вашего пакета и работать по прерываниям.
В других вариантах, как не крутите верхний уровень кода, будут сбои приема.
 

enjoynering

Well-known member
для этого надо в SoftwareSerial включить прерывания, тогда ничего пропадать не будет. как? смотрим тут.

и таки да, SoftwareSerial быстрее 9600 не умеет.
 

SeyranG

New member
и таки да, SoftwareSerial быстрее 9600 не умеет.
с прерываниями не умеет или в принципе ? Ведь сейчас я на скорости 115200 нормально получаю данные .

Второго сериал порта там нет, есть куцый только на прием. Была мысль сделать прием через этот второй порт, а отправку через софтваре сериал

для этого надо в SoftwareSerial включить прерывания, тогда ничего пропадать не будет. как? смотрим тут.
я почему то думал что SoftwareSerial не умеет по прерываниям работать. Спасибо за наводку.
 

SeyranG

New member
по ссылке кроме строчки

//mp3Serial.enableRx(true); //enable interrupts on RX-pin for better response detection, less overhead than mp3Serial.listen()

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

SeyranG

New member
Постоянно проверяем в буфере Serial наличие "стартового" байта.
Только при его появлении начинаем считывать в буфер следующие байты в заданном количестве.
После считывания "закидываем" в очередь (std::queue) этот буфер.
Проверяем очередь на непустоту. Если есть что-то - только тогда проверяем подключение клиента и отправляем данные. Если нет подключения с первого раза - выходим. Очередь может быть большая... При следующем цикле отправим. А пока еще "пакетик" примем... :)
у меня по сути так и сделано, только при условии что клиент подключен. А Serial.println()"ы я навтыкал уже после чтобы понять что не так идет. По сути получается что даже если я поймаю начало пакета, то в следующем лупе уплывает все
 

CodeNameHawk

Moderator
Команда форума
По сути получается что даже если я поймаю начало пакета, то в следующем лупе уплывает все
Что значит уплывет? Просто можете не успеть поймать пакет, но это надо проверять.
Ловите начало нового пакета, в чем проблема?
Работу с сериал перенесите вверх, в независимости от if (client).
 
Последнее редактирование:

CodeNameHawk

Moderator
Команда форума
Код:
if(espSerial.readBytes((byte*)&inBuf, sizeof(inBuf)))
Зачем тормозить? Принимайте те байты, что уже поступили.
Если еще не все байты поступили, выходите из главного цикла.
 

enjoynering

Well-known member
Ссылку кинул ту. Вы все правильно увидели. После приёма, прерывание желательно отключить, до следующего чтения.
 
Сверху Снизу