Помогите сэкономить память

Тема в разделе "Arduino & Shields", создана пользователем SEsin, 24 апр 2020.

  1. SEsin

    SEsin Нерд

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

    Код (C++):
    struct strSetCC {
      byte CC[4]; //Номера MIDI СС, соответствующие ручкам настройки, при выборе раздела настроек
      byte Res[4]; //Шаг ручки
      char* PotName[4]; //Названия ручек
    };

    strSetCC SetCC [10];
    Пользоваться этим мне очень удобно, т.к. можно очень просто задать и получить в цикле названия ручек управления: SetCC[Номер настройки].PotName[Номер ручки] = Имя; - очень удобно.

    Но занимает это все добро почти всю память контроллера. У меня названия ручек точно не будут более 4 символов. Поэтому я полагаю, что можно задать массив строк таким образом: char PotName[4][4];

    Но я не могу понять как с этим удобно работать. Или какую-то промежуточную функцию написать, чтобы можно было одной строкой по индексам задать значение? Или особо ужать char* PotName[4]; не получится?

    Буду рад любому совету, спасибо.
     
  2. parovoZZ

    parovoZZ Гуру

    И нафига этот чар вообще нужен, если с тем же успехом можно использовать указатель на байт???
     
  3. SEsin

    SEsin Нерд

    byte* PotName[4]; - так что ли? Это тоже будет массив строк?
     
  4. Daniil

    Daniil Гуру

    А можно пример того что вы храните в этой структуре?
     
  5. b707

    b707 Гуру

    то, что описано - занимает всего 160 байт. Что за контроллер у вас. что 160 байт это "почти вся память"?
     
  6. b707

    b707 Гуру

    этим вы не выиграете, а проиграете, размер структуры увеличится с16 до 24 байт
     
  7. SEsin

    SEsin Нерд

    Я храню там имена ручек настройки: SetCC[Номер настройки].PotName[Номер ручки] = Имя;
    SetCC - это массив структур.
     
  8. SEsin

    SEsin Нерд

    У меня Амперка Iskra nano Pro. Да, одна такая структура занимает не много. Но у меня массив из этих структур. И есть ещё другие массивы.
    Если приводить полный код объявления глобальных переменных, то вот он:
    Код (C++):
    struct strPot {
      byte analogInPin; //Номер Пина
      int ValAnalog; //Аналоговое значение потенциометра 1
      byte ValMIDI; //MIDI значение потенциометра 1. От 0 до 127
      byte PrValMIDI; //Предыдущее значение для устранения дребезга потенциометра
      byte CC; //Номер CC
      byte Res; //Точность/шаг значения
    };

    strPot Pot[3];

    struct strSetCC {
      byte CC[4]; //Номера СС, соответствующие ручкам настройки, при выборе раздела настроек
      byte Res[4]; //Шаг ручки
      char* PotName[4]; //Названия ручек
      //char PotName[4][4];
      byte ValName[4]; //Если 0, то выводится числовое значение, если больше - выводятся спец. названия
    };

    strSetCC SetCC [10];

    struct strValName {
      byte BorderVal[9]; //Граничное значение для этого имени
      char* Name[9]; //Названия этого значения Синус, Треугольник и т.д.
    };

    strValName ValName[3];
     
  9. b707

    b707 Гуру

    а вы точно понимаете разницу между
    Код (C++):
    char* PotName[4];
    и
    Код (C++):
    char PotName[4];
     
  10. b707

    b707 Гуру

    и что ? - меньше 250 байт в сумме...
     
  11. AlexU

    AlexU Гуру

    Таким образом сэкономите примерно 80 байт, которые тратились на хранение указателей. Вот только массив должен быть размером равным количеству символов + 1, т.е.:
    Код (C++):
    struct strSetCC {
      byte CC[4]; //Номера MIDI СС, соответствующие ручкам настройки, при выборе раздела настроек
      byte Res[4]; //Шаг ручки
      char PotName[4][5]; //Названия ручек, при условии что длина названия не более 4-х символов
    };
    Есть подозрение, что можно сэкономить гораздо больше памяти. Если есть не изменяемые в процессе работы прошивки данные, то их можно из оперативной памяти перенести в постоянную.
     
  12. parovoZZ

    parovoZZ Гуру

    а они потом куда-то выводятся?
     
  13. Daniil

    Daniil Гуру

    ну это не пример.
    Реальные данные какие? Может "имя" лучше хранить как число?
     
  14. SEsin

    SEsin Нерд

    На lcd дисплей выводятся. Я так понимаю, вы хотели предложить удалить переменные, если они никуда не выводятся или что это меняет? )
     
  15. SEsin

    SEsin Нерд

    Тогда вот пример:
    Код (C++):

      //     №№    CC Точность  Ручка    Значения
      iniSet(0,0,   16,   0,    "",       0);//
      iniSet(0,1,   77,   15,   "Wave",   1);//
      iniSet(0,2,   14,   0,    "Ctrl1",  0);//
      iniSet(0,3,   15,   0,    "Ctrl2",  0);//

    ...
    ...
    ...

    void iniSet(byte nSet,byte nCtrl , byte nCC, byte nRes, char* nName, byte nValName) {

      SetCC[nSet].CC[nCtrl] = nCC; SetCC[nSet].Res[nCtrl] = nRes; SetCC[nSet].PotName[nCtrl] = nName;   SetCC[nSet].ValName[nCtrl] = nValName;
    }
    Там все имена разные. 32 разновидности в разных комбинациях. Поэтому я их сохраняю в массиве и использую, ссылаясь на элемент массива по индексу.
     
  16. SEsin

    SEsin Нерд

    Да, это фактически не изменяемые данные. Это настройки, которые инициализируются при старте и далее мне нужно выводить на lcd экран названия в зависимости от выбранной настройки. Поясните пожалуйста, под постоянной памятью вы имеете ввиду работу с SD картой или что-то другое?
     
  17. parovoZZ

    parovoZZ Гуру

    тогда
     
  18. SEsin

    SEsin Нерд

    Все, понял, http://arduino.ru/Tutorial/Memory
    Ок, большое спасибо всем за ответы! Дальше, думаю, решу вопрос.
     
  19. AlexU

    AlexU Гуру

    Ну тогда их можно поместить во flash (см. PROGMEM в avr/pgmspace.h) и статически инициализировать в коде. Могут возникнуть проблемы с инициализацией строковых литералов -- при статической инициализации строковые литералы просто так во flash не переносятся. Если не справитесь, могу подсказать как это сделать.
     
  20. SEsin

    SEsin Нерд

    Уже переделал все через EEPROM. Все супер. Добился чего хотел. Благодарю за помощь.