if внутри if

zkxFTF
Offline
Зарегистрирован: 10.12.2018

Доброго времени суток.

Это мои первое знакомство с ардуиной, возник вопрос после пробы создания первой программки... Хотелось засунуть if внутри if, но почему-то не отрабатывает так как мне хотелось. Буду очень признателен пинку в нужную сторону, гугол не дал нужного ответа. 

 

int ledPin = 8; // Порт подключения + светодиода через резистор
int sh = 0; // Буфер хранения получаемого числа через последовательный порт

void setup(){
    pinMode(ledPin, OUTPUT); // Устанавливаю переменной с пином режим работы - выход.
    Serial.begin(9600); //Устанавливаю последовательное соединение.
    Serial.println("Режим отладки активен."); //Вывод сообщения, что все удачно отработало.
  }

void loop(){
    if (Serial.available() > 0){ // Если есть данные принимаем и
      sh = Serial.read(); // записываем данные в переменную.
      if (sh == 1){ // Если число равно 1, то 
        digitalWrite(ledPin, HIGH); // включить светодиод и
        Serial.println("Светодиод включен."); //вывести строку.
        }
      else { // Иначе
        digitalWrite(ledPin, LOW); // выключить светодиод и
        Serial.println("Светодиод выключен."); // вывести строку и
        Serial.println("Для включения, введите число: 1"); //вывести строку
        }
      }    
  }

Вывод консоли при вводе любого числа 1 раз: 

Режим отладки активен.
Светодиод выключен.
Для включения, введите число: 1
Светодиод выключен.
Для включения, введите число: 1

 

Вопрос 1: Почему при вводе единицы не включает светодиод, а отрабатывает как любое число кроме 1 ?

Вопрос 2: Почему выводит два сообщения на экран?

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Попробуйте
if (sh == "1"){ // Если число равно 1

zkxFTF
Offline
Зарегистрирован: 10.12.2018

trembo пишет:
Попробуйте if (sh == "1"){ // Если число равно 1

Ничего не поменялось

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

а вот так?
 

int ledPin = 13; // Порт подключения + светодиода через резистор
int sh = 0; // Буфер хранения получаемого числа через последовательный порт

void setup(){
    pinMode(ledPin, OUTPUT); // Устанавливаю переменной с пином режим работы - выход.
    Serial.begin(9600); //Устанавливаю последовательное соединение.
    Serial.println("Режим отладки активен."); //Вывод сообщения, что все удачно отработало.
  }

void loop(){
    if (Serial.available()){ // Если есть данные принимаем и
      sh = Serial.read(); // записываем данные в переменную.
      if (sh == 49){ // Если число равно 1, то 
        digitalWrite(ledPin, HIGH); // включить светодиод и
        Serial.println("Светодиод включен."); //вывести строку.
        delay(2000);
        }
      else { // Иначе
        digitalWrite(ledPin, LOW); // выключить светодиод и
        Serial.println("Светодиод выключен."); // вывести строку и
        Serial.println("Для включения, введите число: 1"); //вывести строку
        }
      }    
  }

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

zkxFTF пишет:

trembo пишет:
Попробуйте if (sh == "1"){ // Если число равно 1

Ничего не поменялось


Сорри, ошибся с кавычками.....
if (sh == '1')

zkxFTF
Offline
Зарегистрирован: 10.12.2018

ua6em пишет:

а вот так?

Просто задержка добавлена? Если да, то ничего не поменялось.

zkxFTF
Offline
Зарегистрирован: 10.12.2018

trembo пишет:
'1'

Вот с одинарными сработало, но почему-то сразу же отработал и else, хотя не должен был

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

zkxFTF пишет:

ua6em пишет:

а вот так?

Просто задержка добавлена? Если да, то ничего не поменялось.

а проверить? и будете удивлены

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Потому что АСКИ код единицы равен 49
как правильно указал ua6em
А вы пытались сравнивать с кодом 1.
Я совсем не уверен что вы сможете с клавиатуры набрать символ с кодом 1, или 2, или 3 .......

zkxFTF
Offline
Зарегистрирован: 10.12.2018

ua6em пишет:

Все понял.

zkxFTF
Offline
Зарегистрирован: 10.12.2018
int ledPin = 8; // Порт подключения + светодиода через резистор
int sh = 0; // Буфер хранения получаемого числа через последовательный порт

void setup(){
    pinMode(ledPin, OUTPUT); // Устанавливаю переменной с пином режим работы - выход.
    Serial.begin(9600); //Устанавливаю последовательное соединение.
    Serial.println("Режим отладки активен."); //Вывод сообщения, что все удачно отработало.
  }

void loop(){
    if (Serial.available() > 0){ // Если есть данные принимаем и
      sh = Serial.parseInt(); // записываем данные в переменную.
      if (sh == 1){ // Если число равно 1, то 
        digitalWrite(ledPin, HIGH); // включить светодиод и
        Serial.println("Светодиод включен."); //вывести строку.
        return 1;
        }
      else { // Иначе
        digitalWrite(ledPin, LOW); // выключить светодиод и
        Serial.println("Светодиод выключен."); // вывести строку и
        Serial.println("Для включения, введите число: 1"); //вывести строку
        }
      }    
  }

А почему тогда  после отработки, переходит и выполняет else ??

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

trembo пишет:
Потому что АСКИ код единицы равен 49 как правильно указал ua6em А вы пытались сравнивать с кодом 1. Я совсем не уверен что вы сможете с клавиатуры набрать символ с кодом 1, или 2, или 3 .......

не каждая консоль поддерживает ввод управляющих символов, вводятся через ALT+ код символа

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

zkxFTF пишет:

ua6em пишет:

Все понял.

Если бы Вы поняли, стало понятно зачем я ввел задержку 2 секунды, то-есть, при передаче кода числа на самом деле передается более одного символа, так? И что за второй символ, на который у вас и отработал else?

zkxFTF
Offline
Зарегистрирован: 10.12.2018

ua6em пишет:

Если бы Вы поняли, стало понятно зачем я ввел задержку 2 секунды, то-есть, при передаче кода числа на самом деле передается более одного символа, так? И что за второй символ, на который у вас и отработал else?

 

Даже введя задержку в 2 секунды, светодиод зажигается, ждет две секунды, и срабатывает условие else.

 

int ledPin = 8; // Порт подключения + светодиода через резистор
int sh = 0; // Буфер хранения получаемого числа через последовательный порт

void setup(){
    pinMode(ledPin, OUTPUT); // Устанавливаю переменной с пином режим работы - выход.
    Serial.begin(9600); //Устанавливаю последовательное соединение.
    Serial.println("Режим отладки активен."); //Вывод сообщения, что все удачно отработало.
  }

void loop(){
    if (Serial.available() > 0){ // Если есть данные принимаем и
      sh = Serial.parseInt(); // записываем данные в переменную.
      if (sh == 1){ // Если число равно 1, то 
        digitalWrite(ledPin, HIGH); // включить светодиод и
        Serial.println("Светодиод включен."); //вывести строку.
        delay(2000);
        }
      else { // Иначе
        digitalWrite(ledPin, LOW); // выключить светодиод и
        Serial.println("Светодиод выключен."); // вывести строку и
        Serial.println("Для включения, введите число: 1"); //вывести строку
        }
      }    
  }

 

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

и правильно срабатывает я Вам замечу )))

zkxFTF
Offline
Зарегистрирован: 10.12.2018

ua6em пишет:

и правильно срабатывает я Вам замечу )))

Но после выполнения условия не должно ли выходить из проверки как в цикле?

sadman41
Offline
Зарегистрирован: 19.10.2016

Никто никому ничего не должен. МК работает, как написано в программе и в соответствии с прилетающими данными. Если уверены в коде, смотрите что из Serial вываливается.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

sh = Serial.read();

if (sh==0x0A || sh==0x0D) return;

sh -= '0';

if (sh == 1) ......

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Исправлять нужно то, что неисправно. А то, что исправно, исправлять не следует.

То, что Вы описываете, является нормальным поведением. Как Вы его собираетесь "исправлять"?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

zkxFTF пишет:

trembo пишет:
Попробуйте if (sh == "1"){ // Если число равно 1

Ничего не поменялось

Он опечатался, надо не "1", а '1'

zkxFTF
Offline
Зарегистрирован: 10.12.2018

DetSimen пишет:

sh = Serial.read();

if (sh==0x0A || sh==0x0D) return;

sh -= '0';

if (sh == 1) ......

Сложно... И  не понятно....

 

andriano пишет:

Исправлять нужно то, что неисправно. А то, что исправно, исправлять не следует.

То, что Вы описываете, является нормальным поведением. Как Вы его собираетесь "исправлять"?

Нет, я про отработку, почему когда стоит "NL(новая строка)" он срабатывает еще и на else? По коду написано, если 1 выполни и выйди из проверки, если не 1, то выведи else. 

sadman41
Offline
Зарегистрирован: 19.10.2016

... куда "выйди из проверки"? Вы понимаете, что последующие 'CRLF' тоже попадают в проверку после '1'? Что с ними должен делать МК - выкидывать, руководствуясь уловленными вибрациями мыслей в вашей голове?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

zkxFTF пишет:

Нет, я про отработку, почему когда стоит "NL(новая строка)" он срабатывает еще и на else? По коду написано, если 1 выполни и выйди из проверки, если не 1, то выведи else. 

Потому, что на первый символ срабатывает "if", а на второй - "else".

zkxFTF
Offline
Зарегистрирован: 10.12.2018

sadman41 пишет:

... куда "выйди из проверки"? Вы понимаете, что последующие 'CRLF' тоже попадают в проверку после '1'? Что с ними должен делать МК - выкидывать, руководствуясь уловленными вибрациями мыслей в вашей голове?

 

int ledPin = 8; // Порт подключения + светодиода через резистор
int sh = 0; // Буфер хранения получаемого числа через последовательный порт

void setup(){
    pinMode(ledPin, OUTPUT); // Устанавливаю переменной с пином режим работы - выход.
    Serial.begin(9600); //Устанавливаю последовательное соединение.
    Serial.println("Режим отладки активен."); //Вывод сообщения, что все удачно отработало.
  }

void loop(){
    if (Serial.available()){ // Если есть данные принимаем и
      sh = Serial.parseInt(); // записываем в переменную.
      switch(sh){ //Если переменная 
        case 1: //равна 1, то
          digitalWrite(ledPin, HIGH); // включить светодиод и
          Serial.println("Светодиод включен."); //вывести строку.
          break; // Не проверять дальше
         case 0: //равна 0, то
          digitalWrite(ledPin, LOW); // выключить светодиод и
          Serial.println("Светодиод выключен."); // вывести строку.    
          break; //Не проверять дальше.      
         default: //Если условия не выполнены, то
          Serial.println(sh);
          break;
        }  
    } 
  }

Может так Вы меня поймете, я ему объяснил, что если условие выполнил, то выйди. Не ходи дальше. Мне важно выполнение моего условия, CR LN я вообще не представляю что такое, но они мешают выполнению написанному мной коду.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Даже если ты не представляешь чотакое CR и LF, то они все равно считываюца из сериала, и подходят под определение не 0 и не 1. 

zkxFTF
Offline
Зарегистрирован: 10.12.2018

andriano пишет:

Потому, что на первый символ срабатывает "if", а на второй - "else".

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

zkxFTF
Offline
Зарегистрирован: 10.12.2018

DetSimen пишет:

Даже если ты не представляешь чотакое CR и LF, то они все равно считываюца из сериала, и подходят под определение не 0 и не 1. 

Вот! Теперь, я надеюсь, понял написанный Вами код выше! Это исключение этих CR и LF ? Хотя... Если запустить CR и LF (без Вашего кода) , то все равно если отправить 1, то сработает включение светодиода, потом сразу сработает отключение светодиода. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ну, примерно, да.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ты мой код вставь ВМЕСТО sh=Serial.parseInt()

Densl
Offline
Зарегистрирован: 28.11.2018

Попробую доступным образом написать. Там когда в терминале вводится число 1, обычно автоматически добавляется непечатаемый символ конца строки. А т.к. чтение буфера порта идет в цикле, то сначала читается первый пришедший символ(видимый) а потом на следующей итерации второй(невидимый) до тех пор, пока не опустошится буфер порта.

zkxFTF
Offline
Зарегистрирован: 10.12.2018
int ledPin = 8; // Порт подключения + светодиода через резистор
int sh = 0; // Буфер хранения получаемого числа через последовательный порт

void setup(){
    pinMode(ledPin, OUTPUT); // Устанавливаю переменной с пином режим работы - выход.
    Serial.begin(9600); //Устанавливаю последовательное соединение.
    Serial.println("Режим отладки активен."); //Вывод сообщения, что все удачно отработало.
  }

void loop(){
    if (Serial.available()){ // Если есть данные принимаем и
      sh = Serial.read(); // 
      if (sh==0x0A || sh==0x0D) return;
      sh -= '0';
      switch(sh){ //Если переменная
        case 1: //равна 1, то
          digitalWrite(ledPin, HIGH); // включить светодиод и
          Serial.println("Светодиод включен."); //вывести строку.
          break; // Не проверять дальше
         case 0: //равна 0, то
          digitalWrite(ledPin, LOW); // выключить светодиод и
          Serial.println("Светодиод выключен."); // вывести строку.    
          break; //Не проверять дальше.      
         default: //Если условия не выполнены, то
          Serial.print("Вы ввели: ");
          Serial.println(sh);
          Serial.println("Для включения светодиода введите: 1 ");
          Serial.println("Для выключения светодиода введите 2 ");
          break;
        }  
    } 
  }

 

 

DetSimen пишет:

Ты мой код вставь ВМЕСТО sh=Serial.parseInt()

Спасибо. Теперь точно разобрался как это сработало. Где можно c этим более подробнее ознакомиться не подскажете? 

 

Densl пишет:
Попробую доступным образом написать. Там когда в терминале вводится число 1, обычно автоматически добавляется непечатаемый символ конца строки. А т.к. чтение буфера порта идет в цикле, то сначала читается первый пришедший символ(видимый) а потом на следующей итерации второй(невидимый) до тех пор, пока не опустошится буфер порта.

Спасибо, понял.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Пропал дом! :(

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Эта, если ты введешь 2, светлодиод не выключица, такого case нету, значить

zkxFTF
Offline
Зарегистрирован: 10.12.2018

ЕвгенийП пишет:

Пропал дом! :(

Прошу прощения, не понял Вас :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

zkxFTF пишет:

ЕвгенийП пишет:

Пропал дом! :(

Прошу прощения, не понял Вас :)

http://rushist.com/index.php/rus-literature/3084-bulgakov-sobache-serdts...

zkxFTF
Offline
Зарегистрирован: 10.12.2018

DetSimen пишет:

Эта, если ты введешь 2, светлодиод не выключица, такого case нету, значить

Serial.read работает только с 1 значным числом :)  А если мне нужно включить светодиод если число == 10, он влючится и выключится

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Это не я придумал: 

28          Serial.println("Для выключения светодиода введите 2 ");

zkxFTF
Offline
Зарегистрирован: 10.12.2018

DetSimen пишет:

Это не я придумал: 

28          Serial.println("Для выключения светодиода введите 2 ");

Но все же, если включаться будет по числу 10. Нам без parseInt не обойтись? А как тогда обойти этот перевод строки который шлёт ноль в конце? Может у нас будут заняты все 11 чисел.  И ноль к ним относится.

sadman41
Offline
Зарегистрирован: 19.10.2016

Прежде чем спрашивать "как", подумайте - какой цели вы хотите добиться. Вполне вероятно, что никаких извращений и не понадобится.

b707
Offline
Зарегистрирован: 26.05.2017

zkxFTF пишет:

Но все же, если включаться будет по числу 10. Нам без parseInt не обойтись? А как тогда обойти этот перевод строки который шлёт ноль в конце? Может у нас будут заняты все 11 чисел.  И ноль к ним относится.

прежде чем писать дальше. разберитесь. что такое строки и что такое CR LF. Никакого "ноля в конце" там нет.

А "как обойти перевод строки" - DedSimen вам даже готовый код дал. что в нем непонятно?

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

Пропал дом! :(

Евгений Петрович!
О каком доме речь?
О том, что из облицовочного кирпича с кладкой в 2,5 кирпича?
С ним должно быть всё в порядке, тепло, спутники GPS обязан ловить знамо! )))
 

zkxFTF
Offline
Зарегистрирован: 10.12.2018

sadman41 пишет:

Прежде чем спрашивать "как", подумайте - какой цели вы хотите добиться. Вполне вероятно, что никаких извращений и не понадобится.

Хорошо, к примеру, у меня есть 12 светодиодов, которые я хочу запускать через консоль введя его номер. А нулём выключать их все. Но и выключать каждый из них введя его номер. Так понадобятся извращения же верно?

 

b707 пишет:

прежде чем писать дальше. разберитесь. что такое строки и что такое CR LF. Никакого "ноля в конце" там нет.

А "как обойти перевод строки" - DedSimen вам даже готовый код дал. что в нем непонятно?

Я уже понял, что такое строки, и что такое возврат каретки. Есть же видео https://www.youtube.com/watch?v=oxN1C2QQUIE&feature=youtu.be . У mac'ов, Unix - один LF. Форточки - CR+LF. Кстати, если вывести  число которое там появилось в конце, им будет ноль. Потому я и сказал про ноль. Кстати. С парсом не работает тот обход.

Так же, как сказал товарищ

wdrakula пишет:

3. Как избавиться - самое простое костыль:

вместо:

 msg = msg + c;   //соберем команду от ардуины

пишем:

 if (c !=10) msg = msg + c;   //соберем команду от ардуины, кроме LF, можешь еще что-то добавить в проверку. например isgraph(c) или !isctrl(c)

другой вариант, если ты пользуешься сериал-монитором из ИДЕ, то внизу справа поставть "Конец строки" только CR.

 

напрашивается вопрос: Неужели все настолько непродумано, что приходится пилить костыли? Нет, мне-то не сложно... Но место под них выделяется же... Видите ли, я работаю на станках с ЧПУ, и частенько, для упрощения действия использую макропеременные (переменные), и при работе на очередном станке и написании на нем программы, был сильно разачарован в том, что железо его не способно отрабатывать не то, что тысячные и сотые части, но и десятичные числа тоже, все выходы из условий легко теряются и программа начинает выполнять условие до момента когда концевики сработают или до момента, когда кончится вычислительная способность. Костыли конечно же спасают ситуацию, но это уже ответвление мысли от самой темы, трата времени, места, читабельности.

 

ua6em пишет:

Евгений Петрович!
О каком доме речь?
О том, что из облицовочного кирпича с кладкой в 2,5 кирпича?
С ним должно быть всё в порядке, тепло, спутники GPS обязан ловить знамо! )))
 

боюсь, его на поэзию пробило :)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Да, люди хотят паэзии-на.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

2 ТС, ты можешь не читать символ из сериала, а сначала посмотреть на него Serial.peek(). Если это цыфра, то вызывать Serial.parseInt(), а если нет - считывать и пропускать ничего не делая. Код усложнится ненамного. 

И, да, хватит обучаца по видео из ютуба, почитай наконец Библию от Кернигана.

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

DetSimen пишет:

Да, люди хотят паэзии-на.

Коль праведно то, чего ОН вожделеет, то то, чего я вожделею - грешно?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

А я знаю?

sadman41
Offline
Зарегистрирован: 19.10.2016

zkxFTF пишет:

sadman41 пишет:

Прежде чем спрашивать "как", подумайте - какой цели вы хотите добиться. Вполне вероятно, что никаких извращений и не понадобится.

Хорошо, к примеру, у меня есть 12 светодиодов, которые я хочу запускать через консоль введя его номер. А нулём выключать их все. Но и выключать каждый из них введя его номер. Так понадобятся извращения же верно?

Вполне можно обойтись одним байтом (символом). 'A'..'Z' - включают, 'a'..'z' - выключают. '1' на общее включение, '0' - общее выключение. '2' - инверсия, '3' - включение сирены. И т.п.

Делаете Serial.read(), результат гоните... ну, для начала в switch(). Потом соптимизируете, когда общий скелет увидите.

 

zkxFTF
Offline
Зарегистрирован: 10.12.2018

DetSimen пишет:

2 ТС, ты можешь не читать символ из сериала, а сначала посмотреть на него Serial.peek(). Если это цыфра, то вызывать Serial.parseInt(), а если нет - считывать и пропускать ничего не делая. Код усложнится ненамного. 

И, да, хватит обучаца по видео из ютуба, почитай наконец Библию от Кернигана.

А я на хабаре смотрю. Мне нужна основа, я посчитал, что хабар достоин этой учести... Но не успев начать, словил кучу варнов :( Немогли бы Вы, описать пример использования .peek()? Или поделиться сцылкой, на которой я смогу все разобрать? Пока Гоголь'ю и тщетно...

zkxFTF
Offline
Зарегистрирован: 10.12.2018

sadman41 пишет:

Вполне можно обойтись одним байтом (символом). 'A'..'Z' - включают, 'a'..'z' - выключают. '1' на общее включение, '0' - общее выключение. '2' - инверсия, '3' - включение сирены. И т.п.

Делаете Serial.read(), результат гоните... ну, для начала в switch(). Потом соптимизируете, когда общий скелет увидите.

 

Может я вас не понял? Вы хотите Буквой включать или выключать? К примеру я сделаю панель в 12 численных кнопок. И мне нужно использовать именно эти кнопки, и дабы не путать себя в дальнейшем (а ведь самому дьяволу только извезстно, во что может препратиться код) я хочу... Нет, скажем, что все остальные символы уже используются. Даже "ZdKklJ" (прост о бурда с кнопок), ну нет больше никаких вариантов, и нужно только эти использовать.

sadman41
Offline
Зарегистрирован: 19.10.2016

Вы озвучили задачу, я вам дал простое решение. Если у Вас что-то осталось "за кадром" - это, полагаю, не моя вина. 

К тому же я не особо понимаю, как Вы через "панель в 12 численных кнопок" собрались передавать что-то в Serial Port. 

Код у вас рано или поздно превратится в адскую кашу - что с "ZdKklJ", что с парсером полученных значений. Так что не надейтесь на волшебный скетч в три понятных строчки, который делает всё.

b707
Offline
Зарегистрирован: 26.05.2017

zkxFTF пишет:

Может я вас не понял? Вы хотите Буквой включать или выключать? К примеру я сделаю панель в 12 численных кнопок.

И что в этом такого страшного?  Включение буквами тебе привели только как пример, который легко обьяснить (хотя ты и его не понял :) Если же делать по взрослому. то нужно использовать последовательности из нескольких символов. Всего два байта подряд УЖЕ дают 65 с половиной тысяч различных комбинаций.