ARDUINO Меню на LCD

edkotinsky

★✩✩✩✩✩✩
5 Мар 2021
19
17
22
Алматы
Пишу меню для LCD экрана, попутно изучая язык и Ардуино. Сейчас встрял, не врубаюсь в тему, на форумах похожего найти не могу. Прошу объяснений, что я делаю неправильно и как делать правильно, а также прошу сильно ногами меня не пинать - я начинающий...
Код прилагаю.
 

Вложения

  • 3.7 KB Просмотры: 31

Александр Симонов

★★★★✩✩✩
2 Авг 2018
727
207
Конкретней напиши, что ты пытаешься сделать, и что получается по факту. Только прям конкретно, не надо вот это вот "хочу сделать хорошо, а получается плохо. Что делать?"
 

edkotinsky

★✩✩✩✩✩✩
5 Мар 2021
19
17
22
Алматы
Насчет 100500 раз - не видел, но перед тем, как задавать вопросы, полистал. Интересно, надо разобраться, но конкретно тут проблема другая: код написан где-то на 4/10, и я столкнулся с проблемой передачи конструктору класса массива строк в PROGMEM:
MENU.ino:68:32: warning: invalid conversion from 'char' to 'const char*' [-fpermissive]
_pointNumber = (strlen_P(**namesMassive));

и передачи массива значений, ограничивающих значения, меняющиеся в пунктах:
MENU.ino:66:21: warning: invalid conversion from 'uint8_t {aka unsigned char}' to 'const uint8_t* {aka const unsigned char*}' [-fpermissive]

И вообще проблем в коде относительно много, он компилируется, но в результате работает криво:
pgmspace.h:1781:26: note: initializing argument 1 of 'size_t strlen_P(const char*)'
static __inline__ size_t strlen_P(const char *s) {


MENU.ino:69:38: warning: value computed is not used [-Wunused-value]
EEMEM pointVals[_pointNumber][3];


MENU.ino:205:69: warning: invalid conversion from 'uint8_t* {aka unsigned char*}' to 'char*' [-fpermissive]
strcpy_P(pointControl, pgm_read_byte(&(_pointControls[_leafer])));



Мне не нужно готовое решение, я хочу разобраться, что конкретно здесь не так, где я накосячил, и как это исправляется. Говорю же, я учусь.
 

poty

★★★★★★✩
19 Фев 2020
2,990
895
Вы очень сильно намудрили с кодом. Есть проблемы с пониманием указателей. Например,
C++:
const char* const menu_arrays[8] PROGMEM = { ... }

menuControl menu(menu_arrays, point_controls, 10000, LCD);

    menuControl //главный конструктор
    (const char* const* namesMassive,
    const uint8_t pointCtrls,
    uint32_t wakeTime,
    LiquidCrystal_I2C& objectLCD):
      _namesMassive(namesMassive),
      _pointControls(pointCtrls),
      _wakeTime(wakeTime),
      _LCD(objectLCD)
    {
      _pointNumber = (strlen_P(**namesMassive));
      EEMEM pointVals[_pointNumber][3];
    }
Что Вы хотели этим сказать?
C++:
#define PGM_P   const prog_char *
size_t strlen_P (PGM_P) __ATTR_CONST_
Первая ошибка здесь то, что Вы не можете обращаться к программной памяти напрямую, только через соответствующие функции, которые не поддерживают тип "указатели". menu_arrays у Вас находится в программной памяти, а Вы пытаетесь сделать его разадресацию для передачи в strlen_P. Здесь нужно вводить временный указатель в памяти данных, копировать функциями memcpy_P в этот указатель значение, а потом уже его разадресовывать.
Сама разадресация сделана также неверно: передавать нужно адрес строки в программной памяти, а не первый байт первой строки.
 
Изменено:
  • Лойс +1
Реакции: edkotinsky

edkotinsky

★✩✩✩✩✩✩
5 Мар 2021
19
17
22
Алматы
Спасибо всем ответившим, ибо вы натолкнули меня на мысль, что в таком виде ничего путного у меня не получится. Лучше, если упаковать эти значения (константы для constrain'ов вводимых значений и названия пунктов) в массив структур. Удобнее получается, и передавать проще.
Нашел пару источников по теме.

Буду писать и думать. На этом мои злоключения приключения, наверное, только начинаются...
 

edkotinsky

★✩✩✩✩✩✩
5 Мар 2021
19
17
22
Алматы
Так, я думаю, что раз есть две темы в разных разделах, то можно это и использовать. Эта тема - черновая, здесь я буду тупить, учиться и задавать вопросы, а там - выкладывать готовые результаты.

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

Как избавиться от предупреждения компилятора о не инициализированных константных массивах-адресах EEPROM? Мелочь, но неприятно.
menuLCD.h:24:21: warning: uninitialized const 'pointVals0' [-fpermissive] const uint8_t EEMEM pointVals0[MENU_points];

И самое главное, почему ничего не работает - непонятная мне ошибка: неопределенное обращение. Как так? Ведь по сути все то же самое, только разделенное на .h и .cpp файлы, и уже куча проблем, может, есть какие-то тонкости в этой теме?
undefined reference to `void menuControl::mainDisplay<char const*, char const*, char const*>(char const*, char const*, char const*)'
 

bort707

★★★★★★✩
21 Сен 2020
2,895
860
непонятная мне ошибка: неопределенное обращение. Как так? Ведь по сути все то же самое, только разделенное на .h и .cpp файлы, и уже куча проблем, может, есть какие-то тонкости в этой теме?
код целиком не видел, ибо с телефона, но судя по сообщению об ошибке, используется шаблон класса? Тогда тут и правда есть нюансы. У шаблонных функций нельзя просто так разделить обьявление и описание между .h .cpp файлами, так как компилятору надо знать заранее все варианты создания шаблона, а при разделении эта информация теряется. Можно поместить все касающееся шаблона, в один .h файл, но это может вызвать свои проблемы, например ошибки с повторным описанием, если этот .h файл включен более чем в один модуль.
В общем, тут и правда много "тонкостей" , лучше вам какой-то хороший учебник почитать
 
  • Лойс +1
Реакции: edkotinsky

edkotinsky

★✩✩✩✩✩✩
5 Мар 2021
19
17
22
Алматы
Да, вы правы. Но описывать функции в .h файле, когда есть еще .cpp файл, насколько я знаю, нельзя - будет ошибка. В общем, я перенес все описание в один .h файл, и - hallelujah! - все заработало.

Кстати, в хороших учебниках я не нашел (либо плохо искал, либо не в тех учебниках), зато нашел вот такую тему:
https://www.cyberforum.ru/cpp-beginners/thread1284270.html

Код прилагаю. Хочу узнать - нет ли другого способа поделить объявление и описание? Пробовал положить в другой .h файл - та же хрень. Прошу посоветовать по теме хорошие учебники, потому что информации как-то слишком мало.
 

Вложения