Всем, добрый день. Написал функцию. К которой нет обращения из Setup и Loop. При этом ардуин начинает, без перерыва пихать в порт белиберду. Если функцию укоротить (часть за каментировать) все начинает работать нормально. Размер кода ~6000 байт. У меня Arduino Mini. В чем может быть проблема. Вот кусок текста: Код (Text): #define menu_r_01_0 " " #define menu_r_01_1 " Нормальная " #define menu_r_01_2 " эксплуатация " #define menu_r_01_3 " " #define menu_e_01_0 " " #define menu_e_01_1 " Normal operating " #define menu_e_01_2 " conditions " #define menu_e_01_3 " " . . .//длинный список #define button_demo 14 //A0 #define button_objects 15 //A1 #define button_Conditions 16 //A2 #define button_doun 17 //A3 #define button_up 18 //A5 volatile int menu = 0; void setup() { Serial.begin(9600); pinMode(button_demo,INPUT); pinMode(button_objects,INPUT); pinMode(button_Conditions,INPUT); pinMode(button_doun,INPUT); pinMode(button_up,INPUT); } void loop() { Serial.println("Start"); while (1); } void Menu() { if (menu==1){ if (language==1){ Serial.println(menu_r_01_0); Serial.println(menu_r_01_2); Serial.println(menu_r_01_1); Serial.println(menu_r_01_3); } else { Serial.println(menu_e_01_0); Serial.println(menu_e_01_2); Serial.println(menu_e_01_1); Serial.println(menu_e_01_3); } } if (menu==2){ if (language){ Serial.println(menu_r_02_0); Serial.println(menu_r_02_2); Serial.println(menu_r_02_1); Serial.println(menu_r_02_3); } else { Serial.println(menu_e_02_0); Serial.println(menu_e_02_2); Serial.println(menu_e_02_1); Serial.println(menu_e_02_3); } } if (menu==3){ if (language){ Serial.println(menu_r_03_0); Serial.println(menu_r_03_2); Serial.println(menu_r_03_1); Serial.println(menu_r_03_3); } else { Serial.println(menu_e_03_0); Serial.println(menu_e_03_2); Serial.println(menu_e_03_1); Serial.println(menu_e_03_3); } } . . . .// 23 Меню }
Мини, кажется, располагает только двумя килобайтами оперативной памяти. Вы старательно заполнили ее пробелами, наверное, на все 4 кБ Думаю, что проблема в этом. Подсказка: Чтобы на экране вывелось нечто подобное ____________________ Нормальная эксплуатация ____________________ достаточно написать следующую строку Код (Text): Serial.print("/nНормальная/nэксплуатация/n/n"); Определять текстовые данные дефайнами - смертельно! Совет: Изучите главу Arrays of strings здесь http://arduino.cc/en/Reference/PROGMEM Это решение вашей проблемы.
Хорошее предложение вам уже написали. Я на вскидку без особых раздумий в качестве простого и прямого примера, могу вам предложить замену вашей функции Menu() С учетом того что вы желаете выводить именно 4 строки. Массив массивов, но если подумать над всем более хорошо, думаю можно найти более элегантные решения. Намного короче вашего дикого набора повторяющихся операторов не правда ли Код (Text): void ShowMenu(int languageId, int menuId) { for(var i = 0; i < 4; i++) { Serial.println( menuData[languageId][menuId][i] ); } }
А если даже очень хочется определять строки дефайнами, то зачем 4 раза определять одну и ту же строку из пробелов?
Я не знаю логики вашей программы, посему набросал лишь суть. Которая решает проблему размеров и еще маленькую тележку проблем Код (Text): const int ENGLISH = 1; const int RUSSIAN = 2; char englishMenu[][40] = { "\nEng.Menu 1\nDescription\n", "\nEng.Menu 2\nDescription\n", "\nEng.Menu 3\nDescription\n" }; char russianMenu[][40] = { "\nRu.Menu 1\nDescription\n", "\nRu.Menu 2\nDescription\n", "\nRu.Menu 3\nDescription\n" }; void SomeFunction() { int language = ENGLISH; int menuItem = 1; switch(language) { case ENGLISH : ShowMenu(englishMenu[menuItem - 1]); break; case RUSSIAN : ShowMenu(russianMenu[menuItem - 1]); break; } } void ShowMenu(char *menu) { Serial.println(menu); } Постарался сделать код минимальным и понятным, думаю вы вполне разберетесь. На дуне не проверял но на ПК все работает. Выводит он те же самые 4 строчки на 1 пункт меню, но весь пункт меню хранится лишь в одной строчке в которой мы используем управляющие символы, о которых вам написали выше.
Если уж делать код минимальным, то не стоит один вызов функции заворачивать в другой - это ничего не дает, кроме лишних расходов памяти и тактов. Проще комментарий написать в нужном месте А в остальном все правильно. З.Ы.: а если добавить массиву третье измерение, как Вы поначалу предложили, то еще и switch не понадобится - снова сокращение объема кода и времени выполнения...
Да, вы правы, я просто учитывая то как человек написал свой первый вариант, сознательно постарался не мудрить, а наглядно показать логику что бы он мог поковырять и попробовать
Всем большее спасибо за помощь. Но проблема осталась. На самом деле я показал кусок который пытался отладить с COM портом. Методом подсказок и тыка я понял, что у меня текст превышает 2 кб SRAM. Реально задача следующая. Мне нужно выводить текст на 4-х строчный LCD, 20 символов в строке. Последний вариант массива который я смог написать: Код (Text): char* empty = " "; char* menu_e_01[] = {empty," Normal operating "," conditions ",empty}; char* menu_e_02[] = {" Loss of power with "," diesel generator "," start-up ",empty}; . . char* menu_e_31[].... 31-я уже не влезает. Как правильно описывать такие массивы. Как правильно использовать указатели в таких случаях. Заранее большее спасибо.
Вам уже ответили: И не нужно хранить в памяти кучу ненужных пробелов. Существуют функции для очистки экрана и для установки курсора в заданную позицию.
Добрый вечер. Все подсказки помогли. Большее спасибо. Но вылезли другие проблемы. Памяти стало хватать. Но опять вылезла проблема с кодировкой. В тех строчках где есть русский текст вмести с текстом появляется белеберда. Как будто прихватывается чужая область памяти. С английским таких проблем нет.
Проект уже сдали. К сожалению глубоко разбираться времени не было. Проблему с нехваткой SRAM и неправильным отображением русской кодировки на LCD пришлось решать 2 методами. (Еще раз большое спасибо всем за помощь.) Английский текст я описал следующим методом: Код (Text): prog_char string_17[] PROGMEM={" "" Normal operating "" conditions "" "}; prog_char string_18[] PROGMEM={" Loss of power with "" diesel generator "" start-up "" "}; //........... и т.д. PROGMEM const char *string_table[] = { string_17,string_18,string_19,string_20,string_00,string_21,string_22,string_23,string_24, string_25,string_26,string_27,string_28,string_29,string_30,string_31,string_32,string_33, string_34}; char buffer[80]; //Вывод на экран if (language){ i=menu-1; strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); lcd.setCursor(0,0); for (byte k=0; k<=19; k++) lcd.write(buffer[k]); lcd.setCursor(0,1); for (byte k=20; k<=39; k++) lcd.write(buffer[k]); lcd.setCursor(0,2); for (byte k=40; k<=59; k++) lcd.write(buffer[k]); lcd.setCursor(0,3); for (byte k=60; k<=79; k++) lcd.write(buffer[k]); } Русский текст я описал следующим методом: Код (Text): char* empty = " "; char* menu_r_01[] ={empty, " Нормальная ", " эксплуатация ", empty}; // ....... и т.д. // Вывод на экран lcd.clear(); lcd.print(menu_r_01[0]); lcd.print(menu_r_01[2]); lcd.print(menu_r_01[1]); lcd.print(menu_r_01[3]); В результате я сэкономил память при применении PROGMEM и добился правильного отображения русского. Правда программа местами не очень красиво выглядит. Если PROGMEM вывести в com порт, можно увидеть странные вещи. P.S. Я Arduino первый раз увидел 3 мес. назад. И тогда же стал знакомиться с С. Для решения моей задачи среда Arduino оказалась очень бедная. Отладка в слепую. Что внутри твориться непонятно. Сколько место занимает тоже. Может кто другую среду посоветует.
Программирование есть понимание. (с) Кристин Нюгард Если вы не понимаете что вы пишите, вам никакая среда не поможет. Если вы с первых месяцев думаете не о том что бы понять КАК писать а ГДЕ найти среду которая будет искать баги за вас, забейте на программирование.
Может, сперва форум проглядите? Тут обсуждались и среды другие, и способы отладки "не вслепую", и еще много чего. Мои соболезнования заказчику. Хорошо, что Вы дома не строите. Мне было бы страшно в таком жить.