Несколько дисплеев в классах

Вы начали использовать динамическое выделение памяти. Это значит, что контроль за свободной памятью у вас теперь чуть сложнее. Если раньше (при статическом объявлении дисплеев) вы при компиляции видели, сколько у вас осталось, то теперь эта информация недостоверна. Очередной new может и не получиться.

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

Программа по управлению беговой дорожкой получилась не большая.Возможно такой проблемы не произойдет.

Скетч использует 5874 байт (19%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 290 байт (14%) динамической памяти, оставляя 1758 байт для локальных переменных. Максимум: 2048 байт.

Если не сложно дайте ссылку на книгу. До этого читал кое что для начинающих там об этом ( заменить точку на стрелку) не было.

Да их миллион, в зависимости от Ваших хотелок.

Вот, классика – https://www.ozon.ru/product/yazyk-programmirovaniya-c-4-e-izdanie-straustrup-bern-486936359/

Сейчас вот эту хвалят – https://www.ozon.ru/product/izuchaem-c-cherez-programmirovanie-igr-knigi-po-programmirovaniyu-douson-maykl-211432260

Есть ещё (сколько там от миллиона осталось …) 999998 разных.

1 лайк

Как-то начинал на Action-script, даже деньги получалось зарабатывать на этом.
Потом познакомился с ЦПП плюс, языки высокого уровня стали непонятны совершенно, как так?

Спасибо. Пока скачал в пдф.

Попробуй так. Это минимальный код, без проверок, все в public области. Заработает - добавишь проверки. Не знаешь какте - спроси тут.

Обрати внимание на то, как и где определен “lcd”, когда он создается и когда удаляется. К тому же ты забыл init() :-/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

class Cla {
  public:
    LiquidCrystal_I2C *lcd;

    Cla(byte adr) {
      lcd = new LiquidCrystal_I2C(adr, 16, 2);
      lcd->init();       // Initialize LCD
      lcd->backlight();
    }

    ~Cla() {
      if (lcd) {
        delete lcd;      
      }
    }

    void prin() {
      lcd->print("Hello, world!");
    }
};

Cla displ_1(0x3F);
Cla displ_2(0x27);

void setup() {
  displ_1.prin();
  displ_2.prin();
}

void loop() {
}

Вот и отлично. А то Ваши ошибки они же не такие, что “прям ошибки” – просто абсолютное незнание языка. Вот, смотрите, аналогия какая … как-то в китайском магазине на озоне увидел

вот такое описание воронки с широким горлом

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

Вот неучи! Правильно писать: - Для банков и крупных горлышков!

5 лайков

Эти примитивные дисплеи тоже не работают группой в рамках ходовых библиотек?

Ну, да. Не очень они красивенькие.
…интересно, чем у Ирины сердце успокоилось?

Если ты считаешь, что увлекаешься музыкой, но т.к. не являешься в этой области профессионалом, то тебе достаточно всего двух нот, не удивляйся, что тебя никто не хочет слушать.
И еще:

Хобби - это то, что никто не заставляет делать, а делается исключительно для собственного удовольствия.
Позволю себе процитировать Понтрягина:
Только качественно выполненная работа доставляет удовольствие.
Другими словами, халтура никак не может быть хобби.

О том и речь: Вам только что намекнули, что эта диагностика для динамического выделения памяти не соответствует действительности.
То есть опять халтура по принципу “и так сойдет”.
Какое же это хобби?

Вот это замечание нуждается в комментарии.
В системе Ардуино не зря широко применяются методы init(), begin() и им подобные вместо того, чтобы использовать конструктор класса. Это не случайно.
Дело в том, что инициализация всех статических переменных происходит до выполнения первого оператора программы. При этом, как известно, название программы на Си предопределено: main(). Но в Ардуино ее не видно. А она есть!
Для разных МК она различается, но в общем имеет примерно следующую структуру:

int main(void) {
    system_init();
    setup();
    for(;;) {
        loop();
        system_loop();
    }
}

То есть первый выполняемый оператор находится в блоке system_init() и настраивает “железо” МК для работы в системе Ардуино.
Но код конструктора статического класса выполняется до инициализации “железа” МК. Поэтому его работоспособность зависит от того, используются ли в конструкторе класса какие-либо обращения к системным функциям Ардуино.
Соответственно, если это так, инициализацию внешнего “железа” следует вынести из конструктора класса в отдельный метод init(), вызываемый из setup().
Наличие метода init() в классе LiquidCrystal_I2C как бы само по себе намекает на наличие такой зависимости.
Поэтому и вызывать метод init() любого постороннего из конструктора собственного класса не следует. Во избежание трудно отлавливаемых ошибок.

5 лайков

Имеется в виду так ?

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

class Display {
private:
    LiquidCrystal_I2C lcd;
    byte address;
    bool initialized = false;

public:
    Display(byte adr) : address(adr), lcd(adr, 16, 2) {
    }

    void init() {
        lcd.init();         
        lcd.backlight(); 
        initialized = true;
    }

    void printMessage() {
        if (initialized) {
            lcd.print("Hello, world!");
        }
    }
};

Display displ_1(0x3F);
Display displ_2(0x27);

void setup() {
    displ_1.init();
    displ_2.init();
    
    displ_1.printMessage();
    displ_2.printMessage();
}

void loop() {
}
1 лайк

Я бы сказал, “можно, если понимаешь, что делаешь”.