Нужна помощь. Передать русский текст с C# на Arduino по udp

Тема в разделе "Проводная и беспроводная связь", создана пользователем RussoTuristto, 20 апр 2016.

  1. RussoTuristto

    RussoTuristto Нуб

    Доброго всем дня.
    Собственно в Arduino я новичок, так что сильно не пинайте. Есть сервер на C# с которого я отправляю UDP пакеты на ENC28j60 шилд. Мне необходимо передавать строку русского текста. Использую кодировку UTF-8. Но как я понимаю, при десериализации на стороне Arduino используется ASCII. Как это исправить, или может есть какие то другие решения.
    Вот код на стороне C#:
    Код (C++):
    byte[] bytes = Encoding.UTF8.GetBytes("Привет");
    udpClient.Send(bytes, bytes.Length);
    Вот на стороне Arduino:
    Код (C++):
    ether.packetLoop(ether.packetReceive());
    void udpSerialPrint(uint16_t dest_port, uint8_t src_ip[4], uint16_t src_port, const char *data, uint16_t len)
    {
      IPAddress src(src_ip[0],src_ip[1],src_ip[2],src_ip[3]);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(data);
    }
     
  2. Megakoteyka

    Megakoteyka Оракул Модератор

    А что мешает отправлять в ASCII?
     
  3. RussoTuristto

    RussoTuristto Нуб

    получаю вот такие сообщения: ??? ????? ????
     
  4. RussoTuristto

    RussoTuristto Нуб

    Забыл упомянуть что вот так отлично работает
    Код (C++):
    lcd.print("привет");
     
  5. RussoTuristto

    RussoTuristto Нуб

    Тема закрыта, красивого решения найдено не было(, пришлось закодировать строку латинскими символами и в последующем раскодировать ее на ардуино...
     
  6. Неужели нет никакого решения, столкнулся с такой же проблемой, RussoTuristto, поделитесь пожалуйста)
     
  7. RussoTuristto

    RussoTuristto Нуб

    Прошу прощения что не сразу ответил.
    В общем алгоритм следующий:

    На стороне C#:
    Кодируем строку в цикле: # - спец. символ который сообщает о начале нового символа, далее в самом начале если необходимо передать заведомо известное информационное сообщение просто ставим нужную цифру(в моей реализации случайно она там не может оказаться). Потом кодируем само сообщение - просто в цикле свичем.

    На стороне ардуино:
    Код (C++):
    void udpSerialPrint(uint16_t dest_port, uint8_t src_ip[4], uint16_t src_port, const char *data, uint16_t len)
    {

      if (data[0] == '#')
      {

        if (data[1] == '0')
        {
          // звук не успешно
          tone(7, 423, 1000 / 8);
          delay(200);
          noTone(7);
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print(L"ДОБАВЛЕНА КАРТА");
          lcd.setCursor(1, 1);
          lcd.print(tmp);
          delay(3000);
          lcd.clear();
          lcd.setCursor(5, 0);
          lcd.print(L"ГОТОВ");
          //lcd.setCursor(0, 1);
          //lcd.print(L"ПОДНЕСИТЕ КАРТУ");
        }
        else if (data[1] == '1')
        {
          // звук не успешно
          tone(7, 423, 1000 / 8);
          delay(200);
          noTone(7);
          lcd.clear();
          lcd.setCursor(1, 0);
          lcd.print(L"НЕТ ВЛАДЕЛЬЦА");
          lcd.setCursor(1, 1);
          lcd.print(tmp);

          delay(3000);
          lcd.clear();
          lcd.setCursor(5, 0);
          lcd.print(L"ГОТОВ");
          //lcd.setCursor(0, 1);
          //lcd.print(L"ПОДНЕСИТЕ КАРТУ");
        }
        else if (data[1] == '2')
        {
          lcd.clear();
          lcd.setCursor(6, 0);
          for (int i = 2; i < len; i++)
          {
            if (data[i] == '1')
              lcd.print(L"1");
            else if (data[i] == '2')
              lcd.print(L"2");
            else if (data[i] == '3')
              lcd.print(L"3");
            else if (data[i] == '4')
              lcd.print(L"4");
            else if (data[i] == '5')
              lcd.print(L"5");
            else if (data[i] == '6')
              lcd.print(L"6");
            else if (data[i] == '7')
              lcd.print(L"7");
            else if (data[i] == '8')
              lcd.print(L"8");
            else if (data[i] == '9')
              lcd.print(L"9");
            else if (data[i] == '0')
              lcd.print(L"0");
            else if (data[i] == ':')
              lcd.print(L":");

          }
          //lcd.setCursor(0, 1);
          //lcd.print(L"ПОДНЕСИТЕ КАРТУ");
        }
      }
      else
      {
        // звук успешно
        tone(7, 1234, 1000 / 8);
        delay(200);
        noTone(7);
        tmp = "";
        lcd.clear();
        lcd.setCursor(0, 0);
        for (int i = 0; i < len; i++)
        {
          if (data[i] == '%')
          {
            if (tmp == "AA")
              lcd.print(L"А");
            else if (tmp == "BB")
              lcd.print(L"Б");
            else if (tmp == "VV")
              lcd.print(L"В");
            else if (tmp == "GG")
              lcd.print(L"Г");
            else if (tmp == "DD")
              lcd.print(L"Д");
            else if (tmp == "EE")
              lcd.print(L"Е");
            else if (tmp == "YE")
              lcd.print(L"Ё");
            else if (tmp == "ZH")
              lcd.print(L"Ж");
            else if (tmp == "ZZ")
              lcd.print(L"З");
            else if (tmp == "II")
              lcd.print(L"И");
            else if (tmp == "YY")
              lcd.print(L"Й");
            else if (tmp == "KK")
              lcd.print(L"К");
            else if (tmp == "LL")
              lcd.print(L"Л");
            else if (tmp == "MM")
              lcd.print(L"М");
            else if (tmp == "NN")
              lcd.print(L"Н");
            else if (tmp == "OO")
              lcd.print(L"О");
            else if (tmp == "PP")
              lcd.print(L"П");
            else if (tmp == "RR")
              lcd.print(L"Р");
            else if (tmp == "SS")
              lcd.print(L"С");
            else if (tmp == "TT")
              lcd.print(L"Т");
            else if (tmp == "UU")
              lcd.print(L"У");
            else if (tmp == "FF")
              lcd.print(L"Ф");
            else if (tmp == "KH")
              lcd.print(L"Х");
            else if (tmp == "TS")
              lcd.print(L"Ц");
            else if (tmp == "CH")
              lcd.print(L"Ч");
            else if (tmp == "SH")
              lcd.print(L"Ш");
            else if (tmp == "CS")
              lcd.print(L"Щ");
            else if (tmp == "TZ")
              lcd.print(L"Ъ");
            else if (tmp == "YI")
              lcd.print(L"Ы");
            else if (tmp == "MZ")
              lcd.print(L"Ь");
            else if (tmp == "EA")
              lcd.print(L"Э");
            else if (tmp == "YU")
              lcd.print(L"Ю");
            else if (tmp == "YA")
              lcd.print(L"Я");
            else if (tmp == ":")
              lcd.print(L":");
            else if (tmp == ".")
              lcd.print(L".");
            else if (tmp == "1")
              lcd.print(L"1");
            else if (tmp == "2")
              lcd.print(L"2");
            else if (tmp == "3")
              lcd.print(L"3");
            else if (tmp == "4")
              lcd.print(L"4");
            else if (tmp == "5")
              lcd.print(L"5");
            else if (tmp == "6")
              lcd.print(L"6");
            else if (tmp == "7")
              lcd.print(L"7");
            else if (tmp == "8")
              lcd.print(L"8");
            else if (tmp == "9")
              lcd.print(L"9");
            else if (tmp == "0")
              lcd.print(L"0");
            else if (tmp == " ")
              lcd.print(L" ");

            tmp = "";
            delay(100);
          }
          else if (data[i] == '#')
          {
            tmp = "";
            lcd.setCursor(0, 1);
          }
          else
          {
            tmp += data[i];
          }
        }
        delay(3000);
        lcd.clear();
        lcd.setCursor(5, 0);
        lcd.print(L"ГОТОВ");
        //lcd.setCursor(0, 1);
        //lcd.print(L"ПОДНЕСИТЕ КАРТУ");
      }
      Serial.println(data);

      waitServer = false;
    }
    Код не блещет красотой (писался наспех), но работает и со своей задачей полностью справляется)
    Прокомментирован тоже слабо, так что если будут вопросы спрашивайте
     
  8. ага, спасибо.
    У Вас, судя по всему, тоже что-то связанное с системой контроля доступа)?
     
  9. RussoTuristto

    RussoTuristto Нуб

    Да, она самая)
     
  10. rigl

    rigl Нуб

    Посмотрите кодировку файла скетча, и тогда станет понятно в какой кодировке передавать,
    это если lcd.print("привет"); работает.
    Или открывайте кодировки символов русских и смотрите. Как закодированы буквы.
    Например буква Я в кодировке win-1251 0xB0
    Вот такой код, может прояснит что-то
    Код (C++):
    char letter = 0x00;
    char *rusian = "ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮйцукенгшщзхъфывапролджэячсмитьбю";
    void setup() {
      Serial.begin(9600);
      Serial.println("Русские буквы в кодировке ASCII");
      while(*rusian != '\0')
        {
          Serial.print((char)(*rusian));
          Serial.print(" ");
          Serial.println((uint8_t)(*rusian++),HEX);
        }
    }
    void loop() {
     
    Serial.print("Symbol:");
    Serial.print(letter);
    Serial.print(" Code:");
    Serial.println((uint8_t)letter++,HEX);
    delay(500);
    }
     
  11. joman

    joman Гик

    Я бы для начала вернул бы с ардуино полученное сообщение в сериал и посмотрел бы на него с точки зрения кодировки.
    т.е. вместо
    Код (C++):
     lcd.print(data);
    написал бы
    Код (C++):
    Serial.println(data);
    поймал бы его на компе и посмотрел бы.
    вероятно в этой строке
    Код (C++):
    byte[] bytes = Encoding.UTF8.GetBytes("Привет");
    нужно просто заменить кодировку на какую то другую на пример:
    Код (C++):
    Encoding.GetEncoding("windows-1251").GetBytes("Привет")
     
  12. joman

    joman Гик

    Есть еще один вариант:
    На сервере написать:
    Код (C++):
    int i =0;
    foreach( EncodingInfo ei in Encoding.GetEncodings() )
    {
        byte[] bytes = ei.GetEncoding().GetBytes("Привет" + i.toString());
        Console.Write(i.toString() + ei.Name );
        udpClient.Send(bytes, bytes.Length);
        i++;
        // Тут еще надо задержку пихнуть, чтобы посмотреть что будет на ардуино
    }
    Ну и собственно смотреть на результаты на ардуине.
    При нормальной кодировке посмотреть на циферку и посмотреть название кодировки в консоле