Проблема в скетче

Тема в разделе "Arduino & Shields", создана пользователем Zaic, 15 окт 2013.

  1. Zaic

    Zaic Нерд

    Всем, добрый день.
    Написал функцию. К которой нет обращения из 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 Меню

    }
     
     
    Последнее редактирование: 15 окт 2013
  2. roggedhorse

    roggedhorse Гик

    Мини, кажется, располагает только двумя килобайтами оперативной памяти.
    Вы старательно заполнили ее пробелами, наверное, на все 4 кБ
    Думаю, что проблема в этом.

    Подсказка:

    Чтобы на экране вывелось нечто подобное
    ____________________

    Нормальная
    эксплуатация

    ____________________
    достаточно написать следующую строку

    Код (Text):
    Serial.print("/nНормальная/nэксплуатация/n/n");
    Определять текстовые данные дефайнами - смертельно!

    Совет:

    Изучите главу Arrays of strings здесь http://arduino.cc/en/Reference/PROGMEM
    Это решение вашей проблемы.
     
    Последнее редактирование: 15 окт 2013
  3. NR55RU

    NR55RU Гик

    Хорошее предложение вам уже написали.
    Я на вскидку без особых раздумий в качестве простого и прямого примера, могу вам предложить замену вашей функции Menu()
    С учетом того что вы желаете выводить именно 4 строки.
    Массив массивов, но если подумать над всем более хорошо, думаю можно найти более элегантные решения.
    Намного короче вашего дикого набора повторяющихся операторов не правда ли :)

    Код (Text):
    void ShowMenu(int languageId, int menuId)
    {
        for(var i = 0; i < 4; i++)
        {
            Serial.println( menuData[languageId][menuId][i] );
        }
    }
     
  4. roggedhorse

    roggedhorse Гик

    P.S. Табулированный отступ вывода:

    Код (Text):
    Serial.println("\tТабуляция");
     
  5. Megakoteyka

    Megakoteyka Оракул Модератор

    А если даже очень хочется определять строки дефайнами, то зачем 4 раза определять одну и ту же строку из пробелов?
     
  6. NR55RU

    NR55RU Гик

    Я не знаю логики вашей программы, посему набросал лишь суть.
    Которая решает проблему размеров и еще маленькую тележку проблем :)
    Код (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 пункт меню, но весь пункт меню хранится лишь в одной строчке в которой мы используем управляющие символы, о которых вам написали выше.
     
    Megakoteyka нравится это.
  7. Megakoteyka

    Megakoteyka Оракул Модератор

    Если уж делать код минимальным, то не стоит один вызов функции заворачивать в другой - это ничего не дает, кроме лишних расходов памяти и тактов. Проще комментарий написать в нужном месте :)
    А в остальном все правильно.
    З.Ы.: а если добавить массиву третье измерение, как Вы поначалу предложили, то еще и switch не понадобится - снова сокращение объема кода и времени выполнения...
     
  8. NR55RU

    NR55RU Гик

    Да, вы правы, я просто учитывая то как человек написал свой первый вариант, сознательно постарался не мудрить, а наглядно показать логику что бы он мог поковырять и попробовать :)
     
  9. Zaic

    Zaic Нерд

    Всем большее спасибо за помощь. Но проблема осталась.
    На самом деле я показал кусок который пытался отладить с 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-я уже не влезает.
    Как правильно описывать такие массивы.
    Как правильно использовать указатели в таких случаях.
    Заранее большее спасибо.
     
  10. Megakoteyka

    Megakoteyka Оракул Модератор

    Вам уже ответили:
    И не нужно хранить в памяти кучу ненужных пробелов.
    Существуют функции для очистки экрана и для установки курсора в заданную позицию.
     
  11. Zaic

    Zaic Нерд

    Добрый вечер.
    Все подсказки помогли.
    Большее спасибо. Но вылезли другие проблемы.
    Памяти стало хватать. Но опять вылезла проблема с кодировкой. В тех строчках где есть русский текст вмести с текстом появляется белеберда. Как будто прихватывается чужая область памяти. С английским таких проблем нет.
     
    Последнее редактирование: 17 окт 2013
  12. Megakoteyka

    Megakoteyka Оракул Модератор

    Вы бы показали, что там вылазит, и код заодно...
     
  13. Zaic

    Zaic Нерд

    Проект уже сдали. К сожалению глубоко разбираться времени не было. Проблему с нехваткой 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 оказалась очень бедная. Отладка в слепую. Что внутри твориться непонятно. Сколько место занимает тоже.
    Может кто другую среду посоветует.
     
  14. NR55RU

    NR55RU Гик

    Программирование есть понимание. (с) Кристин Нюгард

    Если вы не понимаете что вы пишите, вам никакая среда не поможет.
    Если вы с первых месяцев думаете не о том что бы понять КАК писать а ГДЕ найти среду которая будет искать баги за вас, забейте на программирование.
     
    Megakoteyka нравится это.
  15. Megakoteyka

    Megakoteyka Оракул Модератор

    Может, сперва форум проглядите? Тут обсуждались и среды другие, и способы отладки "не вслепую", и еще много чего.
    Мои соболезнования заказчику. Хорошо, что Вы дома не строите. Мне было бы страшно в таком жить.