РЕШЕНО Настройка через com-порт

Тема в разделе "Проводная и беспроводная связь", создана пользователем LCD 16x2, 12 фев 2020.

Статус темы:
Закрыта.
  1. LCD 16x2

    LCD 16x2 Нерд

    Добрый день! Нужен рабочий макет программы настройки через ком-порт: пользователь отправляет строку в виде "имя:значение\n", а ардуино считывает значение в переменную имя (строка или число). Нужно чтоб было простенько, без наворотов.
     
  2. Asper Daffy

    Asper Daffy Иксперд

  3. akl

    akl Гуру

    мне было нечего делать и я че-то накропал как мог, не проверял но вроде должно работать. как минимум оно компилируется.

    Код (C++):
    #define CMDLMAX 32 //максимальная длина строки команды
    #define CMDLMIN 1  //минимальная длина строки команды
    char cmd_rcv[CMDLMAX]; //массив для приема команд
    char cmdready = 0; //флаг поступления команды
    char cmderror = 0; //флаг ошибки распознавания команды
    char *cmd_pnt; //Указатель для отделения параметра от имени команды
    int cmdlen=0; //длина имени команды
    //строчки-имена команд
    const char cmdA_label[]="cmdA";
    const char cmdB_label[]="cmdB";
    const char cmdC_label[]="cmdС";
    //переменные для параметров
    int cmdA=0;
    int cmdB=0;
    int cmdC=0;//
    #define CMDSPLIT ':'//символ отделяющий имя команды от параметра
    #define CMDTERMIN '\n'//символ конца строчки
    //образец приходящей строчки:
    //cmdA:123\n
    //cmdA: 123\n
    //cmdA:-123\n

    void setup() {

      Serial.begin(9600);
    }

    void loop() {

      while (Serial.available()){//если что-то приходит в буфер сериала
        char c;//переменная для вынимания символов
        static char i=0;//статическая переменная - счетчик количества символов
        c=Serial.read();//вынимаем символ из буфера
        cmd_rcv[i]=c;//кдадем в наш буфер для команд
        i++;//прибавляем счетчик
        if(i>CMDLMAX){//если счетчик досчитал до конца но строка не кончилась
          cmdready=-1;//значит ошибка - ставим флаг в -1
          i=0;//обнуляем счетчик
          break; //прерываем считывание
        }
        cmd_rcv[i]=0;//если все норм в следующую ячейку буфера ложим нуль
        if(c==CMDTERMIN){//если текущий принятый символ это конец строчки
          if(i<CMDLMIN){//но длина строки слишком мала
            cmdready=-1;//ошибка
             i=0;//обнуляем счетчик
            break;
          }
          else{//если все норм
            cmdready=1;//ставим флаг приема команды в 1
            i=0; //обнуляем счетчик
            break;
          }
        }
      }
      if(cmdready<0){//если была ошибка приема
        Serial.println("rcv_error");//отсылаем сообщение
      }else if(cmdready>0){//если строка принялась
        //находим в строке разделительный символ ':'
        //cmdlen станет равен его положению в строке
        for(cmdlen=0; cmdlen<CMDLMAX && cmd_rcv[cmdlen]!=CMDSPLIT && cmd_rcv[cmdlen]!=0;cmdlen++){;}
        if(cmdlen==CMDLMAX || cmd_rcv[cmdlen]==0){cmderror=1;}//если не нашлось разделителя - ошибка чтения команды
      }
      if(!cmderror && cmdready>0){//если разделитель в строке нашелся и строка принята
        cmd_pnt=cmd_rcv; //нацеливаем указатель на приемный массив
        cmd_rcv[cmdlen]=0;//вместо разделителя ложим нуль, как бы деля строку на две
        cmd_pnt+=cmdlen+1;//устанавливаем указатель на ячейку строки сразу за разделителем
        //cmd_pnt теперь указывает как бы на новый массив, начинающийся после разделителя
        if(!strcmp(cmd_rcv,cmdA_label)){//сравниваем наш обрезанный нулем массив с именами команд
          cmdA=atoi(cmd_pnt);//а цифровое значение идущее после разделителя вынимаем функцией atoi
          Serial.println("OK");
        }else if(!strcmp(cmd_rcv,cmdB_label)){
          cmdB=atoi(cmd_pnt);
          Serial.println("OK");
        }else if(!strcmp(cmd_rcv,cmdC_label)){
          cmdC=atoi(cmd_pnt);
          Serial.println("OK");
        }//....так проверяем все команды
         else{cmderror=1;}//если ни одно имя команды не совпало - значии ошибка
      }
      if(cmderror){
        cmderror=0;
        Serial.println("cmd_error");//отсылаем сообщение об ошибке чтения команды
      }
       cmdready=0;//обнуляем флаг приема команды
    }
    исправил пару багов. Но наверняка их еще много, так что тестируй
     
    Последнее редактирование: 14 фев 2020 в 12:34
    LCD 16x2 нравится это.
  4. LCD 16x2

    LCD 16x2 Нерд

    Спасибо, но оно не работает :(. Сначала ругался на Serial1, заменил его на Serial, загрузил, но работать по-прежнему отказывается: просто спамит меня "cmd-error" (со старта).
     
  5. Asper Daffy

    Asper Daffy Иксперд

    Странно, что тебя это удивляет. Человек же написал, что он не проверял.

    Если ты прочитаешь на вот этой странице, начиная с фразы "А вот если подходящих примеров нет" (найди её поиском), то узнаешь всё, про запрос прошивки на форумах, и про неработающие коды там тоже написано. А когда узнаешь и осознаешь, тогда перечитай мой пост #2
     
  6. akl

    akl Гуру

    а где там у меня сериал1? он там был когда я только выложил. Я потом исправлял еще много что, а ты наверно самую раннюю версию взял. попробуй то что там прямо сейчас лежит.

    сегодня вечером сам поотлаживаю раз уж взялся.
     
    LCD 16x2 нравится это.
  7. akl

    akl Гуру

    еще баговину нашел - был не нацелен указатель на массив. видимо случайно стер строчку ту.
    вот короче последняя версия, потестил как мог без ардуины.
    Код (C++):
    #define CMDLMAX 32 //максимальная длина строки команды
    #define CMDLMIN 1  //минимальная длина строки команды
    char cmd_rcv[CMDLMAX]; //массив для приема команд
    char cmdready = 0; //флаг поступления команды
    char cmderror = 0; //флаг ошибки распознавания команды
    char *cmd_pnt; //Указатель для отделения параметра от имени команды
    int cmdlen=0; //длина имени команды
    //строчки-имена команд
    const char cmdA_label[]="cmdA";
    const char cmdB_label[]="cmdB";
    const char cmdC_label[]="cmdС";
    //переменные для параметров
    int cmdA=0;
    int cmdB=0;
    int cmdC=0;//
    #define CMDSPLIT ':'//символ отделяющий имя команды от параметра
    #define CMDTERMIN '\n'//символ конца строчки
    //образец приходящей строчки:
    //cmdA:123\n
    //cmdA: 123\n
    //cmdA:-123\n

    void setup() {

      Serial.begin(9600);
    }

    void loop() {

      while (Serial.available()){//если что-то приходит в буфер сериала
        char c;//переменная для вынимания символов
        static char i=0;//статическая переменная - счетчик количества символов
        c=Serial.read();//вынимаем символ из буфера
        cmd_rcv[i]=c;//кдадем в наш буфер для команд
        i++;//прибавляем счетчик
        if(i>CMDLMAX){//если счетчик досчитал до конца но строка не кончилась
          cmdready=-1;//значит ошибка - ставим флаг в -1
          i=0;//обнуляем счетчик
          break; //прерываем считывание
        }
        cmd_rcv[i]=0;//если все норм в следующую ячейку буфера ложим нуль
        if(c==CMDTERMIN){//если текущий принятый символ это конец строчки
          if(i<=CMDLMIN){//но длина строки слишком мала
            cmdready=-1;//ошибка
             i=0;//обнуляем счетчик
            break;
          }
          else{//если все норм
            cmdready=1;//ставим флаг приема команды в 1
            i=0; //обнуляем счетчик
            break;
          }
        }
      }
      if(cmdready<0){//если была ошибка приема
        Serial.println("rcv_error");//отсылаем сообщение
      }else if(cmdready>0){//если строка принялась
        //находим в строке разделительный символ ':'
        //cmdlen станет равен его положению в строке
        for(cmdlen=0; cmdlen<CMDLMAX && cmd_rcv[cmdlen]!=CMDSPLIT && cmd_rcv[cmdlen]!=0;cmdlen++){;}
        if(cmdlen==CMDLMAX || cmd_rcv[cmdlen]==0){cmderror=1;}//если не нашлось разделителя - ошибка чтения команды
      }
      if(!cmderror && cmdready>0){//если разделитель в строке нашелся и строка принята
        cmd_pnt=cmd_rcv; //нацеливаем указатель на приемный массив
        cmd_rcv[cmdlen]=0;//вместо разделителя ложим нуль, как бы деля строку на две
        cmd_pnt+=cmdlen+1;//устанавливаем указатель на ячейку строки сразу за разделителем
        //cmd_pnt теперь указывает как бы на новый массив, начинающийся после разделителя
        if(!strcmp(cmd_rcv,cmdA_label)){//сравниваем наш обрезанный нулем массив с именами команд
          cmdA=atoi(cmd_pnt);//а цифровое значение идущее после разделителя вынимаем функцией atoi
          Serial.println("OK");
        }else if(!strcmp(cmd_rcv,cmdB_label)){
          cmdB=atoi(cmd_pnt);
          Serial.println("OK");
        }else if(!strcmp(cmd_rcv,cmdC_label)){
          cmdC=atoi(cmd_pnt);
          Serial.println("OK");
        }//....так проверяем все команды
         else{cmderror=1;}//если ни одно имя команды не совпало - значии ошибка
      }
      if(cmderror){
        cmderror=0;
        Serial.println("cmd_error");//отсылаем сообщение об ошибке чтения команды
      }
       cmdready=0;//обнуляем флаг приема команды
    }
     
    Последнее редактирование: 14 фев 2020 в 14:14
    LCD 16x2 нравится это.
  8. LCD 16x2

    LCD 16x2 Нерд

    Спасибо огромное!!! Всё работает! :):):) Значит, есть ещё на свете добрые люди!
     
Статус темы:
Закрыта.