• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе 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
Ссылку кинул ту. Вы все правильно увидели. После приёма, прерывание желательно отключить, до следующего чтения.
 
Сверху Снизу