Serial. Передача по проводам длинных строк.

Тема в разделе "Arduino & Shields", создана пользователем issida, 26 окт 2017.

  1. issida

    issida Нерд

    Имеется esp8266 и про мини. Нужно передавать и получать строки с данными. Их длинна может быть разной. Проблема в том, что используя Serial.readString() на получение строки , в которой только один символ, тратится 1 секунда. Когда использую Serial.read() начинает неверно читать данные.
    Пример неверно работающих скетчей.

    На ESP

    Код (C++):
    #include <SoftwareSerial.h>

    SoftwareSerial Serial_1 (12, 13); // RX, TX
    String qaz = "{\"VER\":\"ver 1.25\",\"SSDP\":\"fdddd\",\"ssid\":\"uhfg\",\"password\":\"NonoNono\",\"ssidAP\":\"WiFi\",\"passwordAP\":\"\",\"user_LOGIN\":\"11111\",\"user_PFSSWORD\":\"11111\",\"DEVICE_STAT_IP\":\"0\",\"IP\":[0,0,0,0],\"MQTTSERVER\":\"\",\"MQTTPORT\":\"0\",\"MQTTUSER\":\"\",\"MQTTPASS\":\"\",\"PUBTOPIK1\":\"kettle/vol\",\"SUBTOPIK1\":\"kettle/on\",\"DEVICEVOLUM\":\"0\",\"DEVICEWEIGHT\":\"500\",\"DEVICEMINVOL\":\"200\",\"MQTTPERREQ\":\"0\",\"MQTTWORK\":\"0\",\"WIFIINAP\":\"0\",\"MQTTCONNECT\":\"0\",\"READYTOWORK\":\"0\",\"ip\":\"192.168.1.3\",\"AP_ip\":\"192.168.1.1\",\"ALWAYS_AP\":\"0\",\"C_TIME\":\"20\",\"M_TIME\":\"3000\"}";
    void setup() {
      Serial.begin(115200);
      Serial_1.begin(9600);


    }

    void loop() {
      int q = qaz.length();
      char charBufVar[1000] = "";
      qaz.toCharArray(charBufVar, q);
      Serial.print("ОТСЫЛКА  ");
      for (int a1 = 0; a1 < q; a1++) {
        Serial_1.print(charBufVar[a1]);
      }

      while (!Serial_1.available()) {}

      Serial.print("Получение  ");
      char  qqq = Serial_1.read();
      String mes = "";
      for (int a = 0; a < q; a++) {
        char aa = Serial_1.read();
        mes += aa;
      }

      Serial.println(mes);
    }
    На про мини
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial Serial_1 (12, 13); // RX, TX
    String mes = "";
    void setup() {
      Serial_1.begin(9600);
      Serial.begin(115200);

    }

    void loop() {
      if (Serial_1.available() > 0) {
        Serial.print("POLUCH  ");
        int q = 520;
        for (int a = 0; a < q; a++) {
          char aa = Serial_1.read();
          mes += aa;
        }
        Serial.println(mes);
        mes = "";

        Serial.print("OTSYL  ");
        char charBufVar[1000] = "";
        mes.toCharArray(charBufVar, q);
        for (int a = 0; a < q; a++) {
          Serial_1.print(charBufVar[a]);
        }
      }
    }
    Подскажите кто что может.
     
  2. rkit

    rkit Гуру

    Строки можно разделять символом \0. и использовать readBytesUntil
     
    arkadyf нравится это.
  3. b707

    b707 Гуру

    Имея всего 2килобайта ОЗУ, выделять 1000 байт под буфер - это верный путь к глюкам. Не исключено, что если вы уменьшите буфер до 100 байт, все заработает.

    Из прочих советов - зачем вы храните строку в виде обьекта String. а потом переводите ее в char_array? Что мешает сразу положить ее в символьный массив - строка будет занимать в оперативке в 2.5 раза меньше места.

    В целом по вопросу - "Как передавать длинные строки" - ответ банален. Резать на кусочки и передавать, как короткие.
     
    arkadyf нравится это.
  4. issida

    issida Нерд

    Это лишь тестовый вариант. Строка статически хранится не будет. Возможно ли передать большое число символов за раз без разбиения или всегда будут теряться данные в таком случае?
     
  5. b707

    b707 Гуру

    Что значит "за раз"? Вот вы берете строку в 1000 символов и в цикле отправляете ее функцией Serial.write() - это как, "за раз" или нет?
     
    arkadyf нравится это.
  6. brokly

    brokly Гик

    Я тоже в недоумении. Есть решения, когда при загрузке в сериал сыпятся данные непрерывно все время работы, то есть получается один раз за всю сессию работы, от включения, до выключения. И никаких проблем. А уже принять и обработать - это вопрос к программеру.
    Вообще сериальгый интерфейс не может терять данные, если все сделано как положено. Причем, вовсе не обязательно вообще иметь хоть какой то буфер.
     
  7. issida

    issida Нерд

    За раз в смысле последовательно от первого до последнего символа без разбиений и прерываний.
    Все заработало. 300 символов принимает или передает за 27 милисекунд на 115200 бод Вечером как-то не сложилось с реализацией.
    Утро вечера мудренее. Пословицы неспроста слаживалисть.
     
  8. brokly

    brokly Гик

    Просто в работе с последовательными интерфейсами, конечно иногда используют таймауты, отделяя "пачки данных", но такой подход чреват ошибками. Поэтому правильнее в последовательных асинхронных интерфейсах, формировать пакеты с помощью заголовков и проверять их используя контрольные суммы. Так проще реализация и контроль правильности передачи.