if () {} else {}

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

Вопрос простой. До какой степени вложенности можно доводить данный оператор?

if (набор условий) {
  if (набор условий) {команды;}
команды;
}
else if (набор условий) {
  if (набор условий) {команды;}
  else {команды;}
  if (набор условий) {команды;}
команды;
команды;
команды;
}
else if (набор условий) {команды; команды; команды; команды;}
else {команды;}

структура моего кода схожа, в одной из функций происходит множественное ветвление с проверкой кучи условий в основном соединённых логическими операторами. код работал нормально, но в какой то момент усложнения (добавления каких то строк) стал выдавать побочные неожиданные результаты. происходит выполнение блоков условия для выполнения которых не выполнены (т.е. исключены вышестоящим оператором проверки условий).  и присвоение некоторым переменным значений, возникновение которых не возможно без некорректного зацикливания или неверного обращения к памяти. (типа: i=1;,2;,3,;4;,10;, в отдельных условиях i++; и вдруг появляются значения i=250;).

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

 

leshak
Offline
Зарегистрирован: 29.09.2011

 > До какой степени вложенности можно доводить данный оператор?

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

Так что скорее всего, все-таки ошибка где-то у вас. Раз логика "замудренная", то и промахнутся с закрывающей скобой все шансы есть. Или еще что-то (случаной i присвоили, с указателями напутали, вышли за границы массива/буфера и т.п.)

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

>что нифига не на пользу экономии памяти

Зато на пользу сопровождаемости и читабельности кода. А это тоже очень важная храктеристика, не менее важная чем "что-бы работало". Неужели у вас уже действительно счет памяти "на байты" идет? Уверены что не занимаетесь преждевременной оптимизацией?

Да и, возможно, можно как-то по другому все "замутить", что-бы небыло этой тучи ветвлений. Какой-нибудь автомат состояний, pattern matching и т.п. Вообщем попытатся сделать логику более простой. Но не сколько для "экономии памяти", сколько для "более прозрачного кода".

>Прямо сейчас оригинал скетча выгрузить не могу

А без этого можно только "абстрактно теоретизировать".

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

если у вас есть проверка множества условий,почему бы не воспользваться оператором switch() case - этот оператор просто создан для подобного рода заданий))и читабельности ,там так же на каждый case можно определить выпонения нескольких операций )) 

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

все скобки пересчитал первым делом, т.е. буквально каждую выделял и смотрел что она открывает или закрывает. присвоения по подозрительной переменной несколько раз пролистал с помощью поиска (бывало, что вместо проверки условия == появлялось =, но не в этот раз). switch() case совершенно не подходит, он сможет заменить лишь первый уровень if () else{}. переполнение переменной определённой как байт дождаться не тяжело, но только при неправильной работе кода. к нано уже зацеплены SPI экран, кардридер и часы. всё это только в виде библиотек не слабо хавает память. вывод на экран это строки, флешка тоже, часы тоже не пустышка. да плюс всё моё написанное. буду разбивать на функции, если заработает, значит компилятор таки кривой.

leshak
Offline
Зарегистрирован: 29.09.2011

 >буду разбивать на функции, если заработает, значит компилятор таки кривой

Скорее всего поможет. Но не потому что "компилятор кривой" (в лотерию IMHO вероятней миллион выиграть), а потому что переписывая, да еще более читабильным видом вы с большой долей вероятности не повторите ту же самую ошибку.

>все скобки пересчитал первым делом

Ну так скобки это же только "один из возможных" способов :) Еще десяток способов "выстрелить себе в ногу" имеется.

А switch, на самом деле, в сочетании с подходом "автомат состояний" может сильно упростить логику. Если и не полностью избавить от if-вов, то сократить их кардинально, а оставшиеся сделать "тривиальными". Но естесвенно это потребует "смены алгоритма". Просто "вместо if использовать switch" либо ввобще не выйдет, либо будет еще более "монструозно".

И померяйте оставшуюся память (пару дней назад были ветки где это обсуждалось, давал там линки). Раз у вас "куча всего", то шанс совсем не маленький что причина в нехватке оперативки. Причем если вы сейчас "перепишите на функции" и оно заработает, то это может означать только что баг "случайным образом" переместился куда-то в более незаметное место. И когда и куда вылезет - не известно.

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

да, тему про память видел, но руки ещё не дошли. хотя вероятно в любом случае буду аппаратную базу менять. слишком много подводныз камней для неопытного программиста даже при работе с часами DS1307, не говоря уж о цветных многопиксельных экранах

leshak
Offline
Зарегистрирован: 29.09.2011

>слишком много подводныз камней для неопытного программиста

Ну Си она такая :) Большая свобода, но и большая отвественность.

>не говоря уж о цветных многопиксельных экранах

Да. Тут память лишней не будет.

Может покажете свой скетч? Вдруг углядим ошибку какую.

ourlive
Offline
Зарегистрирован: 26.05.2012
/***************************************************
работает:
1. опрос часов раз в пол секунды
2. опрос кнопок нажатие(0.1 сек) и долгое нажатие (1+ сек)
3. индикация нажатия
4. стирание одного символа
5. печать текста с накоплением в буфер печати (длина одного блока не более 255)
6. контроль границ экрана при печати
7. меню - мачало
8. вывод времени
9. установка времени

    LCD  
  _____________________128_________________________
  |
  |
  |
  |
  |
  |
  |
 160
  |
  |
  |
  |
  |
  |
  
  TextSize(1) Heigh 8    length 5+1
  TextSize(2) Heigh 16
  TextSize(3) Heigh 24
  
 ****************************************************/

// определение пинов
#define sclk 13
#define mosi 11
#define cs   8
#define dc   10
#define rst  7  // you can also connect this to the Arduino reset

#include <Adafruit_GFX.h>    // библиотека графики
#include <Adafruit_ST7735.h> // библиотека на экран
#include <SPI.h>

#include <Wire.h>                       // 1-wire
#include <DS1307new.h>                  // часы

// определение пинов экрана
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);

// определение переменных------------------------------------------------------------------------------------------
byte key_put=0;  // нажатая клавиша
byte menu_stat=31;  // статус меню
unsigned long time=0;      // таймер работы дуины
unsigned long timer_key=0; // таймер клавиши
unsigned long timer_time=0; // таймер часов
unsigned long timer_menu=0; // таймер меню
unsigned long timer_my_print=0; // таймер меню
String my_text_print="";        // текстовая строка на печать

uint16_t dc_year;       // время
uint8_t dc_month;
uint8_t dc_day;

uint8_t dc_hour;
uint8_t dc_minute;
uint8_t dc_second;

void setup(void) {
  Serial.begin(9600);
  pinMode(6,OUTPUT); 
  analogWrite(6, 10);        //подсветка
  tft.initR(INITR_REDTAB);   // инициализация ST7735R chip, red tab
  tft.fillScreen(ST7735_BLACK); // залить весь экран чёрным
  start1();
  RTC.getTime();
  time_print(1);
}

void start1() {
  tft.setTextColor(ST7735_WHITE);
  tft.setTextSize(2);
  tft.setCursor(1, 10);
  tft.println("   Nano");
  tft.println("  tester");
  tft.println("   v0.7");
  delay(2000);
  tft.fillScreen(ST7735_BLACK);
  }
  
void time_read() { //читать время раз в пол секунды
  if (time>timer_time) {
  timer_time=timer_time+500000;  
  RTC.getTime();      
  // RTC.year - RTC.month - RTC.day - RTC.dow -год, месяц, день, день недели
  // RTC.hour : RTC.minute : RTC.second - часы:минуты:секунды
  
   //остановить печать времени, если идёт настройка часов
   if (menu_stat<10 || menu_stat>30) {
   time_print(0);} //печать и обновление времени отключены
}}

String time_2d(uint8_t t) { //добавление до двух знаков для печати
  if (t<10) {return "0"+String(t);}
  else {return String(t);}
}
void time_print(boolean k) { //печать времени 0-обычное, 1-принудительное
  if (k==0) {
   if (dc_year!=RTC.year) {dc_year=RTC.year; my_print_tft(1,150,String(dc_year),1);}
   if (dc_month!=RTC.month) {dc_month=RTC.month;  my_print_tft(31,150,time_2d(dc_month),1);}
   if (dc_day!=RTC.day) {dc_day=RTC.day;  my_print_tft(49,150,time_2d(dc_day),1);}
   if (dc_hour!=RTC.hour) {dc_hour=RTC.hour;  my_print_tft(67,150,time_2d(dc_hour),1);}
   if (dc_minute!=RTC.minute) {dc_minute=RTC.minute;  my_print_tft(85,150,time_2d(dc_minute),1);}
   if (dc_second!=RTC.second) {dc_second=RTC.second;  my_print_tft(103,150,time_2d(dc_second),1);}
  }
  else { 
  my_print_tft(25,150,".",1);
  my_print_tft(43,150,".",1);
  my_print_tft(79,150,":",1);
  my_print_tft(97,150,":",1);
  my_print_tft(1,150,String(dc_year),1); 
  my_print_tft(31,150,time_2d(dc_month),1);
  my_print_tft(49,150,time_2d(dc_day),1);
  my_print_tft(67,150,time_2d(dc_hour),1);
  my_print_tft(85,150,time_2d(dc_minute),1);
  my_print_tft(103,150,time_2d(dc_second),1);
  
  }}
  

void key() { //определение нажатой кнопки
if (time>timer_key) {
  byte key_put_local=0;
  timer_key=time+10000;                          // ожидание нажатия клавиши 10 раз в секунду
  unsigned int key=analogRead(A3);
  tft.drawLine(0,0, 2,0,ST7735_BLACK);            // затереть индикацию
  if (key>1000) {key_put_local=0;}                // клавиша не нажата
  else if (key<470 && key>455) {key_put_local=1; timer_key=time+500000;} // клавиша нажата, следующая проверка через пол секунды
  else if (key<395 && key>385) {key_put_local=2; timer_key=time+500000;}
  else if (key<305 && key>290) {key_put_local=3; timer_key=time+500000;}
  else if (key<185 && key>165) {key_put_local=4; timer_key=time+500000;}
  else {key_put_local=5; timer_key=time+500000;}  //кнопка не определена
  if (key_put_local!=0) {
  if (key_put_local==key_put || key_put==key_put_local+5) {key_put=key_put_local+5;} // если клавиша нажата более 1 секунды(две проверки нажатия), установить статус +5 - долгое нажатие
  else {key_put=key_put_local;}
  if (key_put==1) {tft.drawLine(0,0, 1,0,ST7735_RED);}      // цветовая индикация нажатия
  if (key_put==2) {tft.drawLine(0,0, 1,0,ST7735_YELLOW);}
  if (key_put==3) {tft.drawLine(0,0, 1,0,ST7735_GREEN);}
  if (key_put==4) {tft.drawLine(0,0, 1,0,ST7735_BLUE);}
  if (key_put==5) {tft.drawLine(0,0, 1,0,ST7735_WHITE);}
  if (key_put==6) {tft.drawLine(0,0, 2,0,ST7735_RED);}
  if (key_put==7) {tft.drawLine(0,0, 2,0,ST7735_YELLOW);}
  if (key_put==8) {tft.drawLine(0,0, 2,0,ST7735_GREEN);}
  if (key_put==9) {tft.drawLine(0,0, 2,0,ST7735_BLUE);}
  if (key_put==10) {tft.drawLine(0,0, 2,0,ST7735_WHITE);}}
  else {key_put=0;}                                         //коррекция статуса, если ничего не нажато.
}}

void clear_byte (byte x, byte y, byte s) { // стирает один символ курсор (х,у), размер шрифта (s)
  tft.setTextColor(ST7735_BLACK);
  tft.setTextSize(s); 
  tft.setCursor(x, y); 
  tft.println(char(218)); 
  }

void my_print_tft (byte x, byte y, String text, byte s) { //х,у - курсор; text - текст на печать, s - size
Serial.print(menu_stat); //---------------------------------------------------------блок контроля выявивший косяк
Serial.print(" ");
Serial.print(timer_menu);
Serial.print(" ");
Serial.println(key_put);

  // при адекватных параметрах отправить данные на печать и наличии места в буфере
  if (x>0 && x<128 && y>0 && y<160 && s>0 && s<5 && text!="" && my_text_print.length()+text.length()<256) {
      if (my_text_print!="") {
      my_text_print=my_text_print+String(char(218))+String(char(x))+String(char(y))+String(char(s))+text;} // если печать уже идёт
      else {my_text_print=String(char(1))+String(char(218))+String(char(x))+String(char(y))+String(char(s))+text;} // если буфер пуст (курсто установить на единицу)
  }}
  
void my_print_tft_t() {
  if (my_text_print!="") {
  if (time>=timer_my_print) {
    timer_my_print=time+100000; // печатать 10 символов в секунду
    label1:
  byte l=my_text_print.length(); // выделение параметров из строки
  byte s= my_text_print.charAt(4);
  byte cur= my_text_print.charAt(0);
  word x= my_text_print.charAt(2)+(cur-1)*s*6;
  byte y= my_text_print.charAt(3);
  char my_char=my_text_print.charAt(5);
  //если достигнут ключевой символ стереть старые координаты и записать новые
  if (my_char==char(218) &&l>6) {
  my_text_print=String(char(1))+my_text_print.substring(5); 
  goto label1;}
    label2:
  if (x>122 && s==1) {x-=122;y+=8*s;goto label2;} // при выходе строки за экран перейти на следующую------------кривое исполнение
  if (x>116 && s==2) {x-=116;y+=8*s;goto label2;}
  if (x>110 && s==3) {x-=110;y+=8*s;goto label2;}
  if (x>104 && s==4) {x-=104;y+=8*s;goto label2;}
  if (y<153) { // при выходе строки за экран, игнорировать печать
  clear_byte(x,y,s);  //очистка позиции и печать символа
  tft.setTextColor(ST7735_WHITE);
  tft.setTextSize(s);
  tft.setCursor(x, y);
  tft.print(my_char); }
  my_text_print=my_text_print.substring(0,5)+my_text_print.substring(6); //удаление из буфера напечатанного символа
  cur++;
  my_text_print.setCharAt(0,char(cur));
  if (l<7) {my_text_print="";}// напечатан последний символ
}}}

void menu_start() {  //главное меню
  timer_menu=1; 
  tft.fillScreen(ST7735_BLACK); 
  my_text_print="";
  time_print(1);
  my_print_tft (50,1,"MENU",2); 
  menu_stat=1;
  my_print_tft (10,20,"1. TIME",1);
  my_print_tft (10,30,"2. ",1);
  my_print_tft (10,40,"3. ",1);
  my_print_tft (10,50,"4. ",1);
  menu_cur('-');
}
void menu_time() { //меню времени
timer_menu=1; 
  tft.fillScreen(ST7735_BLACK);
  my_text_print=""; 
  my_print_tft (50,1,"TIME",2); 
  my_print_tft (10,20,"year",1);
  my_print_tft (10,30,"month",1);
  my_print_tft (10,40,"day",1);
  my_print_tft (10,50,"hour",1);
  my_print_tft (10,60,"minute",1);
  my_print_tft (10,70,"second",1);
  
  my_print_tft (50,20,String(dc_year),1);
  my_print_tft (62,30,time_2d(dc_month),1);
  my_print_tft (62,40,time_2d(dc_day),1);
  my_print_tft (62,50,time_2d(dc_hour),1);
  my_print_tft (62,60,time_2d(dc_minute),1);
  my_print_tft (62,70,time_2d(dc_second),1);
  menu_cur('>');
}

void menu_cur(char ch) {
  key_put=0;
 if  (menu_stat<1) {menu_stat=1;}
 if  (menu_stat>4 && menu_stat<10) {menu_stat=4;} 
 if  (menu_stat==10) {menu_stat=11;} 
 if  (menu_stat>16 && menu_stat<20) {menu_stat=16;} 
 if (menu_stat<10) {my_print_tft (1,(menu_stat+1)*10,String(ch),1);}
 else if (menu_stat<20) {my_print_tft (1,(menu_stat-9)*10,String(ch),1);}}
 
void time_plus() { //плюс ко времени
  //год
  if (menu_stat==21) {dc_year++; if (dc_year>2222) {dc_year=2222;}  my_print_tft (50,20,String(dc_year),1);day_correct();}
  //месяц
  if (menu_stat==22) {dc_month++; if (dc_month>12) {dc_month=12;}my_print_tft (62,30,time_2d(dc_month),1);day_correct();}
  //день
  if (menu_stat==23) {dc_day++;day_correct();}
  //час
  if (menu_stat==24) {dc_hour++; if (dc_hour>23) {dc_hour=0;}my_print_tft (62,50,time_2d(dc_hour),1);}
  //минута
  if (menu_stat==25) {dc_minute++; if (dc_minute>59) {dc_minute=0;}my_print_tft (62,60,time_2d(dc_minute),1);}
  //секунда
  if (menu_stat==26) {dc_second++; if (dc_second>59) {dc_second=0;}my_print_tft (62,70,time_2d(dc_second),1);}
}
void time_minus() { //минус от времени
  //год
  if (menu_stat==21) {dc_year--; if (dc_year<2010) {dc_year=2010;}  my_print_tft (50,20,String(dc_year),1);day_correct();}
  //месяц
  if (menu_stat==22) {dc_month--; if (dc_month<1) {dc_month=1;} my_print_tft (62,30,time_2d(dc_month),1);day_correct();}
  //день
  if (menu_stat==23) {dc_day--; if (dc_day<1) {dc_day=1;}day_correct();}
  //час
  if (menu_stat==24) {dc_hour--; if (dc_hour>250) {dc_hour=23;}my_print_tft (62,50,time_2d(dc_hour),1);}
  //минута
  if (menu_stat==25) {dc_minute--; if (dc_minute>250) {dc_minute=59;}my_print_tft (62,60,time_2d(dc_minute),1);}
  //секунда
  if (menu_stat==26) {dc_second--; if (dc_second>250) {dc_second=59;}my_print_tft (62,70,time_2d(dc_second),1);}
}

void day_correct() { //корректировка дня
  if (dc_month==4 || dc_month==6 || dc_month==9 || dc_month==11) {
    if (dc_day>30) {dc_day=30;}}
    
  if (dc_month==2 && dc_day>28 && (dc_year % 4)!=0) {dc_day=28;}
  else if (dc_month==2 && dc_day>29) {dc_day=29;}
  if (dc_day>31) {dc_day=31;}
  my_print_tft (62,40,time_2d(dc_day),1);}

void day_enter() {//установка нового времени часов
RTC.fillByYMD(dc_year, dc_month, dc_day);
RTC.fillByHMS(dc_hour, dc_minute, dc_second);
RTC.setTime();
RTC.startClock();
}
//menu_stat = 
//1-10 - главное меню
//11-20 - меню часов
//21-31 - настройка часов

void menu () {  //меню
  if (key_put==6 && timer_menu==0) {menu_start();}
  if (timer_menu!=0 && time>=timer_menu) {   
  timer_menu=time+200000;
    if (menu_stat<10) { // перемещение по главному меню
    if (key_put==2) {clear_byte(1,(menu_stat+1)*10,1); menu_stat--; menu_cur('-');}
    if (key_put==3) {clear_byte(1,(menu_stat+1)*10,1); menu_stat++; menu_cur('-');}
    if (key_put==4 && menu_stat==1) {menu_stat=11; menu_time();}
  //-----------------------------------------------------------------где то тут косяк, при выборе пустого меню появляется левый курсор
  if (key_put==6) {tft.fillScreen(ST7735_BLACK); my_text_print=""; time_print(1);key_put=0;menu_stat=0;timer_menu=0;}
  }
  else if (menu_stat<20) { // перемещение по меню часов
  if (key_put==2) {clear_byte(1,(menu_stat-9)*10,1); menu_stat--; menu_cur('>');}
  if (key_put==3) {clear_byte(1,(menu_stat-9)*10,1); menu_stat++; menu_cur('>');}
  if (key_put==4) {menu_stat=menu_stat+10; clear_byte(1,(menu_stat-9)*10,1); my_print_tft (1,(menu_stat-19)*10,"*",1);key_put=0;}}
  if (key_put==6) {key_put=0; day_enter(); menu_stat=1;menu_start();}
  
  else if (menu_stat<30) {
  if (key_put==2) {clear_byte(1,(menu_stat-9)*10,1); my_print_tft (1,(menu_stat-19)*10,"+",1);time_plus();key_put=0;}
  if (key_put==3) {clear_byte(1,(menu_stat-9)*10,1); my_print_tft (1,(menu_stat-19)*10,"-",1);time_minus();key_put=0;} 
  if (key_put==4) {clear_byte(1,(menu_stat-9)*10,1); my_print_tft (1,(menu_stat-19)*10,">",1);menu_stat=menu_stat-10;key_put=0;}}
}}



void loop() {
 
  time=micros();
  key();
  time_read();
  my_print_tft_t();
  menu ();
  
}

 откомментирую работу.

на старте выводится версия кода, далее в цикле начинает читаться и выводится на LCD текущие дата и время.

при долгом нажатии на на клавишу"1" разворачивается главное меню. на данный момент 1й пункт установка времени, 2,3,4. не заняты. клавиши 2,3 -вверх/вниз 4-ок. 5-ошибка чтения нажатия клавишь, 6-9 соответственно долгие нажатия соответствующих клавишь.

при выборе пункта "1. time" разворачивается подменю. пункты часов от года до секунды. параметры изменяются аналогично курсорным методом. выход в главное меню долгое нажатие клавиши "1", и одновременно записывает в часы новые данные. выход в основной экран (в котором кроме часов пока ничего нет) аналогично.

всё работает как задумано, однако если в главном меню выбрать пункт "2. " - резерв, то получаю косяк. появляется курсор из подменю часов, а статус меню menu_stat (одновременно и курсор и указатель) получает значение на данный момент не существующее. (число 250 за один цикл работы функции вроде просто неоткуда взять)

 

leshak
Offline
Зарегистрирован: 29.09.2011

 Вечерком попробую посмотреть подробней, но присмотритесь к строчке 311 и 318.

Втыкните там Serial.print посмотрите что там происходит. Возможно  что 250 это не "сильно увеличенная", а наоборот "сильно уменьшенная" menu_stat . Если она была 0, а вы от нее отняли 1, то получите 254 (она же беззаковая), потом еще парочку отниманий и имеем искомую 250.

leshak
Offline
Зарегистрирован: 29.09.2011

 Но то что это не проблема "вложенности if" - это точно. Никакго "сверх-глубокого вложения" - у вас нет и в помине.

Код немного "заспагечен" и стоило бы его "причесать" (убрать "магические цифры", где-то  switch "просится",  где-то массивом можно, где-то дублирование кода...), но к чему-то "фатальному" это не должено приводить.

Так что либо "искать ошибку" (вероятней) либо "проверять сколько оперативки".

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

так у этого кода в любом случае одна дорога - в архив, на память об ошибках молодости. в этом скетче нужно ещё изучить и отработать начальные умения по работе с SD карточкой и чтоб оно не конфликтовало с остальным, возможно ещё  подвесить датчик температуры. если оставшихся 10к памяти хватит.

а блок контроля Serial я перетащил с 300х строк на 169ю, результат во всех точках одинаковый, переменная изменяет своё значение скачком, вероятно выполняется строка 326 (щас углядел единственную возможность), но как получается, что она выполняется - непонятно

leshak
Offline
Зарегистрирован: 29.09.2011

 >так у этого кода в любом случае одна дорога - в архив

Ну почему. Потренероватся на нем в результатах чтения книг типа "Совершенный код" и "Ремесло программиста" - очень даже можно. Не всегда можно "все переписать с нуля". Так что уметь "приводить код в чувство" - нужно. Тем боле что "писать сразу красиво всегда" - не возможно как бы не хотелось. Да и иногда "быстро" важнее чем "красиво". Чисто проверить идею. Если "заработало", тогда уже и про оптимизации с красивостями думать можно.

>если оставшихся 10к памяти хватит.

Уй. Вы натурально ошибаетесь. У самой жирной меги памяти всего 8KB. Вы скорее всего спутали с "флеш памятью" (это то что показывает как "размер скетча"). Флеш - это аналог компьютерного "винчестера" где скетч хранится при выключении. А при подачи питания он копируются в RAM. Если не хватит флеша - скетч просто не зальется, если не хватит памяти (RAM) - ребуты, зависы и магические глюки.

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

>а блок контроля Serial я перетащил с 300х строк на 169ю,

Не понял что вы куда перетащили. Но навтыкайте дополнительно Serial.print везде где вы изменяете menu_stat. Особенно где уменьшаете (не заметил 326 строку) . Можете по два раза "до изменения" и "после". Задетекте четко место где происходит "скачок", потом будете выяснять "а как оно туда попадает" (тем же способом - тыкаем Serial-принты. Можно к ним добавлять еще какую-то строку, что-бы было легче понять "какой именно принт гавгнул").

 

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

> 10к

да, я имел в виду именно флешную память.

с Serial.print поразбираюсь

leshak
Offline
Зарегистрирован: 29.09.2011

 Думаю примерно такая функция может помочь

byte prev_menu_stat=0;

void dbgms(char rowName[]){
  Serial.print(rowName); Serial.print(": ");
  Serial.print("prev_m=");Serial.print(prev_menu_stat);
  Serial.print(", m=");Serial.println(menu_stat);
  prev_menu_stat=menu_stat;
}

....
menu_stat=menu_stat-10;
dbgms("Kakaya-to stroka");

....

menu_stat++;
dbgms("Drugaya stroka");
....