Как работать с массивом из нескольких объектов microLED?

thelookin

✩✩✩✩✩✩✩
20 Фев 2023
4
1
Добрый день. Я новичок в Ардуино и в С++. И я не могу понять – как мне сделать массив из нескольких объектов типа MicroLED. То есть у меня 6 лент подключены на разные пины, и мне нужно в зависимости от ID работать с определенной лентой.

C++:
microLED < NUMLEDS, STRIP1_PIN, -1, LED_WS2812, ORDER_GRB > strip1;
microLED < NUMLEDS, STRIP2_PIN, -1, LED_WS2812, ORDER_GRB > strip2;
microLED < NUMLEDS, STRIP3_PIN, -1, LED_WS2812, ORDER_GRB > strip3;
microLED < NUMLEDS, STRIP4_PIN, -1, LED_WS2812, ORDER_GRB > strip4;
microLED < NUMLEDS, STRIP5_PIN, -1, LED_WS2812, ORDER_GRB > strip5;
microLED < NUMLEDS, STRIP6_PIN, -1, LED_WS2812, ORDER_GRB > strip6;

microLED strips[6];

void enableStrip(stripID) {
  strip[stripID].clear();
  strip[stripID].fill(mRGB(c1, c2, c3));
  strip[stripID].show();
}
Как мне можно реализовать что то подобное?
 

rkit

★★★✩✩✩✩
5 Фев 2021
508
127
Нет типа "microLED", есть тип "microLED < NUMLEDS, STRIP1_PIN, -1, LED_WS2812, ORDER_GRB >".
Все твои объекты имеют разные типы. Бери другую библиотеку, эта плохо спроектирована.
 
  • Лойс +1
Реакции: thelookin

Геннадий П

★★★★★★✩
14 Апр 2021
1,969
632
44
Скорее всего можно, гуглите про указатели, ссылки. Но это не для новичков.
 

bort707

★★★★★★✩
21 Сен 2020
3,062
912
@Геннадий П, вот даже не уверен.
На эти обьекты и ссылки в один массив не положить, поскольку из шаблона получаются разные классы. Даже если у этих лассов есть общий предок - то как их потом приводить по типу к конкретному экземпляру? - все равно выходит надо каждый экземпляр обрабатывать отдельно? - зачем тогда массив?
 
  • Лойс +1
Реакции: thelookin

thelookin

✩✩✩✩✩✩✩
20 Фев 2023
4
1
Я так понял перебором в функции с возвратом класса эту проблему тоже не решить?

Тогда может посоветуете библиотеку, которую я могу использовать как массив? Потому что я конечно могу написать портянку в 6 раз больше, но как то это не по феншую (

FastLED подойдет?
 

Сотнег

★★★★★★★
15 Янв 2020
4,364
1,494

@thelookin, а зачем вам такой массив?

Да и сажать фрагменты ленты на разные пины - тоже сомнительное решение.

Только ради strip.fill() такой огород городить не стоит.
Яркость разных фрагментов собираетесь по-отдельности регулировать?
 
Изменено:

thelookin

✩✩✩✩✩✩✩
20 Фев 2023
4
1
@Сотнег,
1. Гибкое управление отдельными лентами (включить, выключить, задать цвет, определенные эффекты). Без массива придется каждый кусок кода дублировать 6 раз.

2. Так архитектурно задумано. Опять таки для гибкости системы.Одна лента - один блок с дополнительными датчиками и своим адресом. Вышел из строя блок - просто воткнул другой без всякой пайки.
 

Boroda22

★✩✩✩✩✩✩
23 Фев 2022
251
42
Даже если у этих лассов есть общий предок - то как их потом приводить по типу к конкретному экземпляру? - все равно выходит надо каждый экземпляр обрабатывать отдельно?
Очень даже просто, у предка должен быть виртуальный метод, реализация которого ложится на плечи дочернего. Можно объявить массив родительского типа, тогда элементы вполне могут быть "разными". Такие задачи не для новичков, и нужно хорошо ориентироваться в ООП.
Потому что я конечно могу написать портянку в 6 раз больше, но как то это не по феншую (
Поэтому пишется своя библиотека с необходимым функционалом.
 

bort707

★★★★★★✩
21 Сен 2020
3,062
912
Тогда может посоветуете библиотеку
Фастлед или Неопиксель.
Использовать поделку гайвера имеет смысл только в одном случае - если вы пытаетесь управлять длинной лентой контроллером с малой памятью, например Нано/Уно.
Если проблем с памятью нет, берите нормальные библиотеки.
 
  • Лойс +1
Реакции: thelookin

thelookin

✩✩✩✩✩✩✩
20 Фев 2023
4
1
Понял, спасибо.

С текущей библиотекой тогда не стал заморачиваться с массивами. Сделал так:
C++:
void enableLED(int strip_id, int c1, int c2, int c3) {
  switch (strip_id) {
    case 1:
      strip1.clear();
      strip1.fill(mRGB(c1, c2, c3));
      strip1.show();
      break;
    case 2:
      strip2.clear();
      strip2.fill(mRGB(c1, c2, c3));
      strip2.show();
      break;
    case 3:
      strip3.clear();
      strip3.fill(mRGB(c1, c2, c3));
      strip3.show();
      break;
    case 4:
      strip4.clear();
      strip4.fill(mRGB(c1, c2, c3));
      strip4.show();
      break;
    case 5:
      strip5.clear();
      strip5.fill(mRGB(c1, c2, c3));
      strip5.show();
      break;
    case 6:
      strip6.clear();
      strip6.fill(mRGB(c1, c2, c3));
      strip6.show();
      break;
  }
 
}

void disableLED(int strip_id) {
  switch (strip_id) {
    case 1:
      strip1.clear();
      strip1.fill(mBlack);
      strip1.show();
      break;
    case 2:
      strip2.clear();
      strip2.fill(mBlack);
      strip2.show();
      break;
    case 3:
      strip3.clear();
      strip3.fill(mBlack);
      strip3.show();
      break;
    case 4:
      strip4.clear();
      strip4.fill(mBlack);
      strip4.show();
      break;
    case 5:
      strip5.clear();
      strip5.fill(mBlack);
      strip5.show();
      break;
    case 6:
      strip6.clear();
      strip6.fill(mBlack);
      strip6.show();
      break;
  }
}
Но нашел, что с массивами можно легко работать в FastLED - https://github.com/FastLED/FastLED/tree/master/examples/Multiple/ArrayOfLedArrays
 
  • Лойс +1
Реакции: Сотнег

Kir

★✩✩✩✩✩✩
28 Мар 2020
69
16
@thelookin,

для того чтобы сформировать массив объектов, они должны быть одного типа. В вашем случае все экземпляры разного типа.
Для этого нужно привести все экземпляры к одному типу, и для этого необходимо сформировать интерфейс, которым будут обладать все экземпляры, и реализацию, которая будет по сути просто оберткой над уже существующим шаблонным типом, например вот так:
C++:
class microLed_IFace {
public:
    virtual void set(int n, mData color) = 0;                    // ставим цвет светодиода mData (равносильно leds[n] = color)                   
    virtual mData get(int num) = 0;                                // получить цвет диода в mData (равносильно leds[n])
    virtual void fill(mData color) = 0;                            // заливка цветом mData
    virtual void fill(int from, int to, mData color) = 0;        // заливка цветом mData
    virtual void fillGradient(int from, int to, mData color1, mData color2) = 0;    // залить градиентом двух цветов
    virtual void fade(int num, byte val) = 0;                    // уменьшить яркость
    
    // матрица
    virtual uint16_t getPixNumber(int x, int y) = 0;            // получить номер пикселя в ленте по координатам
    virtual void set(int x, int y, mData color) = 0;            // ставим цвет пикселя x y в mData
    virtual mData get(int x, int y) = 0;                        // получить цвет пикселя в mData
    virtual void fade(int x, int y, byte val) = 0;                // уменьшить яркость
    virtual void drawBitmap8(int X, int Y, const uint8_t *frame, int width, int height) = 0;    // вывод битмапа (битмап 1мерный PROGMEM)
    virtual void drawBitmap16(int X, int Y, const uint16_t *frame, int width, int height) = 0;    // вывод битмапа (битмап 1мерный PROGMEM)
    virtual void drawBitmap32(int X, int Y, const uint32_t *frame, int width, int height) = 0;    // вывод битмапа (битмап 1мерный PROGMEM)
    
    // общее
    virtual void setMaxCurrent(int ma) = 0;                        // установить максимальный ток (автокоррекция яркости). 0 - выключено
    virtual void setBrightness(uint8_t newBright) = 0;            // яркость 0-255
    virtual void clear() = 0;                                    // очистка
    
    // вывод буфера
    virtual void show() = 0;                                    // вывести весь буфер
    
    // вывод потока
    virtual void begin() = 0;                                    // начать вывод потоком
    virtual void send(mData data) = 0;                            // отправить один светодиод
    virtual void end() = 0;   
    
    virtual ~microLed_IFace() {}
};


template<int amount, int8_t pin, int8_t pinCLK, M_chip chip, M_order order, M_ISR isr = CLI_OFF, uint8_t uptime = 0>
class wrapperMicroLed : public microLed_IFace {
public:
    void set(int n, mData color)                                                    {        leds.set(n, color);                          }
    mData get(int num)                                                              { return leds.get(num);                               }
    void fill(mData color)                                                          {        leds.fill(color);                            }
    void fill(int from, int to, mData color)                                        {        leds.fill(from, to, color);                  }
    void fillGradient(int from, int to, mData color1, mData color2)                 {        leds.fillGradient(from, to, color1, color2); }
    void fade(int num, byte val)                                                    {        leds.fade(num, val);                         }
    
    // матрица
    uint16_t getPixNumber(int x, int y)                                             { return leds.getPixNumber(x, y);                       }
    void set(int x, int y, mData color)                                             {        leds.set(x, y, color);                         }
    mData get(int x, int y)                                                         { return leds.get(x, y);                                }
    void fade(int x, int y, byte val)                                               {        leds.fade(x, y, val);                          }
    void drawBitmap8(int X, int Y, const uint8_t *frame, int width, int height)     {        leds.drawBitmap8 (X, Y, frame, width, height); }
    void drawBitmap16(int X, int Y, const uint16_t *frame, int width, int height)   {        leds.drawBitmap16(X, Y, frame, width, height); }
    void drawBitmap32(int X, int Y, const uint32_t *frame, int width, int height)   {        leds.drawBitmap32(X, Y, frame, width, height); }
    
    // общее
    void setMaxCurrent(int ma)                                                      {        leds.setMaxCurrent(ma);        }
    void setBrightness(uint8_t newBright)                                           {        leds.setBrightness(newBright); }
    void clear()                                                                    {        leds.clear();                  }
    
    // вывод буфера
    void show()                                                                     {        leds.show(); }
    
    // вывод потока
    void begin()                                                                    {        leds.begin();    }
    void send(mData data)                                                           {        leds.send(data); }
    void end()                                                                      {        leds.end();      }
    
    virtual ~wrapperMicroLed() {}

    wrapperMicroLed() : leds(microLED<amount, pin, pinCLK, chip, order, isr, uptime>()) { }

private:
    microLED<amount, pin, pinCLK, chip, order, isr, uptime> leds;
};
Тогда можно будет обращаться экземплярам через абстрактный интерфейс.

C++:
wrapperMicroLed < NUMLEDS, STRIP1_PIN, -1, LED_WS2812, ORDER_GRB > strip1;
wrapperMicroLed < NUMLEDS, STRIP2_PIN, -1, LED_WS2812, ORDER_GRB > strip2;
wrapperMicroLed < NUMLEDS, STRIP3_PIN, -1, LED_WS2812, ORDER_GRB > strip3;
wrapperMicroLed < NUMLEDS, STRIP4_PIN, -1, LED_WS2812, ORDER_GRB > strip4;
wrapperMicroLed < NUMLEDS, STRIP5_PIN, -1, LED_WS2812, ORDER_GRB > strip5;
wrapperMicroLed < NUMLEDS, STRIP6_PIN, -1, LED_WS2812, ORDER_GRB > strip6;

microLed_IFace* const strips[6] = {
   strip1 ,strip2 ,strip3 ,strip4 ,strip5 ,strip6
};

void enableStrip(stripID) {
  strip[stripID]->clear();
  strip[stripID]->fill(mRGB(c1, c2, c3));
  strip[stripID]->show();
}
 
  • Лойс +1
Реакции: thelookin

Boroda22

★✩✩✩✩✩✩
23 Фев 2022
251
42
Для этого нужно привести все экземпляры к одному типу
Учите ООП, молодой человек, особенно-полиморфизм. C++ допускает множественное наследование, в отличие от C#(там интерфейсы рулят). Перечитал еще раз ваше ссобщение, вполне годно, извиняйте😊
 
Изменено: