вопросы по общению с МК через сериал порт

Тема в разделе "Arduino & Shields", создана пользователем kulver, 2 окт 2012.

  1. kulver

    kulver Нерд

    Первый вопрос.
    Вот есть такой код:
    Код (Text):
      int sign = +1;
      int new_destination = 0;
      float destination = 0;
      // read the serial:
      while (Serial.available() > 0) {
        int inByte = Serial.read();
          if (inByte == 45) {
            sign = -1;
          }
          else {
            new_destination = new_destination*10;
            new_destination = new_destination + (inByte - 48)*sign;
          };
        };
      destination = destination + new_destination ;
      if (new_destination != 0){
        Serial.print("I received: ");
        Serial.println(destination);
    И в нём всё отлично работает. Что даже странно. Число склеивается в единое из отдельных символов, знак минус дописывается, всё круто.

    И вот есть другой, "большой" код, в который я копипастнул этот кусок, получилось так:
    Код (Text):
    //motor
    const int Motor1_Speed = 6;
    const int Motor1_Dir = 7;
     
    //slider
    float last_pos_x = 0;
    const float stepp = 0.2083;
     
    //hall sensor
    const int Sensor1_Signal = A2;
    boolean MagnetNear = false;
    boolean MagnetNearOld = false;
    int MagnetMax = 480;
    int MagnetMin = 400;
     
     
    void setup(){
      Serial.begin(115200);
    }
     
    void loop(){
      //НАЧАЛО СКОПИРОВАННОГО КУСКА
      int sign = +1;
      int new_destination = 0;
      float destination = 0;
      // read the serial:
      while (Serial.available() > 0) {
        int inByte = Serial.read();
          if (inByte == 45) {
            sign = -1;
            //Serial.println("YAY!"); <--------------- Чудо-Камент.
          }
          else {
            new_destination = new_destination*10;
            new_destination = new_destination + (inByte - 48)*sign;
          };
        };
      destination = destination + new_destination ;
      if (new_destination != 0){
        Serial.print("I received: ");
        Serial.println(destination); //КОНЕЦ СКОПИРОВАННОГО КУСКА
        float pos_x = 0;
        if (destination > 0) {
          digitalWrite(Motor1_Dir, LOW); //LOW > k motoru; HIGH < ot motora;
        } else {
          digitalWrite(Motor1_Dir, HIGH); //LOW > k motoru; HIGH < ot motora;  
        };
        digitalWrite(Motor1_Speed, HIGH);
        unsigned long time = millis();
        unsigned long time2;
        do{
          int avValue = analogRead(Sensor1_Signal);
          if (avValue<MagnetMin) {MagnetNear = false;};
          if (avValue>MagnetMax) {MagnetNear = true;};
          if (MagnetNear != MagnetNearOld) {
            if (destination > 0){pos_x = pos_x + stepp;}
            else {pos_x = pos_x - stepp;};
            MagnetNearOld = MagnetNear;
            if (destination > 0) {
              if ((pos_x + stepp/2) >= destination) {
                digitalWrite(Motor1_Speed, LOW);
                break;};
            } else {
              if ((pos_x - stepp/2) <= destination) {
                digitalWrite(Motor1_Speed, LOW);
                break;};
            };
          };
          time2 = millis();
        }  while((5000>(time2-time))); //shut down on timeout, if hall sensor is broken
        digitalWrite(Motor1_Speed, LOW);
        //last_pos_x = pos_x;
        Serial.print("Time spent [ms]:");
        Serial.println((time2-time));
        Serial.print("Distance runned [mm]:");
        Serial.println(pos_x);
      };
    }
    И вот в нём-то уже и ничего не работает. Точнее, если в порт отправлять число односимвольное положительное, то всё отлично. Если отрицательное, то оно всё равно выдаёт "I received:" число по модулю и, соответственно, мотор едет не туда. Если отправлять 2 и более значные числа, то они не склеиваются в исходное число, а разбиваются на знаки и выполяются последовательно мотором. Мне непонятно - почему один и тот же код сперва работает в 1м скетче, а потом не работает во 2м. Вроде остальной код с этим куском не взаимодействует.

    И второй вопрос - методом тыка, при добавлении глубокомысленного printLn-а во второй код
    Код (Text):
    //Serial.println("YAY!"); <--------------- Чудо-Камент.
    контроллер стал различать знак отправляемого в порт числа. Каким образом ничего не меняющее сообщение в порт может так всё менять?

    Очевидно, я не до конца понимаю, как оно общается с портом, разъясните, пожалуйста...
    И да, сорри за быдло-код)
     
  2. Unixon

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

    У вас протокол общения не допускает, что Serial.available() может вернуть false в середине сообщения, но изза особенностей работы библиотеки и оборудования, такая ситуация имеет место. Безотносительно причины пропусков протокол ненадежен.

    В нормальных языках программирования инструкции отделяются каким-либо служебным символом, а в коммуникационных протоколах еще и сопровождаются контрольным кодом. Стоит воспользоваться этим опытом.

    Пусть у вас цикл Serial.available() склеивает инструкцию до тех пор, пока не встретит некоторый служебный символ, например ";" или перевод строки. Не опирайтесь на непрерывный прием.