Странное поведение ардуино.

DarkLor
Offline
Зарегистрирован: 06.12.2012

Помогите пожалуйста, а то что-то я совсем запутался. Берем простейший код: 

String str = "";
boolean stringComplete = false;

void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop() {
int cur;  
  
  if (str == "0" ) {
    digitalWrite(13, LOW);
    cur=0;
  }
  if (str == "1" ) {
    digitalWrite(13, HIGH);
    cur=1;
  }
  if (str == "2" ) {
    Serial.print(cur);
  }
  str = "";
  stringComplete = false;
}

void serialEvent() {
  while (Serial.available()) {
    char in=(char)Serial.read();
    str += in;
    if (in == '\n') {
      Serial.print(in);
      stringComplete = true;
    }
  }
}

Если в порт записать 1 то LED загорается, если 0 то гаснет. А вот если кинуть 2 то на выходе всегда имеем 0. Более того если записать 22 то на выходе получим 00, если 222 то 000 и т.д. Если писать в порт 111, то LED зажигается, и т.д. Я почему-то по наивности считал что сравнение идет по полной строке а не по выборочному символу. А самое главное непонятно почему при записи 2 всегда имеем на выходе 0. Может я чего-то недопонимаю?

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

DarkLor пишет:

А самое главное непонятно почему при записи 2 всегда имеем на выходе 0. Может я чего-то недопонимаю?

Рискну предположить: потому, что "два" в машинных кодах - это 10, учитывая, что состояние порта хранится в одном знаке, получаем последнюю цифру - 0. Чтобы не вставать на такие грабли - как раз и придуманы типы переменных int, float, char и т.д. В Вашем случае - программа должна делать обработку на вводе данных с клавиатуры и отбрасывать бессмысленные значения с соответствующей диагностикой. Ну, типа, помигать 13-м диодом часто-часто в случае ошибки. :)

DarkLor
Offline
Зарегистрирован: 06.12.2012

К сожалению Ваше предположение не катит. Если поменять местами if с 0 и if с 1 то на выходе всегда будет 1. Да и причем-тут машинные коды, я же сравниваю не их а цифру 2.

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

DarkLor пишет:

К сожалению Ваше предположение не катит. Если поменять местами if с 0 и if с 1 то на выходе всегда будет 1. Да и причем-тут машинные коды, я же сравниваю не их а цифру 2.

Кто сказал "цифру"? У Вас переменная - типа "строка" и сравниваете Вы, скорее всего, коды знаков. Сделайте переменную типа unsigned int - будут Вам цифры...

DarkLor
Offline
Зарегистрирован: 06.12.2012

Делал. Делал и переменную типа char[] и срвнивал char[0] == '2' и переменную типа int и сравнивал int ==2 эффект один и тот-же, всегда возвращается то значение переменной cur которая стоит в первом if.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Это не странное поведение ардуино, это странная программа.

stringComplete нигде не используется.

В 21 строке лучше написать Serial.println иначе будут цифры лепиться друг к другу.

Вообще, если хотите, чтобы программа срабатывала только по Enter, вставьте весь loop в такую конструкцию:

if( stringComplete )
{
...
}

тогда str к Вам приедет всей строкой, что Вы передали в мониторе. Однако помните, что если Вы введете 22, то программа работать не будет (так как Вы хотите).

int cur - лучше инициализировать, либо сделать глобальной переменной, в противном случае она у Вас при каждом вызове loop имеет неопределенное значение (зависит от компилятора).

И мелочи, если пишите несколько if, делайте так:

if( условие 1)
{
}
else if( условие2 )
{
}
else
{
}

Во всяком случае в этом исходнике так было бы лучше. Потому что если там "0", то два оставшихся if не сработают.

Впрочем, не настаиваю, пишите как Вам нравится :) Работать будет, но не эффективно.

Удачи!

 

 

DarkLor
Offline
Зарегистрирован: 06.12.2012

Спасибо за ответ, наконец-то я разобрался. Виноват несколько запутанный пример на SerialEvent. Я почему-то решил что stringComplete это какая-то служебная переменная, ну и плюс подзапутался с инициализацией переменных. Все-таки Arduino несколько отличается от C к которому я привык.