Передача 15 переменных по сериал

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

  1. Maks2186

    Maks2186 Нуб

    Всем привет. Как правильно организовать передачу 15 переменных типа float, по сериал?
    Данные в таком формате 12.25,12.36,10.45,8.12, ...
    Отправляю с ардуино уно на esp8266.

    На ардуине формирую строку, кидаю в сериал, жду 1с:
    Код (C++):
    sendData =   String(data_a[0]) + "," + String(data_a[1]) + "," + String(data_a[2]) + "," + String(data_a[3]) + "," + String(data_a[4]) + "," + String(data_a[5]) + ","
                   + String(data_a[6]) + "," + String(data_a[7]) + "," + String(data_a[8]) + "," + String(data_a[9]) + "," + String(data_a[10]) + "," + String(data_a[11]) + ","
                   + String(data_a[12]) + "," + String(data_a[13]) + "," + String(data_a[14]) + ",";
      Serial.println(sendData);
      delay(1000);
    На есп, читаю в строку и шлю по вифи:
    Код (C++):
    if (Serial.available())
      {
        char temp = Serial.read();
        if (temp > ' ')
        {
          data += temp;
        }

    client.print(data);  
    На сервере(сокет) получаю кракозябры, типа х56/x25/x45 и т.д.

    Если на есп, я убираю прием с ардуины, и вывожу строку с данными 12.25,12.36,10.45,8.12 на сокет, то сокет обрабатывает их нормально, и выводит в таком виде в котором я отправил.

    Т.е выходит я не правильно принял данные с ардуины, пните в нужном направлении.
     
  2. b707

    b707 Гуру

    В виде двоичного буфера длиной 60 байт (60 = 15 переменных по 4 байта )
    То, как делаете вы - запихивать флоат в строки, чтобы после передачи разбирать их из строк обратно в числа - это удаление гланд через задницу.
     
    Arduiner001, Igor68 и arkadyf нравится это.
  3. ostrov

    ostrov Гуру

    Создать массив из этих переменных и перекинуть его побайтно (write-read). Или что нужно? В виде текста?
     
  4. b707

    b707 Гуру

    Если приглядется к первому сообщению - массив у автора уже есть. Это не сразу можно заметить, потому что он (автор) запихивает каждый элемент массива в строку по отдельности, как будто не догадывается о наличии в языке Си циклов :)

    Автор, - вам рано еще коды писать, начните с чтения учебника
     
    Igor68 и Tomasina нравится это.
  5. ostrov

    ostrov Гуру

    Про указатели и ссылки спрашивать не стоит наверное? )
     
  6. ИгорьК

    ИгорьК Гуру

    Это дело привычки и языка. Не зря же после массивов и структур Си придумали такие вещи как json, xml, etc. Не сями едиными...
     
  7. b707

    b707 Гуру

    Я с вами согласен - на Перле или Питоне, к примеру, я бы тоже строчками передавал.
    Но автор-то пишетт на Си... В Си, на мой взгляд, как раз работа со строками продумана слабее всего- и явно хуже, чем с двоичными данными - поэтому совершенно непонятно, зачем самому лезть в эти дебри, если данные изначально бинарные, "родные" для Си.
     
  8. ИгорьК

    ИгорьК Гуру

    С дебрями тоже не все однозначно. Представление float в разных железках компилятороами может быть выполнено по-разному и стыковки будут непростыми.
     
  9. Maks2186

    Maks2186 Нуб

    Float можно заменить на int, умножив на 1000 например. Чтобы оперировать с целыми числами, а на клиенте пк буду делить и писать в файлы.

    Когда есть желание и стремление, то ни чего не рано.

    Да, на ардуине есть массив, его передаю на есп, с есп на клиент в ПК.

    Мне нужно передать данные на пк, любым способом, главное что бы работало. С есп данные идут корректно, но когда с ардуины на есп и на пк то с ошибками, так как не правильно передаются с ардуины на есп.
     
    Последнее редактирование: 26 окт 2017
  10. Maks2186

    Maks2186 Нуб

    ПК без разницы какие данные и сколько строк разбирать. Мне главное передать данные на него.
     
  11. ИгорьК

    ИгорьК Гуру

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

    Я бы в вашем случае вместо массива Си делал простой json объект '{1:234.00,2:743.22...}' и перегонял его в компьютер где и парсил. Это как направление мысли.
     
    Последнее редактирование: 26 окт 2017
  12. Maks2186

    Maks2186 Нуб

    Программа на пк у меня написана под Linux, на фреймворке QT.

    Я сейчас проверил, в сериал есп пишу данные в ручную, далее передаю на пк. Пишу 1 в сериал есп, на пк получаю 47, 2 - 48. Т.е. приходят коды символов.

    Отправил число 450 пришли коды 52 53 48..

    json можно в си встроить? Я пока про json не читал, на работе. Дома почитаю.
     
    Последнее редактирование: 26 окт 2017
  13. ИгорьК

    ИгорьК Гуру

  14. b707

    b707 Гуру

    так зачем же дело встало? Получить из кода символа цифру - непосильная задача?

    это одно действие
    char c;
    int a;
    a = c - '0';
     
    MickNich и arkadyf нравится это.
  15. b707

    b707 Гуру

    Простите Игорь, согласится не могу. Ваш совет из разряда вредных.

    Вместо того чтоб один раз разобраться в различии представлений типа флоат на стороне ардуины и компа (залачка-то ерундовая. ну что может быть сложного в 4х байтах?) - вы предлагаете сначала формировать json обьект с одной стороны. а потом парсить его с другой? Неээфективный и медленный подход, имх, который. к тому же, потребует от автора много больше сил и времени, чем передача двоичных данных
     
  16. ИгорьК

    ИгорьК Гуру

    Давайте посмотрим. Возможно автор решит проблему и поделится.
    Быстро или медленно, много или мало - вещи относительные.
    Возможно решение лежит в программировании в машинных кодах - конечная задача известна только автору.

    Я понимаю, что оторваться ментально от привычек и подходов Си сложно. Но json в целом удобнее. Задача же не только "протолкнуть" данные, но и как-то обработать. И не обязательно это будет Си: Python на стороне компа гораздо удобнее. И если данные к нему придут в приятном для него формате - что здесь плохого?
     
  17. ИгорьК

    ИгорьК Гуру

    Добавлю. Json - не стиль ардуино. Но здесь и общение идет с компьютером. А ему (по мощности) плевать на то как придут данные - лишь бы программисту было удобно.
    Отправить данные с ардуино - та же бодяга: включил библиотеку и выполнил пример. ESP-8266 переправит это транзитом.
    Все несложно. Так что совет не так вреден как кажется. И я даю его в твердой уверенности что поступил бы именно так.
     
  18. b707

    b707 Гуру

    Согласен, самый правильный алгоритм - тот, который лучше знаешь :)
    ИМХО, у ТС уже достаточно вариантов. пусть выбирает.
     
    ИгорьК нравится это.
  19. Igor68

    Igor68 Гуру

    Конечно спорить не буду... но:
    Код (C++):

    float pf = 1234567.89;
    //snd - буфер для передачи
    memcpy(&snd[0], &pf, sizeof(float));
    ...
    //далее собственно передача
     
    правда snd[0] указал почти не так просто... при пиёме допустим в структуру или массив такое обращение:
    Код (C++):

    float fp = (*(float*)(&rcv[0]));
     
    будет нормально, а вот к примеру:
    Код (C++):

    //при передаче
    (*(float*)(&snd[1])) = 123.456;
    ...
    //при приёме
    float frs = (*(float*)(&rcv[1]));
     
    такое вряд ли прокатит... хотя можно и memcpy применить. Но всё же проще распологать данные в структуре/массиве кратно размеру (в байтах) ну типа этого:
    Код (C++):

    typedef struct _DAT
    {
           float       fp1;
           float       fp2;
           int32_t  p321;
           int16_t  p161;
           int8_t    p81;
    } DAT;
     
    то есть по убывающей - это гарантированно. Но можно и (как ранее говорил) memcpy.
    А ещё можно #pagma pack(1) примеить... но вот тут компиляторы разные сработают по разному. Прще сразу учесть выравнивание.
     
    ИгорьК нравится это.
  20. Maks2186

    Maks2186 Нуб

    Только не смейтесь... RX с TX перепутал...

    На есп сделал так:

    bool send = false;
    int c;
    String data = " ";

    Код (C++):
    while (Serial.available())
      {
       char temp=Serial.read();
         if (temp>' ') {
           //data += temp;    
           c = temp -'0';
           data +=c;
         }
       
         //c = Serial.read();
         send = true;    
      }
    Шлю на пк так:
    Код (C++):
      if(send)
      {
        client.print(data);
        data = " ";
        send = false;
      }
    На ардуине, шлю большую строку из первого поста через Serial.print();

    На пк, в программе на QT, даже не надо преобразовывать, строка приходит в первозданном виде, кроме запятой, она почему то приходит как -4.

    Перепробовал ку ча вариантов, потом пригляделся к проводам, и тут доперло что перепутал их.

    Спасибо за помощь всем!