До безобразия простой код не работает

Slavin
Offline
Зарегистрирован: 04.02.2013

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

То ли лыжи не едут....

Короче проблема в следующем... Отлаживаю небольшие фрагменты своего диплома и наткнулся на проблему.

В рамках отладки нужно чтоб ардуина выплюнула в сериал команду только один раз, для того поставил счетчик i=0

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

Код

int i=0;

void setup(){

Serial.begin(9600);

}
void loop(){
if (i<1) Serial.print("OFF");
//delay(10);
i=i++
}

Проблема:

По сути тут задержка нафиг не нужна и потому я ее решил закаментить и как только я зашил код в ардуино у меня пошла постоянная передача моей команды в сериал.

Вместо OFF поставил i и обнаружил что и в начале выполнения программы присваивается значение -32768

далее в цикле i инкрементируется и получаемое число естественно <1

Но что странно если убрать камент с задержки все работает нормально

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

if(i==0)
{
Serial...
i = 1;
}

Artur1985
Offline
Зарегистрирован: 19.02.2013

День добрый.

int i=0;

void setup(){

Serial.begin(9600);

}
void loop(){
  if (i<1) {Serial.print("OFF");}
  if (i<1){i=i++;}
  
}

Вот так наверно будет правильнее.
Да внимательнее в вашем коде ошибка
i=i++
Должно быть так 
i=i++;

UPD. kisoft меня опередил:)
И у него более правильно, я просто исправил ваш код.
 

Slavin
Offline
Зарегистрирован: 04.02.2013

эм... как это я сам не додумался до такого решения?)

Самое забавное работает)))

СПС. Видимо надо чаще отдыхать)

Slavin
Offline
Зарегистрирован: 04.02.2013

эм... как это я сам не додумался до такого решения?)

Самое забавное работает)))

СПС. Видимо надо чаще отдыхать)

Artur1985
Offline
Зарегистрирован: 19.02.2013

Бывает, сам ступил.
И предложил, аж 2 раза проверять и оставил ваш i=i++;

Slavin
Offline
Зарегистрирован: 04.02.2013

Давно не программил и алгоритмия хромать начала)

Все равно не понятно почему с задержкой все работало?) Особенности Ардуино?)

Кстати даже если написать delay(0) работало... а убираешь хер)

Artur1985
Offline
Зарегистрирован: 19.02.2013

Тут не знаю (может из знающих, кто-то пояснит), опыта с ардуиной пока не много.
Но уже делаю первый станок.

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

Всё объяснимо.

Конструкция i = i++ фактически это i = i + 1; т.е. счетчик в цикле постоянно увеличивается. При наличии delay он увеличивается медленней (!) и только. Кроме того, при отрицательных i, производится вывод в Сериал, что еще больше замедляет работу программы. Короче, i будет меньшую часть времени положительным, а большую часть (дольше за счет времени вывода в сериал) отрицательным. Т.е. если прогу оставить, то она тысяч 16 выведет в сериал OFF, затем чуть помолчит (недолго) и снова 16 тысяч в сериал. Примерно так.

UPD: облажался, i = i++; это i++;, а не i = i + 2;

mixail844
Offline
Зарегистрирован: 30.04.2012

а зачем вообще изначально прописывать i=i++; если можно написать просто i++; <=> i=i+1;

по мне так i=i++; это тавтология какаято "масло маслянное"

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Slavin, ваш i  постоянно увеличивается на 1. С максимально возможной скоростью. Когда i достигает значения 32 767, прибавленая к нему 1 сделает значение i - 32768.

Т.е. половину времени работы i имеет значение выше 0 а оставшуюся половину - ниже.

Вот почитайте. http://arduino.ru/Reference/Arithmetic.

Как правильно подметил kisoft, ваша задержка лишь притормаживает данный процесс.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Задержка в 10мс приведет к тому что ваша i будет иметь положительное значение примерно 54 минуты, потом столько же она будет отрицательной.

step962
Offline
Зарегистрирован: 23.05.2011

nestandart пишет:

Т.е. половину времени работы i имеет значение выше 0 а оставшуюся половину - ниже.

Эх, если бы...

При счете от 0 до 32767 программа подобна пуле - ничто не сдерживает ее работу.

Но как только значение счетчика перепрыгнет с 32767 на -32768, начинается вывод в UART и скорость выполнения падает примерно в тысячу раз - вместо 1-2 мксек (5-20 тактов) на каждое прохождение цикла будет требоваться около 3 мсек (при работе UART на скорости 9600 один символ пропихивается примерно за 1 миллисекунду).

А всего-то и надо было вместо 

void loop(){
  if (i<1) Serial.print("OFF");
  i=i++
}

написать (уже, наверное, надцатый вариант исправления)

void loop(){
  if (i<1) { // <- начинаем блок
    Serial.print("OFF");
    i=i++ // ужос-ужос, лучше просто i=i+1;
  } // <- и завершаем его
}

или

void loop(){
  if (i==0) // выполняем вывод только один раз из 65536
    Serial.print("OFF");
  i=i+1;  // если уж нам настоятельно необходимо крутить счетчик для других дел
}
mr.il
Offline
Зарегистрирован: 05.01.2013

Всем привет!

А почему бы просто в секции setup не вписать требуемый код и не заморачиваться с ифами и переменными?

Artur1985
Offline
Зарегистрирован: 19.02.2013

Спасибо, kisoft, nestandart за подробное разъяснение.

step962
Offline
Зарегистрирован: 23.05.2011

mr.il пишет:

Всем привет!

А почему бы просто в секции setup не вписать требуемый код и не заморачиваться с ифами и переменными?

Все ниженаписанное исключительно мое IMHO:

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

Во-вторых, топик-стартера не вопрос исполнения этого кода волновал, а - как он полагал - бага в компиляторе. Однако, чуда в очередной раз не произошло.

mr.il
Offline
Зарегистрирован: 05.01.2013

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

byte isFirst = 1;

void setup(){
  Serial.begin(9600);
}
void loop(){
  if (isFirst == 1) {Serial.print("OFF"); isFirst = 0;}
}

и ни каких ++

ourlive
Offline
Зарегистрирован: 26.05.2012

Начал тут читать и меня переклинило. i=i++; это же i=i; ?

Счётчик увеличит значение, но присвоит старое. А i=++i; идентична i++; ?

Сам такими конструкциями не пользуюсь, ибо накосячить проще простого, но всё же?

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

i = i++;

можно разложить по полочкам как:

i = i;
i++;

т.е. i = i++; равносильно i++;

i = ++i;

по полочкам:

++i;
i = i;

т.е. i = ++i; равносильно i++;

Такие конструкции лучше не использовать, чтобы не было проблем ни у автора, ни у того, кто будет этот код читать.

Компилятору же до таких конструкций дела нет, они синтаксически корректны.

 

mr.il
Offline
Зарегистрирован: 05.01.2013

ourlive пишет:

Начал тут читать и меня переклинило. i=i++; это же i=i; ?

Счётчик увеличит значение, но присвоит старое. А i=++i; идентична i++; ?

Сам такими конструкциями не пользуюсь, ибо накосячить проще простого, но всё же?

в твоей реализации всё пройдет так как ты задумывал, хотя само написаниё и коряво (извини за выражение)

1. произойдет присвоение i=i

2. произойдет инкримент i++

В итоге i увеличит значение на 1 но так писать нельзя, так как в другом случае ты можешь сильно пролететь.

Например

...
j = 5; i = 5;
...
if (j <> i++) {
}
...

т.е. в данный проход условие не выполнится, т.к. сначала произойдет сравнение, а потом инкримент.

ourlive
Offline
Зарегистрирован: 26.05.2012

добавьте такой развёрнутый пример с порядком присвоения значений в соотвествующий раздел справки (т.е. достаточно имеющиеся комментатии скорректировать)

Slavin
Offline
Зарегистрирован: 04.02.2013

nestandart пишет:

Slavin, ваш i  постоянно увеличивается на 1. С максимально возможной скоростью. Когда i достигает значения 32 767, прибавленая к нему 1 сделает значение i - 32768.

Эта мысль меня к вечеру посещала что я просто не вижу положительных значений при условии что отрицательное выводится в сериал

Свем огромный человеческий сенкс