Как правильно поместить дескриптор u8g2 в класс

programming class oled u8glib object-oriented

Я пытаюсь создать небольшой будильник с батарейным питанием, используя Arduino MKRZero и универсальный OLED-дисплей с разрешением 128x64 пикселей, управляемый SH1106.

Я начал просто сбрасывать весь код в один файл с именем Clock.ino. По мере того как код становился больше, я начал разбивать функциональность на отдельные классы. Это прекрасно подходило для хронометража и сигнализации, но когда я попытался сделать то же самое для функциональности дисплея, я столкнулся с проблемой.

Теперь я хотел разделить свой код отображения на отдельный класс. Рабочий код перед рефакторингом выглядит примерно так:

Clock.ino

//Display stuff
#include <U8x8lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);

void setup(void) {
  u8x8.begin();
}

void print_clock([...]) {
  [...]
  u8x8.setCursor(0,3);
  u8x8.print("23:59:59");
  [...]
}

void loop(void) {
  [...]

  // Main clock
  print_clock(clk.datetime);

  [...]
}

Я попытался разделить его следующим образом:

Clock.ino

#include "Display.h"

Display disp;

void setup(void) {}

void loop(void) {
  [...]

  // Main clock
  disp.print_clock([...]);

  [...]
}

Display.cpp

#include "Display.h"

Display::Display() {
  this->u8x8.begin();
}

void Display::print_clock([...]) {
  [...]
  this->u8x8.setCursor(0,3);
  this->u8x8.print("23:59:59");
  [...]
}

Дисплей.h

//Display stuff
#include <U8x8lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif

class Display {
  public:
    Display();
    void print_clock([...]);
  private: 
    U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
} 

Это не сработало, выдало мне целый список ошибок, все похожие на эти:

  5 In file included from /home/simon/Arduino/libraries/U8g2/src/U8x8lib.h:45:0,                          
  6                  from sketch/Display.h:9,                                                             
  7                  from sketch/Display.cpp:1:                                                           
  8 /home/simon/Arduino/libraries/U8g2/src/clib/u8x8.h:323:23: error: expected identifier before numeric c    \>onstant                                                                                             
  9  #define U8X8_PIN_NONE 255                                                                            
 10                        ^                                                                              
 11 sketch/Display.h:26:55: note: in expansion of macro 'U8X8_PIN_NONE'                                   
 12      U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);                                
 13                                                        ^~~~~~~~~~~~~                                  
 14 /home/simon/Arduino/libraries/U8g2/src/clib/u8x8.h:323:23: error: expected ',' or '...' before numeric    \> constant                                                                                           
 15  #define U8X8_PIN_NONE 255                                                                            
 16                        ^                                                                              
 17 sketch/Display.h:26:55: note: in expansion of macro 'U8X8_PIN_NONE'                                   
 18      U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);                                
 19                                                        ^~~~~~~~~~~~~                                  
 20 sketch/Display.cpp: In constructor 'Display::Display()':                                              
 21 Display.cpp:8:9: error: invalid use of member function 'U8X8_SH1106_128X64_NONAME_HW_I2C Display::u8x8    \>(int)' (did you forget the '()' ?)                                                                  
 22    this->u8x8.begin();                                                                                
 23    ~~~~~~^~~~                 

Поэтому я попытался переписать его таким образом, чтобы u8xu var был глобальным, как это было раньше, определив его в Display.cpp и избавляюсь от этого->> до того, как u8x8. вызовет метод на дисплее:: методы. Это тоже не сработало. Он компилируется, но мой дисплей остается пустым, и arduino застревает (больше не взаимодействует с последовательным интерфейсом, пока я его не сброшу).

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

итак, главный вопрос: как создать экземпляр объекта внутри моего класса, чтобы он стал доступным в качестве частной переменной?

Если кто-то хочет ознакомиться с полным кодом, он находится прямо здесь: https://github.com/ffective/wake-up/tree/master/Clock

Последняя фиксация-это способ разделения, который я описал последним: использование глобальной переменной. Предыдущая фиксация-это рабочий код со всеми методами отображения только в глобальном масштабе в Clock.ino. К сожалению, я не сохранил свои попытки поместить его в качестве частной переменной.

, 👍-1

Обсуждение

То, что вы получили, - это объявление метода, а не определение переменной-члена. u8x8-это частный метод, возвращающий U8X8_SH1106_128X64_NONAME_HW_I2C. И он терпит неудачу на этой константе в списке параметров., @KIIV


2 ответа


0

Вам нужно создать "пустой" объект в своем классе, а затем создать его экземпляр в списке инициализаторов конструктора:

class Display { 
    private: 
        U8X8_SH1106_128X64_NONAME_HW_I2C u8x8;

    public: 
        Display() : u8x8(U8X8_PIN_NONE) {} 
        void print_clock([...]); 
};

Частный объект не создается до тех пор, пока конструктор не будет вызван вызовом конструктора Display ().

С этого момента вы можете использовать u8x8.whatever (), как обычно.

,

Также можно использовать U8X8_SH1106_128X64_NONAME_HW_I2C u8x8 { U8X8_PIN_NONE }; и ему не нужно использовать список инициализаторов в конструкторе по умолчанию. Здесь важно использовать {} вместо ()., @KIIV


0

Первые ошибки не очень полезны, но последняя, касающаяся функции-члена, объясняет все это. Вы не создаете переменную-член этого типа, вы пытаетесь создать функцию-член (со списком недопустимых параметров), которая возвращает значение U8X8_SH1106_128X64_NONAME_HW_I2C.

Этот код совершенно действителен:

class Display {
  public:
    Display() { u8x8.begin(); }

    // вы также можете использовать другой инициализатор для объекта u8x8 (по умолчанию в этом случае он никогда не выполняется): 
    Display(uint8_t resetPin) : u8x8{resetPin} { u8x8.begin(); } 

  private:
    U8X8_SH1106_128X64_NONAME_HW_I2C u8x8 { U8X8_PIN_NONE };
};

и в скетче:

// создание экземпляра:
Display disp{ 5 };

// или с конструктором по умолчанию и сбросом значения вывода
Display disp2;
,