Проблема с сериал портом (возможно, проблема в очистке буфера, но это не точно)

Тема в разделе "Arduino & Shields", создана пользователем _Scotty_the_Engineer_, 16 ноя 2020.

Метки:
  1. Всем добрый вечер)
    Ниже приведен кусочек очень упрощенного кода. Что должно происходить в идеале: я ввожу 2, в сериал выводится 222, затем я ввожу 3, и в сериал выводится еще 333. На деле выводятся только двойки - тройки не выводятся, и я никак не могу понять, почему.
    В оригинальном коде мы вводим 1, если хотим получить данные с датчика, и вводим 2, если после этого еще хотим ввести некоторые параметры для датчика.


    Код (C++):
    if ( Serial.available() > 0 ) {
      incomingData = Serial.parseInt();
      switch (incomingData) {
        case 1:
          Serial.println(" 111 ");
          break;

        case 2:
          Serial.println("222");
          if ( Serial.available() > 0 ) {
            incomingData2 = Serial.parseInt();
            if (incomingData2 == 3) {
              Serial.println("333");
            }
          }
          break;
      }
    }
     
  2. NikitOS

    NikitOS Шут Администратор

    Оно и не выполнится. case 2 выполняется, когда будет получено «2» в Serial. Вы пытаетесь прочитать в нем новые данные, но эта проверка просто не выполнится, так как case уже отаботал. Используйте флаги и еще один case.
     
  3. Можно, пожалуйста, поподробнее)
     
  4. b707

    b707 Гуру

    не запихивайте вариант "333" внутрь "222", сделайте его отдельным case по аналогии с "111"
     
    NikitOS нравится это.
  5. Asper Daffy

    Asper Daffy Иксперд

    Так ему важно, чтобы 3 шёл именно после 2, а не когда попало. А проверка происходит быстро и когда он вводит эту 3, всё уже давно проверилось, а ещё раз сюда она не попадает - опять 2-ка нужна.
     
  6. b707

    b707 Гуру

    эт я понимаю :) но что-то мне подсказывает, что он даже так не сделает, хотя эт проще :)
     
  7. parovoZZ

    parovoZZ Гуру

    таки delay в помощь.
     
  8. Nekto_nikto

    Nekto_nikto Гик

    Меняем
    if( Serial.available()>0)
    во втором case на
    while(not(Serial.available())) { }

    и т.д.
     
  9. a1000

    a1000 Гуру

    Тут надо немного алгоритм уточнить. После "2" всегда "3" будет идти?
     
    NikitOS нравится это.
  10. parovoZZ

    parovoZZ Гуру

    не всё так просто:
    С представленным ТС алгоритмом это невозможно в принципе. Необходимо сперва "отлавливать" из сериала строку с нажатой цифрой, запомнить её, а уже потом в отдельной подпрограмме её парсить.
    Не знаю, как в ардуринах работает сериал, но "отлавливать" символы строк необходимо в прерывании от сериал порта.
     
  11. akl

    akl Гуру

    в ардуинах по прерыванию приходящее кладется в циклический буфер, а команды типа Serial.read() достают из этого буфера.

    как уже заметили выше, проще всего использовать флаг

    Код (C++):
    static char flag = 0;
    if ( Serial.available() > 0 ) {
      incomingData = Serial.parseInt();
      switch (incomingData) {
        case 1:
          Serial.println(" 111 ");
          break;

        case 2:
          Serial.println("222");
          flag =1;
          break;
        case 3:
          if(flag==1){
              Serial.println("333");
              flag=0;
          }
          break;
      }

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

    например можно придумать условный протокол что каждая команда начинается на '#' и заканчивается на '\n' (или '\r'). тогда простейшая функция будет просто ждать пока придет '#', и положит в массив все что до '\n' (с учетом ограничения длины массива), затем проанализирует это и сделает вывод что это определенная команда или ошибка.
    Передавать данные можно командами типа
    "#param1=2314\n"
    тогда например ардуина легко поймет что param1 это параметр такой-то, а после '=' идет значение.
     
    Последнее редактирование: 17 ноя 2020
    Daniil нравится это.
  12. Daniil

    Daniil Гуру

    Если что, то прерывания по сериал есть в примерах, там можно строку получить, при появлении /n выставлять флаг "строка пришла" и т.д.