Почему не идет приращение переменной?

Andreas
Offline
Зарегистрирован: 10.11.2021

Добрый день

Недавно начал играть с ардуино, накидал небольшой код, но есть вопрос в котором не могу разобраться.

Не идёт приращение переменной.

 

#define CLK 7
#define DT 6
#define SW 4

#include "GyverEncoder.h"
#include <OLED_I2C.h>
#include <microDS3231.h>

Encoder enc1(CLK, DT, SW);  // для работы c кнопкой
OLED  myOLED(SDA, SCL);
MicroDS3231 rtc;

extern uint8_t MediumNumbers[];
byte segment;
byte sec;
char time[8];
char mod_time[8];
unsigned long timing_loop;
unsigned long timing_blink;

void setup()
{
  enc1.setType(TYPE2);
  myOLED.begin(SSD1306_128X32);
  myOLED.setFont(MediumNumbers);
  Serial.begin(9600);
  rtc.begin();
}

void loop()
{ 
  enc1.tick();
  if (segment > 0) {    
       if (enc1.isClick())
      segment++;
    if (segment > 3)
      segment = 1;
    
    if (sec > 100) {
      segment = 0;
      sec = 0;
    }
    sec++;
  }
  else {
    if (enc1.isClick())
      segment = 1;

  }
  printTime();
  Serial.println(sec);
  Serial.println(segment);
  delay(100);
}



void change_time() {


}

void printTime() {
  rtc.getTimeChar(time);   
  Serial.println(time);
}

По какой то причине sec++ не сохраняет значение при проходе loop, он всегда сбрасывается на 0.

Если sec++ вставить в самое начало цикла loop, тогда перестает запоминаться segment, он сбрасывается на 0.

Видимо где то есть глупая ошибка в логике, но не могу понять где

 

void loop()
{ 
  sec++;
  enc1.tick();
  if (segment > 0) {    
       if (enc1.isClick())
      segment++;
    if (segment > 3)
      segment = 1;
    
    if (sec > 100) {
      segment = 0;
      sec = 0;
    }
   }
  else {
    if (enc1.isClick())
      segment = 1;

  }
  printTime();
  Serial.println(sec);
  Serial.println(segment);
  delay(100);
}

 

Dumper
Offline
Зарегистрирован: 21.09.2020

У меня было похожее. Помогло sec=sec+1. Колхоз, но времени разбираться не было. Работает и иже с ним.
Возможно, у вас другой случай

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

А что, если оставить в лупе только ++, println и delay - тоже постоянно нулю равно значение?

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

У вас sec увеличивается только при условии segment > 0.Сам segment увеличивается тоже только при условии segment > 0. А в каком месте segment становится больше нуля?  Ну и что вас удивляет? ))

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

v258 пишет:

А в каком месте segment становится больше нуля?  

В строке №47 при условии, что enc1.isClick() не 0.

А что там происходит с "enc1.isClick()" мы не знаем.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
boolean isClick();       // возвращает true при нажатии и отпускании кнопки, сама сбрасывается в false

Вы нажимаете и отпускаете кнопку ?

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

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

v258 пишет:

А в каком месте segment становится больше нуля?  

В строке №47 при условии, что enc1.isClick() не 0.

А что там происходит с "enc1.isClick()" мы не знаем.

Вот то то ж и оно. Пока на кнопку не кликнет, ничего не заработает ))

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

v258 пишет:

Пока на кнопку не кликнет, ничего не заработает ))

Ну, как бы кнопка для того и существует...)))

Andreas
Offline
Зарегистрирован: 10.11.2021

Это клик энкодера, его нажимаешь и сегмент увеличивается, доходит до трёх сбрасывается до одного, все в соотвествии с кодом.

А вот sec++ вообще никак не реагирует.
Хоть закликайся, увеличивается только segment.

Andreas
Offline
Зарегистрирован: 10.11.2021

v258 пишет:

У вас sec увеличивается только при условии segment > 0.Сам segment увеличивается тоже только при условии segment > 0. А в каком месте segment становится больше нуля?  Ну и что вас удивляет? ))

Меня удивляет то, что вы не видите, что есть условие при котором segment будет больше 0, при этом это условие выполняется -_-

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

Ну... Раз выполняется, начт, всё работает нормально.  Чо ты от нас-то хошь тогда?

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

Andreas пишет:

А вот sec++ вообще никак не реагирует.

А Вы не пробовали сами хоть что-нибудь сделать для решения проблемы?

Вот, смотрите. ВСЕГДА (от слова АБСОЛЮТНО ВСЕГДА - БЕЗ ИСКЛЮЧЕНИЙ) если возникает затык, то начинать надо не с поста на форуме, а с элементарной вставки отладочного вывода и его изучения.

Вот я вставил кое что в Ваш код, смотрите

#define CLK 7
#define DT 6
#define SW 4

#include "GyverEncoder.h"
#include <OLED_I2C.h>
#include <microDS3231.h>

Encoder enc1(CLK, DT, SW);  // для работы c кнопкой
OLED  myOLED(SDA, SCL);
MicroDS3231 rtc;

extern uint8_t MediumNumbers[];
byte segment;
byte sec;
char time[8];
char mod_time[8];
unsigned long timing_loop;
unsigned long timing_blink;

void setup()
{
  enc1.setType(TYPE2);
  myOLED.begin(SSD1306_128X32);
  myOLED.setFont(MediumNumbers);
  Serial.begin(9600);
  rtc.begin();
  Serial.println("Let's go on !!!");
}

void loop()
{
  enc1.tick();
  if (segment > 0) {
    Serial.println("Entered: if (segment > 0)");

    if (enc1.isClick())
      segment++;
    if (segment > 3)
      segment = 1;

    if (sec > 100) {
      segment = 0;
      sec = 0;
    }
    Serial.print("Just before sec++: sec=");
    Serial.print(sec);
    Serial.print("; segment=");
    Serial.println(segment);
    sec++;
    Serial.print("Just after sec++: sec=");
    Serial.println(sec);
  } else {
    if (enc1.isClick()) {
      segment = 1;
      Serial.println("Segment got 1");
    }
  }
  printTime();
  Serial.println(sec);
  Serial.println(segment);
  delay(100);
}



void change_time() {


}

void printTime() {
  rtc.getTimeChar(time);
  Serial.println(time);
}

Строка №28 нужна практически всегда! По идее, она печатается один раз, но важность её в том, что если программа по каким-то причинам неожиданно перегружается, Вы это увидите по повторному появлению этой печати в листинге.

Ну, а остальное более или менее понятно.

Запустите, изучите и, если не поймёте проблему, выкладывайте свежий код и протокол работы, чтобы мы могли изучить.

Andreas
Offline
Зарегистрирован: 10.11.2021

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

Andreas пишет:

А вот sec++ вообще никак не реагирует.

А Вы не пробовали сами хоть что-нибудь сделать для решения проблемы?

Вот, смотрите. ВСЕГДА (от слова АБСОЛЮТНО ВСЕГДА - БЕЗ ИСКЛЮЧЕНИЙ) если возникает затык, то начинать надо не с поста на форуме, а с элементарной вставки отладочного вывода и его изучения.

Вот я вставил кое что в Ваш код, смотрите

#define CLK 7
#define DT 6
#define SW 4

#include "GyverEncoder.h"
#include <OLED_I2C.h>
#include <microDS3231.h>

Encoder enc1(CLK, DT, SW);  // для работы c кнопкой
OLED  myOLED(SDA, SCL);
MicroDS3231 rtc;

extern uint8_t MediumNumbers[];
byte segment;
byte sec;
char time[8];
char mod_time[8];
unsigned long timing_loop;
unsigned long timing_blink;

void setup()
{
  enc1.setType(TYPE2);
  myOLED.begin(SSD1306_128X32);
  myOLED.setFont(MediumNumbers);
  Serial.begin(9600);
  rtc.begin();
  Serial.println("Let's go on !!!");
}

void loop()
{
  enc1.tick();
  if (segment > 0) {
    Serial.println("Entered: if (segment > 0)");

    if (enc1.isClick())
      segment++;
    if (segment > 3)
      segment = 1;

    if (sec > 100) {
      segment = 0;
      sec = 0;
    }
    Serial.print("Just before sec++: sec=");
    Serial.print(sec);
    Serial.print("; segment=");
    Serial.println(segment);
    sec++;
    Serial.print("Just after sec++: sec=");
    Serial.println(sec);
  } else {
    if (enc1.isClick()) {
      segment = 1;
      Serial.println("Segment got 1");
    }
  }
  printTime();
  Serial.println(sec);
  Serial.println(segment);
  delay(100);
}



void change_time() {


}

void printTime() {
  rtc.getTimeChar(time);
  Serial.println(time);
}

Строка №28 нужна практически всегда! По идее, она печатается один раз, но важность её в том, что если программа по каким-то причинам неожиданно перегружается, Вы это увидите по повторному появлению этой печати в листинге.

Ну, а остальное более или менее понятно.

Запустите, изучите и, если не поймёте проблему, выкладывайте свежий код и протокол работы, чтобы мы могли изучить.

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

Вот вывод монитора с вашим кодом:
 

Let go on !!!
16:06:18
0
0
16:06:18
0
0
16:06:18
0
0
16:06:18
0
0
16:06:18
0
0
16:06:18
0
0
16:06:18
0
0
16:06:18
0
0
16:06:18
0
0
Segment got 1
16:06:18
0
1
Entered: if (segment > 0)
Just before sec++: sec=0; segment=1
Just after sec++: sec=1
16:06:19
0
1
Entered: if (segment > 0)
Just before sec++: sec=0; segment=1
Just after sec++: sec=1
16:06:19
0
1
Entered: if (segment > 0)
Just before sec++: sec=0; segment=1
Just after sec++: sec=1
16:06:19
0
1
Entered: if (segment > 0)
Just before sec++: sec=0; segment=2
Just after sec++: sec=1
16:06:19
0
2
Entered: if (segment > 0)
Just before sec++: sec=0; segment=2
Just after sec++: sec=1
16:06:19
0
2
Entered: if (segment > 0)
Just before sec++: sec=0; segment=2
Just after sec++: sec=1
16:06:19
0
2
Entered: if (segment > 0)
Just before sec++: sec=0; segment=2
Just after sec++: sec=1
16:06:19
0
2
Entered: if (segment > 0)
Just before sec++: sec=0; segment=3
Just after sec++: sec=1
16:06:20
0
3

При этом в конце кода стоят два принта которые выводят сегмент и сек, к моменту их вывода sec уже обнулена.

Но самое интересное, что если из кода вообще убрать sec = 0;

 
То есть она нигде не должна обнуляться, то она все равно обнуляется.
Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

а если 59 ю закомментировать ?

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Andreas пишет:

Меня удивляет то, что вы не видите, что есть условие при котором segment будет больше 0, при этом это условие выполняется -_-

Вас удивляет совсем не то, что должно удивлять. Программа работает как задумано? Нет? Значит условие не выполняется. Условие выполняется, но переменная обнуляется? Значит где-то что-то ее обнуляет. И видимо это происходит где-то в недрах используемых библиотек. Если лень искать, где это происходит, просто переименуйте ее, например, в sec1

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

Andreas пишет:

Вот вывод монитора с вашим кодом:

Впредь вставляйте с номерами строк! Ну как это теперь обсуждать?

Ну, вот уже из этого листинга мы видим, Вы нам пудрите мозги (возможно, и себе тоже), когда пишете 

Andreas пишет:

А вот sec++ вообще никак не реагирует.

Если бы ++ не работал, то мы НИКОГДА не увидели бы вывода (в хз какой строке) типа

Just after sec++: sec=1

А раз он есть, значит, ++ работает. Согласны? 

Для меня ошибка уже очевидна, Вы распахиваете память и тупо записываете 0 в эту sec. И понятно в каком именно месте. Если для Вас это пока неочевидно, то можно поставить вывод sec буквально через строчку, только так, чтобы выводы отличались один от другого, и тогда Вы чётко увидите в каком месте и кто гадит.

Дальше сами или мне продолжать? 

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

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

 Вы распахиваете память и тупо записываете 0 в эту sec. И понятно в каком именно месте.

ура!

Евгений, как обычно, ТС забыл выделить место под терминатор?

 

PS - а вот и благодарность - кто-то уже влепил минус :)

Andreas
Offline
Зарегистрирован: 10.11.2021

Komandir пишет:

а если 59 ю закомментировать ?

Это решает проблему, но что не так с 59?
Там стандартная функция для часов.

Пробовал обозвать переменную иначе, но это не помогает, она все равно обнуляется.
Разве вызов функции должен ее обнулять?

Andreas
Offline
Зарегистрирован: 10.11.2021

b707 пишет:

ура!

Евгений, как обычно, ТС забыл выделить место под терминатор?

Под терминатор?
 

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

Andreas пишет:

что не так с 59?
Там стандартная функция для часов.
Разве вызов функции должен ее обнулять?

Ее обнуляет не "вызов функции", а ваша ошибка с выделением памяти. Читайте внимательно сообщение #15

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

16:06:20 это 8 символов + 1 символ #0 как окончание строки - ИТОГО 9 ...

Вы же выделили всего 8 байт под переменную time !!! Измените на 9 как минимум !!!

Загуглите "нультерминированные строки"

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

Andreas пишет:

Разве вызов функции должен ее обнулять?

А самому узнать что не позволяет? Религия или камасутра?

ЕвгенийП пишет:
Если для Вас это пока неочевидно, то можно поставить вывод sec буквально через строчку, только так, чтобы выводы отличались один от другого, и тогда Вы чётко увидите в каком месте и кто гадит.

Дальше сами или мне продолжать?

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

Ну, тваю ш дивизию! Мужики!

Ну, он бы сам дошёл очень скоро! И запомнил бы! Не столь важно про буфер, сколь про методику поиска ошибки!

А так Вы выложили всё на тарелочке и что? До следующего затыка? :-(((

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

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

...Ну, он бы сам дошёл очень скоро! ...

НЕ ВЕРЮ

он не туда смотрит как минимум

тем более что переменные объявлены как бы в другом порядке ...

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

Вот и посмотрели бы :-(

Komandir пишет:

он не туда смотрит как минимум

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

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

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

Ну, он бы сам дошёл очень скоро!

ну соррри... я старался не прямо намекнуть

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

Те, кто умеют думать - глупые вопросы на форумах не задают.

Andreas
Offline
Зарегистрирован: 10.11.2021

Komandir пишет:

16:06:20 это 8 символов + 1 символ #0 как окончание строки - ИТОГО 9 ...

Вы же выделили всего 8 байт под переменную time !!! Измените на 9 как минимум !!!

Загуглите "нультерминированные строки"

Огромное спасибо!
Впервые столкнулся с этой проблемой, т.к. раньше не писал на С.

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

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

Andreas пишет:

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

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

А догадайтесь с одного раза кто виноват ???

// вывод времени через char array
  char time[8];
  rtc.getTimeChar(time);
  Serial.println(time);

Это пример с гита гАЙВЕРА :-))))))))))))))))))))))))))

 

ТСу. Можете читать/смотреть/учиться у гАЙВЕРА, но НИКОГДА не пользуйтесь его ГОВНОКОДОМ !!!

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Кто бы сомневался.
Я , кстати , сам недавно попал в подобную ситуацию.
Даже перед заказчиком неудобно стало.
В промежуточной версии все работало как положено , а в предрелизной у заказчика дисплей падал после ввода параметров. При чем у меня все работало.
В общем в одной из правок был изменён вывод вводимых значений , точнее продублирован. Ну и соответственно под вводимые данные я выделил 4байта(3 знака на вывод), а по факту из за кириллицы нужно было выделять 7.
Самое печальное, что для того что бы отловить ошибку пришлось версию ПО заказчика у себя воспроизводить.
В моей видимо память как то по другому выделялась и на работу это переполнение никак не влияло.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Фигня. Вот я лет много назад на bash писал скрипт и не мог переменную инкрементить. Ну никак. Все строка получалась. )))

ЗВ: Конечно же разобрался потом, но кто бы мог подумать о таких «выкрутасах» в bash)))

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

У меня такая херня была. Написал программу, а переменные выдают жесть. Оказалось, что в библиотеке переменные с теми же именами.