Чтение из serial

Тема в разделе "Arduino & Shields", создана пользователем r0c, 6 мар 2022.

  1. r0c

    r0c Гик

    Подскажите , пожалуйста, как решить такой вопрос?
    в Serial Arduino Nano по команде приходит такой пакет байтов от устройства:
    Код (C++):

    0:00AA4029066244
    1:0000000000312A
    2:2D760000310001
    3:000000486809C8
    4:2D760000680001
    5:0000004800312A
    6:00000000680001
    7:00AA4000AA0001
    8:00031001006001
    9:09AA00486809C8
    ... и так далее еще 10 строк
     
    Просто чтение буфера UART не не работает, последние строки обрезаются.
    Как вытащить байты из последних строк пакета? Именно в них содержится нужные данные.
    Пример чтения пакета байтов небольшого размера рабоает без проблем:
    Код (C++):

    while (Serial.available()) {
     char inChar = (char)Serial.read();
     inputString += inChar;
     if (inChar == '\n')  Serial.println(inputString);
     
    Ткните ссылку, где почитать?
    Спасибо.
     
  2. SergeiL

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

    Нет в потоке строк, все это байты и перевод строки тоже определенный байт.
    Могу предположить, что используя string вы просто не успеваете опустошать буфер приема, буфер переполняется и информация теряется (не вытаскивается из регистра приема, так как буфер переполнился ).
    Для начала попробуйте снизить скорость обмена между устройствами.
     
  3. b707

    b707 Гуру

    длина пакета данных всегда одинаковая? Если да - то просто пропускайте ненужные байты, не записывая.

    Если пакеты разные - то для начала нужно разобраться, как определить длину пакета.
     
  4. r0c

    r0c Гик

    скорость передачи снизить нельзя.
    пакетов несколько, но они фиксированной длины.
     
  5. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Здесь вы накапливаете массив (строку) байт размером минимум 14х20=280. Плюс служебные байты. Что-то вспоминаются ограничения (256 символов) на длину строки !!! Ему места зарезервировано ?
    А если не накапливать массив, а печатать каждый байт ?
     
  6. SergeiL

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

    Я же написал, избавьтесь от String, он тут не нужен, а операция добавления символа в строку типа String - не быстрое дело связанное с выделением новой динамической памяти и перетаскиванием накопленных символов в новую память.

    Убирайте String, выделите массив байт char, судя по вашему примеру - 20 байт должно хватить.
    Считали новое значение.
    Получили '\n' - записали в массив 0, вывели массив, сбросили указатель на последний байт в 0.
    Получили НЕ '\n' - Записывайте байт в массив, увеличиваем указатель на последний байт (сдвигаемся на следующий байт).
    В коде будет выглядеть как то так:
    Код (C++):
      static unsigned char i = 0;
      static char buff[20];

      while (Serial.available())
      {
        char inChar = (char)Serial.read();
        if (inChar == '\n')
        {
          buff[i] = 0;
          Serial.println(buff);
          i = 0;
        }
        else
          buff[i++] = inChar;
      }
     
     
    Михаил123 и r0c нравится это.
  7. b707

    b707 Гуру

    Если пакеты разные, как вы определяете, какиебайты вам нужны?
     
  8. r0c

    r0c Гик

    Заголовки у пакетов разные. И размер разный. Номера нужных байтов в пакете заранее известны. Нужно лишь пару байт из середины и конца пакета взять . Остальное - мусор. Большая часть там нули...
     
  9. b707

    b707 Гуру

    тогда еще раз повторю предыдущий совет - пропускайте ненужные байты и буфер увеличивать не нужно будет
     
  10. r0c

    r0c Гик

    Спасибо за советы.
    Завести счетчик байтов ? или лучше счетчик '\n', что бы сразу пропускать ненужную "строку" целиком?
     
  11. SergeiL

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

    Так кто же тут знает, что вам нужно.
    Код из вашего вопроса выше, тоже не имеет особого смысла: получаем байты посимвольно, дожидаемся '\n' отправляем их обратно :)
     
  12. parovoZZ

    parovoZZ Гуру

    Читать непосредственно из приемного регистра UART. Как только поняли, что приняли первый пакет (с этим проблем нет?), включаем счётчик байтов и все лишние байты пропускаем (даже не читая из регистра) по флагу приема байта (можно мониторить этот флаг, но лучше зайти в прерывание). Но ой - это выходит за рамки дурины. Она не для таких задач. Поэтому читаем Евстифеева.
    Ну и никакие мегабуферы здесь не нужны. Только то, что нам надо принять.
     
  13. r0c

    r0c Гик

    Спасибо за советы. Немного не понятно, как делать пропуск байтов. Но понятно одно- мой подход в корне не верный, есть более простое решение. Буду читать, искать дальше.
     
  14. b707

    b707 Гуру

    Serial.read() нужное число раз без сохранения
     
    SergeiL нравится это.
  15. SergeiL

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

    А я бы все таки смотрел, что приходит.
    Может ведь прийти и начало пакета раньше времени, например, если сбой какой-то, и байт не будет принят.
    Но тут нужно смотреть спеку по протоколу обмена.
     
  16. r0c

    r0c Гик

    Нашел интересный пример чтения из Serial по прерыванию
    https://wikihandbk.com/wiki/Arduino:Примеры/SerialEvent
    Используется для разбора данных с устройств типа gps приемников, когда данный поступают постоянно и в большом количестве. Пишет в массив построчно до символа '\n'.

    Код (C++):
    [code]
    static char buff[90];
    static unsigned char i = 0;
    boolean Complete = false;  // флаг заполнения
    void setup() {
      Serial.begin(38400);
    }
    void loop() {
      //  выводим пакет построчно:
      if (Complete) {
        Complete = false;
        Serial.print(buff);
      }
    }
    void serialEvent() {
      while (Serial.available()) {
        char inChar = (char)Serial.read();
        buff[i++] = inChar;   // заполняем условную строку из пакета
        if (inChar == '\n') {//обнуляем после перевода строки
          buff[i] = 0;
          i = 0;
          Complete = true;
        }
      }
    }
     
    [/code]
    Все таки, по прерыванию гораздо удобнее. Осталось разобраться, как отсечь ненужные "строки" (хотя конечно же там не строки ) и вытащить нужный байт.
    Код (C++):

    0:00AA4029066244
    1:0000000000312A
    2:2D760000310001
    3:000000486809C8
    4:2D760000680001
    5:0000004800312A
    6:00000000680001
    7:00AA4000AA0001
    8:00031001006001
    9:09AA00486809C8
     
     
  17. parovoZZ

    parovoZZ Гуру

    тихий ужасЪ
     
  18. b707

    b707 Гуру

    в этом примере нет чтения Сериал по прерыванию
     
  19. r0c

    r0c Гик

    Я понимаю, что это ваша работа- оставлять комментарии к любым сообщениям, тем самым направляя на саморазвитие.
    Но прочитав много форумов за эту неделю, я так и не нашел решения вопроса.
    Как же вытащить нужный байт из конца большого массива данных? Подскажите, пожалуйста, с примером кода.
     
  20. Рокки1945

    Рокки1945 Гуру

    приветствую - до какой строчки принимает буфер?