Повреждение данных SoftwareSerial - поиск предложений

У меня проблемы с последовательной связью между NodeMCU ESP8266 и Arduino Uno. Я использую «стандартную» настройку SUART, то есть контакты D1 и D2 на ESP подключены к GPIO 2 и 3 на UNO; tx от UNO к ESP подается через делитель напряжения, чтобы понизить его до 3,3 В.

Раньше установка работала нормально; внезапно - да, я читал это раньше, моя установка внезапно не работает, но, честно говоря, это то, что произошло - данные были повреждены. Устройства обмениваются строкой в формате json:

{"action":"position","lat":123,"lon":123}

и это сработало. Теперь я получаю что-то вроде:

{"⸮⸮⸮⸮⸮⸮":"pos⸮⸮⸮onb,"l⸮tF:0,"lo⸮":0,"⸮⸮s⸮⸮":0⸮

Оба SUART работают на скорости 115200 бод, физические соединения проверены, все в порядке, оба устройства заземлены на одном опорном уровне.

Я пытался заменить ESP на другой и поменять контакты TX/RX на UNO - безрезультатно.

Поэтому я ищу предложения, что делать дальше, чтобы отладить проблему, что проверить и что может быть не так. Заранее спасибо.

Ниже приведены фрагменты кода UNO и ESP.

ESP8266

SoftwareSerial SUART(4, 5);

int16_t last_fetch = 0;
int16_t last_serial = 0;

double azimut, elevation;

#define DATA_FETCH_TIME_INT 3
#define SERIAL_TRASMISSION_TIME_INT 5

void setup() {
  Serial.begin(115200);  //включить последовательный монитор
  SUART.begin(115200);   //включаем порт SUART

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.println(WiFi.localIP());
}

void loop() {
  if (secs() - last_fetch >= DATA_FETCH_TIME_INT) {
    last_fetch = secs();
    fetchData();
  }

  if (secs() - last_serial >= SERIAL_TRASMISSION_TIME_INT) {
    last_serial = secs();
    sendDataViaSerial();
    }
}

void fetchData() {
  //подключается к серверу и получает данные
}

void sendDataViaSerial() {
  int lat_i = (int) elevation;
  int lon_i = (int) azimut;
  int checksum = lat_i + lon_i;

  const int capacity = 200;
  StaticJsonDocument<capacity> doc;

  doc["action"] = "position";
  doc["lat"] = lat_i;
  doc["lon"] = lon_i;
  doc["cksum"] = checksum;

  Serial.println("Sending data via serial: ");
  serializeJson(doc, Serial);

  //SUART.flush();
  //serializeJson(doc, SUART);
  // работает так же

  String outstring;
  serializeJson(doc, outstring);
  SUART.println(outstring);
}

АРДУИНО УНО

SoftwareSerial SUART(2, 3);
#define arraySize 150
char inData[arraySize];

void setup() {
  pinMode(STATUS_LED, OUTPUT);
  digitalWrite(STATUS_LED, HIGH);

  Serial.begin(115200);
  SUART.begin(115200);

  Serial.println("Ready to go.\n");
}

void loop() {
  readSerial();
}

void readSerial() {
  short index = 0;
  char inChar;

  if (SUART.available() > 0) {
    while (SUART.available() > 0 && index < arraySize - 1) {
      inChar = SUART.read();    
      inData[index] = inChar;

      index++;
      inData[index] = '\0';  // Добавляем ноль в конце
    }

    SUART.flush();
    String myData = (String)inData;
    Serial.println(myData);

    // потребляем данные
    // анализ входящих данных (в данных);
  }
}

, 👍0

Обсуждение

использовать 9600 бод. AVR SoftwareSerial не может надежно слушать на скорости 115200 бод, @Juraj

Я использовал SoftwareSerial для MIDI (со скоростью 31 250 бод), и он не работал надежно, поэтому действительно 9600 кажется хорошей отправной точкой, вероятно, вы не сможете подняться намного выше., @Michel Keijzers


1 ответ


Лучший ответ:

1

Как упоминает @Juraj в комментариях, не используйте 115200 бод с SoftwareSerial.

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

Использование более низкой скорости передачи данных (например, 9 600 бод) просто дает больше времени для обработки данных по мере их поступления.

,

И вы, и @Juraj были правы. Так что спасибо! Снижение скорости передачи (теперь используется 38400) устранило проблему с повреждением. Тем не менее, добавление *delay(5);* в конце цикла while получателя тоже помогает. Еще раз спасибо, ребята. Остается выяснить, почему он работал на 115200, а затем внезапно остановился., @veveve