Последовательное чтение и отправка в UDP

Я пытался отправить все, что получено от serial по udp, но это не работает должным образом. сторона приемника показывает номер 50 51 53 ..... результат, как показано ниже скриншота:

кто-нибудь может мне помочь, пожалуйста, исправить ?

скетч отправителя:

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "MikroTik";
const char* password = "12345678";
unsigned int localPort = 2390;

WiFiUDP Udp;
void setup() {
  delay(1000);
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Udp.begin(localPort);
}

void loop() {
  Udp.beginPacket("10.5.50.23", localPort);
  int val = Serial.read();
  Udp.print(val);
  Udp.endPacket();
  delay(10);
}

скетч приемника:

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "MikroTik";
const char* password = "12345678";
unsigned int localPort = 2390; 
char packetBuffer[255];
WiFiUDP Udp;

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }
  Udp.begin(localPort);
}

void loop() {
  delay(10);
  if (Udp.parsePacket()) {
    int len = Udp.read(packetBuffer, 255);
    if (len > 0) {
      packetBuffer[len] = 0;
      Serial.println(packetBuffer); 
    }
  }
}

, 👍-1

Обсуждение

спасибо за ответ. извините, я новичок в кодировании arduino можете ли вы помочь мне и отредактировать мой код, чтобы он работал правильно ?, @ErfanDL

Какая именно помощь вам нужна? Я объяснил, что вы должны заменить Udp.print() на Udp.write(). Дальнейшие правки зависят от того, что вы хотите сделать с кодом. Вы действительно описали это., @chrisl

хорошо, я перешел на Udp.write(val), но на стороне приемника отображается только первый номер последовательного чтения. например, вместо того, чтобы показывать число 300, он отображает число 3, @ErfanDL

Это та часть, которая касается чтения до символа-разделителя. Например, для этого вы можете использовать Serial.readStringUntil('\n'). Это блокирующая функция, но это должно быть нормально для вашего случая. Извините, но я не буду писать код за вас. В Интернете есть много примеров кодов и учебных пособий по этому поводу. Вы также можете посмотреть на пример serialEvent, который поставляется с Arduino IDE, @chrisl

Помимо проблем с кодом, я надеюсь, вы понимаете, что UDP не является "надежным" протоколом. Это не гарантирует, что вы получите все, что было отправлено, и не скажет вам, если что-то упадет., @romkey


1 ответ


1

Проблема заключается в различных интерпретациях двоичных данных и заключается в этих двух строках:

int val = Serial.read();
Udp.print(val);

То, что вы записываете в последовательный монитор, - это текст в кодировке ASCII. Каждый байт данных соответствует одному символу. Если вы пишете a, это принимается за ASCII - представление. В шестнадцатеричном формате этот символ равен 0x61, а в десятичном-97. Это фактическое значение, которое передается в ESP по последовательному каналу. Затем вы считываете это в целое число. ТАКИМ образом, val будет иметь значение 97. Затем вы используете Udp.print(val). Все функции print() предназначены для создания удобочитаемого представления данных, что означает кодировку ASCII (это стандартное соглашение Arduino). Итак, в основном вы сказали здесь: "Вот у вас есть число (целое число). Распечатайте его в UDP-пакете в удобочитаемой (ASCII) форме". Таким образом, UDP-пакет теперь содержит строку ASCII "97". Вероятно, вы набрали цифру 5, а затем 4 несколько раз. Их десятичные значения равны 53 и 52.

Вероятно, существует также функция Udp.write(). Функции write() по соглашению не изменяют данные. Они просто пишут это без интерпретации. Таким образом, с помощью Udp.write() фактическое двоичное значение полученных данных будет отправлено, и буква a будет отображаться как буква a на последовательном выходе приемника.

Это хорошо работает до тех пор, пока вы хотите отправлять только отдельные байты в своих пакетах. Также обратите внимание, что Serial.read() вернет -1, если в буфере нет данных для чтения. Поэтому, чтобы справиться с этим, вам нужно увеличить код отправителя:

  • Считывайте только с последовательного сервера, если в буфере действительно есть данные. Вы можете использовать оператор if для этого, например:

      if(Serial.available()){ // read in this if statement
    
  • Считывание всех данных с последовательного до определенного символа - разделителя, который отмечает конец полного сообщения. Обычно для этого используется символ новой строки \n. Вы можете настроить последовательный монитор так, чтобы он использовал символ новой строки в качестве окончания строки (затем он добавляется к набранному тексту при нажатии клавиши Enter). В Интернете есть много примеров кодов для этого.

,