Неустранимая ошибка Adafruit_SSD1306.cpp: pgmspace.h: нет такого файла или каталога с использованием SSD1306 на Arduino Nano RP2040

adafruit ssd1306 arduino-nano-rp2040

В настоящее время я пытаюсь заставить дисплей SBC-OLED01 работать под управлением моего Arduino Nano RP2040. Я использую официальный пример Adafruit, прикрепленный код.

/*************************************************** **********************************
Это пример для наших монохромных OLED-дисплеев на основе драйверов SSD1306.

Возьмите один сегодня в магазине Adafruit!
------> http://www.adafruit.com/category/63_98

Этот пример относится к дисплею с разрешением 128x64 пикселей, использующему I2C для связи.
Для интерфейса требуется 3 контакта (два I2C и один сброс).

Adafruit инвестирует время и ресурсы, предоставляя этот открытый
исходный код, пожалуйста, поддержите Adafruit и открытый исходный код
оборудование, покупая продукты у Adafruit!

Написано Лимором Фридом/Ладьядой для Adafruit Industries,
при участии сообщества открытого исходного кода.
Лицензия BSD, дополнительную информацию см. в файле license.txt.
Весь текст выше и заставка ниже должны быть
включены в любое перераспределение.
******************************************************* ************************/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // Ширина OLED-дисплея в пикселях
#define SCREEN_HEIGHT 64 // Высота OLED-дисплея в пикселях

// Объявление для дисплея SSD1306, подключенного к I2C (контакты SDA, SCL)
// Пины для I2C определяются Wire-библиотекой.
// На Arduino UNO: A4(SDA), A5(SCL)
// На Arduino MEGA 2560: 20(SDA), 21(SCL)
// На Arduino LEONARDO: 2(SDA), 3(SCL), ...
#define OLED_RESET     -1 // Номер вывода сброса (или -1, если общий вывод сброса Arduino)
#define SCREEN_ADDRESS 0x3C ///< См. спецификацию для адреса; 0x3D для 128x64, 0x3C для 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define NUMFLAKES     10 // Количество снежинок в примере анимации

#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16
static const unsigned char PROGMEM logo_bmp[] =
{ 0b00000000, 0b11000000,
  0b00000001, 0b11000000,
  0b00000001, 0b11000000,
  0b00000011, 0b11100000,
  0b11110011, 0b11100000,
  0b11111110, 0b11111000,
  0b01111110, 0b11111111,
  0b00110011, 0b10011111,
  0b00011111, 0b11111100,
  0b00001101, 0b01110000,
  0b00011011, 0b10100000,
  0b00111111, 0b11100000,
  0b00111111, 0b11110000,
  0b01111100, 0b11110000,
  0b01110000, 0b01110000,
  0b00000000, 0b00110000 };

void setup() {
  Serial.begin(9600);

  // SSD1306_SWITCHCAPVCC = генерировать внутреннее напряжение дисплея от 3,3 В
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Не продолжать, цикл навсегда
  }

  // Показать содержимое буфера начального отображения на экране --
  // библиотека инициализирует это с помощью экрана-заставки Adafruit.
  display.display();
  delay(2000); // Пауза на 2 секунды

  // Очистить буфер
  display.clearDisplay();

  // Рисуем один пиксель белым цветом
  display.drawPixel(10, 10, SSD1306_WHITE);

  // Показать буфер отображения на экране. Вы ДОЛЖНЫ вызывать display() после
  // команды рисования, чтобы сделать их видимыми на экране!
  display.display();
  delay(2000);
  // display.display() НЕ требуется после каждой отдельной команды рисования,
  // если это то, что вы хотите... скорее, вы можете собрать кучу
  // операции рисования, а затем сразу обновить весь экран, вызвав
  // дисплей.дисплей(). Эти примеры демонстрируют оба подхода...

  testdrawline();      // Рисуем много линий

  testdrawrect();      // Рисуем прямоугольники (контуры)

  testfillrect();      // Рисуем прямоугольники (заполненные)

  testdrawcircle();    // Рисуем круги (контуры)

  testfillcircle();    // Рисуем круги (заполненные)

  testdrawroundrect(); // Рисуем прямоугольники со скругленными углами (контуры)

  testfillroundrect(); // Рисуем прямоугольники со скругленными углами (заполненные)

  testdrawtriangle();  // Рисуем треугольники (контуры)

  testfilltriangle();  // Рисуем треугольники (закрашенные)

  testdrawchar();      // Рисуем символы шрифта по умолчанию

  testdrawstyles();    // Рисуем "стилизованные" символы

  testscrolltext();    // Рисуем прокручиваемый текст

  testdrawbitmap();    // Рисуем маленькое растровое изображение

  // Инвертировать и восстановить отображение с паузой между ними
  display.invertDisplay(true);
  delay(1000);
  display.invertDisplay(false);
  delay(1000);

  testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Анимация растровых изображений
}

void loop() {
}

void testdrawline() {
  int16_t i;

  display.clearDisplay(); // Очистить буфер дисплея

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
    display.display(); // Обновляем экран с каждой вновь нарисованной линией
    delay(1);
  }
  for(i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=display.width()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.height(); i+=4) {
    display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=0; i<display.width(); i+=4) {
    display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000); // Пауза на 2 секунды
}

void testdrawrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=2) {
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
    display.display(); // Обновляем экран с каждым вновь нарисованным прямоугольником
    delay(1);
  }

  delay(2000);
}

void testfillrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=3) {
    // Цвет INVERSE используется, поэтому прямоугольники чередуются белый/черный
    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
    display.display(); // Обновляем экран с каждым вновь нарисованным прямоугольником
    delay(1);
  }

  delay(2000);
}

void testdrawcircle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
    display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillcircle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
    // Используется ИНВЕРСНЫЙ цвет, поэтому круги чередуются белыми и черными
    display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
    display.display(); // Обновляем экран с каждым вновь нарисованным кругом
    delay(1);
  }

  delay(2000);
}

void testdrawroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    // Цвет INVERSE используется, поэтому круглые прямоугольники чередуются белый/черный
    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawtriangle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
    display.drawTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfilltriangle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
    // Используется инвертированный цвет, поэтому треугольники чередуются белыми и черными.
    display.fillTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawchar(void) {
  display.clearDisplay();

  display.setTextSize(1);      // Обычный масштаб пикселя 1:1
  display.setTextColor(SSD1306_WHITE); // Рисуем белый текст
  display.setCursor(0, 0);     // Начинаем с верхнего левого угла
  display.cp437(true);         // Использовать полный 256-символьный шрифт «Кодовая страница 437»

  // Не все символы поместятся на дисплее. Это нормально.
  // Библиотека нарисует то, что может, а остальное будет обрезано.
  for(int16_t i=0; i<256; i++) {
    if(i == '\n') display.write(' ');
    else          display.write(i);
  }

  display.display();
  delay(2000);
}

void testdrawstyles(void) {
  display.clearDisplay();

  display.setTextSize(1);             // Обычный масштаб пикселя 1:1
  display.setTextColor(SSD1306_WHITE);        // Рисуем белый текст
  display.setCursor(0,0);             // Начинаем с верхнего левого угла
  display.println(F("Hello, world!"));

  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Рисуем «инверсный» текст
  display.println(3.141592);

  display.setTextSize(2);             // Рисуем текст в масштабе 2X
  display.setTextColor(SSD1306_WHITE);
  display.print(F("0x")); display.println(0xDEADBEEF, HEX);

  display.display();
  delay(2000);
}

void testscrolltext(void) {
  display.clearDisplay();

  display.setTextSize(2); // Рисуем текст в масштабе 2X
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 0);
  display.println(F("scroll"));
  display.display();      // Показать исходный текст
  delay(100);

  // Прокрутка в разных направлениях с паузами между ними:
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
}

void testdrawbitmap(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - LOGO_WIDTH ) / 2,
    (display.height() - LOGO_HEIGHT) / 2,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();
  delay(1000);
}

#define XPOS   0 // индексирует массив 'icons' в функции ниже
#define YPOS   1
#define DELTAY 2

void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  int8_t f, icons[NUMFLAKES][3];

  // Инициализировать позиции «снежинки»
  for(f=0; f< NUMFLAKES; f++) {
    icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
    icons[f][YPOS]   = -LOGO_HEIGHT;
    icons[f][DELTAY] = random(1, 6);
    Serial.print(F("x: "));
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(F(" y: "));
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(F(" dy: "));
    Serial.println(icons[f][DELTAY], DEC);
  }

  for(;;) { // Цикл навсегда...
    display.clearDisplay(); // Очистить буфер отображения

    // Рисуем каждую снежинку:
    for(f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
    }

    display.display(); // Показать буфер отображения на экране
    delay(200);        // Пауза на 1/10 секунды

    // Затем обновляем координаты каждой чешуйки...
    for(f=0; f< NUMFLAKES; f++) {
      icons[f][YPOS] += icons[f][DELTAY];
      // Если снежинка находится за пределами нижней части экрана...
      if (icons[f][YPOS] >= display.height()) {
        // Повторная инициализация в случайном месте, чуть выше
        icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
        icons[f][YPOS]   = -LOGO_HEIGHT;
        icons[f][DELTAY] = random(1, 6);
      }
    }
  }
}

Я скачал оптимизированную библиотеку Adafruit GFX с github и установил ее, как описано. В качестве платы я использую Arduino Nano RP2040 из ОС Arduino Mbed версии 3.4.1.

Теперь, когда я компилирую код, я получаю следующую ошибку:

[...]Arduino\libraries\Adafruit_SSD1306\Adafruit_SSD1306.cpp:42:10: fatal error: pgmspace.h: No such file or directory
#include <pgmspace.h>
          ^~~~~~~~~~~~
compilation terminated.

exit status 1

Compilation error: exit status 1

К сожалению, я не нашел в сети решения, как решить проблему, поэтому сейчас написал этот вопрос. Я попробовал "нормальный" Библиотека GFX из менеджера пакетов вместо оптимизированной, с тем же результатом. Я предполагаю, что ошибка в библиотеке Adafruit_SSD1306, так что в любом случае это не имеет никакого значения.

, 👍2

Обсуждение

Первая запись, которая появилась у меня в Google, касается той же проблемы с другой библиотекой того же разработчика. См. [https://github.com/Bodmer/TFT_eSPI/issues/1148](https://github.com/Bodmer/TFT_eSPI/issues/1148). Обходной путь/решение здесь, по-видимому, состоит в том, чтобы закомментировать строку #include <pgmspace.h> в Adafruit_SSD1306.cpp., @StarCat

в Adafruit_SSD1306.cpp попробуйте удалить || определено (ARDUINO_ARCH_RP2040) в строке 41, которое, я думаю, было добавлено для «пикоядра», которое Adafruit предпочитает для своих плат RP2040., @Juraj


1 ответ


2

Происходит следующее: в включенной вами библиотеке есть другая библиотека: есть два решения: удалить #include pgmspace.h в одной из этих библиотек или просто получить pgmspace.h. Надеюсь, это поможет!

,