Редактор изображений для Arduino
Предыстория
Однажды мне захотелось создать очередную метеостанцию на Arduino. Да, вы правы, порой кажется, что ардуинщики только и делают, что создают метеостанции и мигают светодиодами.
Но моя новая метеостанция должна была быть написана на чистом Си без использования сторонних библиотек. Мне было интересно посмотреть, насколько это сложно сделать и как сократится размер прошивки для ATmega328P. Это означало, что мне пришлось погрузиться в спецификации подключаемых по I2C модулей и написать для них драйверы.
![]()
Одним из таких модулей, для которого я писал драйвер, был OLED-дисплей SSD1306. Про этот дисплей подробно писали на Хабре, поэтому не буду повторяться. Это достаточно популярный дисплей для вывода текстовой и графической информации.
Изображения в дисплей загружаются в формате X BitMap. Подготовить изображение можно в любом графическом редакторе, а потом специальной утилитой или веб-сайтом сконвертировать его в формат X BitMap.
Этот процесс показался мне не очень удобным и сложным для новичков. Мне хотелось подготавливать картинки в одном месте, хранить коллекцию своих монохромных изображений для OLED-дисплея и иметь возможность пересылать их друзьям. Не найдя подходящего редактора, я решил написать свое PWA-приложение.
В этой статье мы рассмотрим возможности редактора X BitMap-изображений под названием Bitmap Editor, загрузку изображения в Arduino-устройство и немного поговорим о шрифтах.
Проект создан в любительских целях, рассчитан на новичков и любителей Arduino. Возможно, он будет вам полезен. Также приглашаю вас поучаствовать в развитии проекта: поделиться своими идеями в issue или добавить новый функционал в редактор.
Создание нового изображения, панель рисования
Если вы пиксель-арт-художник, то, возможно, вам это понравится. Что может быть лучше пиксельной графики на монохромном дисплее?
Перейдите в Bitmap Editor.
Нажмите кнопку «Создать».
На странице заполните форму и нажмите кнопку «Сохранить».
Обратите внимание, что ширина изображения должна быть кратна 8 для корректного отображения на SSD1306 (а возможно, и на других моделях). Это обусловлено схемой кодирования, в которой каждый сегмент страницы хранит 8 ячеек памяти.
После создания изображения вы попадёте на страницу его редактирования.
Вы можете рисовать, используя правую кнопку мыши, инвертировать цвет, отменять свои действия, настраивать сетку.
![]()
Обратите внимание, что ваши правки сохраняются автоматически в локальном хранилище браузера.
Чтобы вернуться к списку ваших изображений, нажмите на логотип приложения.
После загрузки изображения в Arduino вы увидите на экране:
![]()
Создание изображения из картинки
Возможно, у вас уже есть картинка, которую вы хотели бы отобразить на OLED-дисплее?
Тогда вам нужно зайти в Bitmap Editor и нажать на кнопку «Импортировать» — «Из изображения».
В форме выберите файл вашего изображения.
Если ваша картинка выглядит не очень хорошо в монохромном виде, то вам необходимо настроить её с помощью ползунка «Чувствительность».
Изменить размер картинки можно с помощью значений в полях «Ширина» и «Высота».
Если вы хотите сделать размер изображения по контуру заполненных пикселей, то выберите «Обрезать».
Заполните форму и нажмите кнопку «Сохранить».
![]()
После загрузки изображения на Arduino вы увидите на экране:
![]()
Создание изображения из коллекции иконок
Подбирать картинки для интерфейса Arduino-приложения — задача не из лёгких и порой утомительная. Поэтому в редакторе есть большой набор готовых иконок, которые вы можете использовать в своём интерфейсе.
Перейдите в Bitmap Editor и нажмите кнопку «Импортировать» → «Из коллекции».
Выберите понравившуюся иконку, настройте и сохраните её.
Импорт/экспорт изображений
Как я уже писал выше, все ваши изображения хранятся в локальном хранилище вашего браузера.
А что если вы захотите поделиться с другом своими любимыми bitmap-картинками?
Для этого зайдите в Bitmap Editor и нажмите на иконку с дискетой у нужного элемента списка.
В появившемся диалоговом окне выберите изображения для экспорта. Они будут сохранены в JSON-файл, который вы сможете передать друзьям.
Чтобы импортировать bitmap-картинки из JSON-файла, на главной странице приложения нажмите «Импортировать» — «Из JSON».
Обратите внимание: если вы пытаетесь импортировать изображение, которое уже есть в вашем списке, то импорт этого изображения будет проигнорирован. Каждое изображение получает уникальный идентификатор при создании.
Загрузка изображения в Arduino
Итак, пришло время отобразить наши изображения на OLED-дисплее Arduino.
Схема подключения SSD1306 к Arduino UNO:
- GND (SSD1306) к GND (Arduino)
- VCC (SSD1306) к 5V (Arduino)
- SCL (SSD1306) к A5 (Arduino)
- SDA (SSD1306) к A4 (Arduino)
![]()
Заходим в Bitmap Editor, нажимаем на нужный элемент списка.
На странице редактирования изображения нажимаем кнопку «Экспорт в C».
![]()
В диалоговом окне настраиваем параметры экспорта.
Самое важное здесь — правильно указать «Порядок битов» в зависимости от используемой библиотеки OLED-дисплея: U8g2 или Adafruit.
![]()
Пример кода для U8g2:
// ssd1306_u8g2.ino
#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);
#define BITMAP_WIDTH 96
#define BITMAP_HEIGHT 64
static const unsigned char PROGMEM bitmap[] = { 0x0, 0x0, 0xff, 0x3f, 0x0, 0x0, 0x0, 0x0, 0xff, 0x3f, 0x0, 0x0, 0x0, 0xe0, 0xff, 0xff, 0x1, 0x0, 0x0, 0xe0, 0xff, 0xff, 0x1, 0x0, 0x0, 0xf8, 0xff, 0xff, 0xf, 0x0, 0x0, 0xf8, 0xff, 0xff, 0x7, 0x0, 0x0, 0xfe, 0xff, 0xff, 0x1f, 0x0, 0x0, 0xfe, 0xff, 0xff, 0x1f, 0x0, 0x0, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0xff, 0xff, 0xff, 0x3f, 0x0, 0x80, 0xff, 0xff, 0xff, 0xff, 0x0, 0x80, 0xff, 0xff, 0xff, 0xff, 0x0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x1, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x1, 0xf0, 0xff, 0xf, 0xfc, 0xff, 0x7, 0xf0, 0xff, 0xf, 0xfc, 0xff, 0x7, 0xf0, 0xff, 0x1, 0xc0, 0xff, 0xf, 0xf8, 0xff, 0x1, 0xe0, 0xff, 0x7, 0xf8, 0x7f, 0x0, 0x0, 0xff, 0x1f, 0xfc, 0x7f, 0x0, 0x80, 0xff, 0xf, 0xfc, 0x1f, 0x0, 0x0, 0xfc, 0x3f, 0xfe, 0x1f, 0x0, 0x0, 0xfe, 0x1f, 0xfc, 0xf, 0x0, 0x0, 0xf8, 0x7f, 0xff, 0xf, 0x0, 0x0, 0xfc, 0x1f, 0xfe, 0x7, 0x0, 0x0, 0xf0, 0x7f, 0xff, 0x7, 0x0, 0x0, 0xf8, 0x3f, 0xfe, 0x7, 0x0, 0x0, 0xe0, 0xff, 0xff, 0x3, 0xf0, 0x1, 0xf0, 0x3f, 0xfe, 0x3, 0x0, 0x0, 0xc0, 0xff, 0xff, 0x1, 0xf0, 0x1, 0xe0, 0x7f, 0xff, 0x3, 0x0, 0x0, 0x80, 0xff, 0xff, 0x0, 0xf0, 0x1, 0xc0, 0x7f, 0xff, 0x1, 0x0, 0x0, 0x80, 0xff, 0x7f, 0x0, 0xf0, 0x1, 0xc0, 0x7f, 0xff, 0x1, 0x0, 0x0, 0x0, 0xff, 0x7f, 0x0, 0xf0, 0x1, 0xc0, 0x7f, 0xff, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x3f, 0x80, 0xff, 0x3f, 0x80, 0x7f, 0xff, 0x80, 0xff, 0xff, 0x0, 0xfe, 0x3f, 0x80, 0xff, 0x3f, 0x80, 0x7f, 0xff, 0x80, 0xff, 0xff, 0x0, 0xfc, 0x1f, 0x80, 0xff, 0x3f, 0x80, 0x7f, 0xff, 0x80, 0xff, 0xff, 0x0, 0xfc, 0x1f, 0x80, 0xff, 0x3f, 0x80, 0x7f, 0xff, 0x80, 0xff, 0xff, 0x0, 0xfe, 0x1f, 0x80, 0xff, 0x3f, 0x80, 0x7f, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0x3f, 0x0, 0xf0, 0x1, 0xc0, 0x7f, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0x7f, 0x0, 0xf0, 0x1, 0xc0, 0x7f, 0xff, 0x1, 0x0, 0x0, 0x80, 0xff, 0x7f, 0x0, 0xf0, 0x1, 0xc0, 0x7f, 0xff, 0x1, 0x0, 0x0, 0xc0, 0xff, 0xff, 0x0, 0xf0, 0x1, 0xe0, 0x7f, 0xff, 0x3, 0x0, 0x0, 0xc0, 0xff, 0xff, 0x1, 0xf0, 0x1, 0xe0, 0x3f, 0xfe, 0x3, 0x0, 0x0, 0xe0, 0xff, 0xff, 0x3, 0x0, 0x0, 0xf0, 0x3f, 0xfe, 0x7, 0x0, 0x0, 0xf0, 0xff, 0xff, 0x7, 0x0, 0x0, 0xf8, 0x3f, 0xfe, 0xf, 0x0, 0x0, 0xf8, 0x3f, 0xff, 0xf, 0x0, 0x0, 0xf8, 0x1f, 0xfc, 0x1f, 0x0, 0x0, 0xfc, 0x3f, 0xfe, 0xf, 0x0, 0x0, 0xfc, 0x1f, 0xfc, 0x3f, 0x0, 0x0, 0xfe, 0x1f, 0xfe, 0x3f, 0x0, 0x0, 0xff, 0xf, 0xf8, 0xff, 0x0, 0x80, 0xff, 0xf, 0xfc, 0xff, 0x0, 0x80, 0xff, 0xf, 0xf8, 0xff, 0x3, 0xe0, 0xff, 0x7, 0xf8, 0xff, 0x3, 0xe0, 0xff, 0x7, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x3, 0xf0, 0xff, 0x3f, 0xfc, 0xff, 0x3, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x1, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x1, 0x80, 0xff, 0xff, 0xff, 0xff, 0x0, 0x80, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0xfe, 0xff, 0xff, 0x3f, 0x0, 0x0, 0xfe, 0xff, 0xff, 0x1f, 0x0, 0x0, 0xf8, 0xff, 0xff, 0xf, 0x0, 0x0, 0xf8, 0xff, 0xff, 0xf, 0x0, 0x0, 0xe0, 0xff, 0xff, 0x3, 0x0, 0x0, 0xe0, 0xff, 0xff, 0x3, 0x0, 0x0, 0x0, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x7, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x3, 0xff, 0xf1, 0x1f, 0x3c, 0x3c, 0xff, 0xe7, 0xe3, 0xe1, 0xf, 0xe0, 0x7, 0xff, 0xf3, 0x7f, 0x3c, 0x3c, 0xff, 0xe7, 0xe3, 0xf1, 0x1f, 0xf0, 0x7, 0xff, 0xf3, 0xff, 0x3c, 0x3c, 0xff, 0xe7, 0xe7, 0xf9, 0x3f, 0xf0, 0x7, 0xc7, 0xf7, 0xf8, 0x3c, 0x3c, 0xf8, 0xe0, 0xe7, 0x79, 0x3c, 0xf0, 0x7, 0xc7, 0xf7, 0xf0, 0x3d, 0x3c, 0xf8, 0xe0, 0xe7, 0x3d, 0x78, 0x78, 0xe, 0xc7, 0xf7, 0xe0, 0x3d, 0x3c, 0xf8, 0xe0, 0xef, 0x3d, 0x78, 0x78, 0xe, 0xff, 0xf3, 0xe0, 0x3d, 0x3c, 0xf8, 0xe0, 0xef, 0x3d, 0x78, 0x78, 0xe, 0xff, 0xf1, 0xe0, 0x3d, 0x3c, 0xf8, 0xe0, 0xff, 0x3d, 0x78, 0x7c, 0x1e, 0xff, 0xf0, 0xe0, 0x3d, 0x3c, 0xf8, 0xe0, 0xff, 0x3d, 0x78, 0xfc, 0x1f, 0xf7, 0xf1, 0xe0, 0x3d, 0x3c, 0xf8, 0xe0, 0xfd, 0x3d, 0x78, 0xfc, 0x1f, 0xe7, 0xf1, 0xe0, 0x3d, 0x3c, 0xf8, 0xe0, 0xfd, 0x3d, 0x78, 0xfc, 0x1f, 0xe7, 0xf3, 0xf0, 0x3c, 0x3c, 0xf8, 0xe0, 0xf9, 0x3d, 0x78, 0xfe, 0x3f, 0xc7, 0xf3, 0xfc, 0x7c, 0x3e, 0xf8, 0xe0, 0xf9, 0x79, 0x3c, 0x1e, 0x3c, 0xc7, 0xf7, 0x7f, 0xfc, 0x3f, 0xff, 0xe7, 0xf9, 0xf9, 0x3f, 0x1e, 0x7c, 0x87, 0xf7, 0x3f, 0xf0, 0x1f, 0xff, 0xe7, 0xf1, 0xf1, 0x1f, 0xe, 0x78, 0x87, 0xf7, 0xf, 0xe0, 0x7, 0xff, 0xe7, 0xf1, 0xe1, 0x7 };
void setup(void) {
if (!u8g2.begin()) {
Serial.println(F("SSD1306 allocation failed"));
for (;;) {
// Don't proceed, loop forever
}
};
u8g2.clearDisplay();
u8g2.drawXBMP(16, 0, BITMAP_WIDTH, BITMAP_HEIGHT, bitmap);
u8g2.sendBuffer();
}
void loop(void) {}
Пример кода для Adafruit:
// ssd1306_adafruit.ino
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <avr/pgmspace.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define BITMAP_WIDTH 96
#define BITMAP_HEIGHT 64
static const unsigned char PROGMEM bitmap[] = { 0x0, 0x0, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0x80, 0x0, 0x0, 0x7, 0xff, 0xff, 0x80, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xf8, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, 0x80, 0x3, 0xff, 0xff, 0xff, 0xff, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x7, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf, 0xff, 0xf0, 0x3f, 0xff, 0xe0, 0xf, 0xff, 0xf0, 0x3f, 0xff, 0xe0, 0xf, 0xff, 0x80, 0x3, 0xff, 0xf0, 0x1f, 0xff, 0x80, 0x7, 0xff, 0xe0, 0x1f, 0xfe, 0x0, 0x0, 0xff, 0xf8, 0x3f, 0xfe, 0x0, 0x1, 0xff, 0xf0, 0x3f, 0xf8, 0x0, 0x0, 0x3f, 0xfc, 0x7f, 0xf8, 0x0, 0x0, 0x7f, 0xf8, 0x3f, 0xf0, 0x0, 0x0, 0x1f, 0xfe, 0xff, 0xf0, 0x0, 0x0, 0x3f, 0xf8, 0x7f, 0xe0, 0x0, 0x0, 0xf, 0xfe, 0xff, 0xe0, 0x0, 0x0, 0x1f, 0xfc, 0x7f, 0xe0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xc0, 0xf, 0x80, 0xf, 0xfc, 0x7f, 0xc0, 0x0, 0x0, 0x3, 0xff, 0xff, 0x80, 0xf, 0x80, 0x7, 0xfe, 0xff, 0xc0, 0x0, 0x0, 0x1, 0xff, 0xff, 0x0, 0xf, 0x80, 0x3, 0xfe, 0xff, 0x80, 0x0, 0x0, 0x1, 0xff, 0xfe, 0x0, 0xf, 0x80, 0x3, 0xfe, 0xff, 0x80, 0x0, 0x0, 0x0, 0xff, 0xfe, 0x0, 0xf, 0x80, 0x3, 0xfe, 0xff, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfc, 0x1, 0xff, 0xfc, 0x1, 0xfe, 0xff, 0x1, 0xff, 0xff, 0x0, 0x7f, 0xfc, 0x1, 0xff, 0xfc, 0x1, 0xfe, 0xff, 0x1, 0xff, 0xff, 0x0, 0x3f, 0xf8, 0x1, 0xff, 0xfc, 0x1, 0xfe, 0xff, 0x1, 0xff, 0xff, 0x0, 0x3f, 0xf8, 0x1, 0xff, 0xfc, 0x1, 0xfe, 0xff, 0x1, 0xff, 0xff, 0x0, 0x7f, 0xf8, 0x1, 0xff, 0xfc, 0x1, 0xfe, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfc, 0x0, 0xf, 0x80, 0x3, 0xfe, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0x0, 0xf, 0x80, 0x3, 0xfe, 0xff, 0x80, 0x0, 0x0, 0x1, 0xff, 0xfe, 0x0, 0xf, 0x80, 0x3, 0xfe, 0xff, 0x80, 0x0, 0x0, 0x3, 0xff, 0xff, 0x0, 0xf, 0x80, 0x7, 0xfe, 0xff, 0xc0, 0x0, 0x0, 0x3, 0xff, 0xff, 0x80, 0xf, 0x80, 0x7, 0xfc, 0x7f, 0xc0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xc0, 0x0, 0x0, 0xf, 0xfc, 0x7f, 0xe0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x1f, 0xfc, 0x7f, 0xf0, 0x0, 0x0, 0x1f, 0xfc, 0xff, 0xf0, 0x0, 0x0, 0x1f, 0xf8, 0x3f, 0xf8, 0x0, 0x0, 0x3f, 0xfc, 0x7f, 0xf0, 0x0, 0x0, 0x3f, 0xf8, 0x3f, 0xfc, 0x0, 0x0, 0x7f, 0xf8, 0x7f, 0xfc, 0x0, 0x0, 0xff, 0xf0, 0x1f, 0xff, 0x0, 0x1, 0xff, 0xf0, 0x3f, 0xff, 0x0, 0x1, 0xff, 0xf0, 0x1f, 0xff, 0xc0, 0x7, 0xff, 0xe0, 0x1f, 0xff, 0xc0, 0x7, 0xff, 0xe0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf, 0xff, 0xfc, 0x3f, 0xff, 0xc0, 0x3, 0xff, 0xff, 0xff, 0xff, 0x80, 0x7, 0xff, 0xff, 0xff, 0xff, 0x80, 0x1, 0xff, 0xff, 0xff, 0xff, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xc0, 0xff, 0x8f, 0xf8, 0x3c, 0x3c, 0xff, 0xe7, 0xc7, 0x87, 0xf0, 0x7, 0xe0, 0xff, 0xcf, 0xfe, 0x3c, 0x3c, 0xff, 0xe7, 0xc7, 0x8f, 0xf8, 0xf, 0xe0, 0xff, 0xcf, 0xff, 0x3c, 0x3c, 0xff, 0xe7, 0xe7, 0x9f, 0xfc, 0xf, 0xe0, 0xe3, 0xef, 0x1f, 0x3c, 0x3c, 0x1f, 0x7, 0xe7, 0x9e, 0x3c, 0xf, 0xe0, 0xe3, 0xef, 0xf, 0xbc, 0x3c, 0x1f, 0x7, 0xe7, 0xbc, 0x1e, 0x1e, 0x70, 0xe3, 0xef, 0x7, 0xbc, 0x3c, 0x1f, 0x7, 0xf7, 0xbc, 0x1e, 0x1e, 0x70, 0xff, 0xcf, 0x7, 0xbc, 0x3c, 0x1f, 0x7, 0xf7, 0xbc, 0x1e, 0x1e, 0x70, 0xff, 0x8f, 0x7, 0xbc, 0x3c, 0x1f, 0x7, 0xff, 0xbc, 0x1e, 0x3e, 0x78, 0xff, 0xf, 0x7, 0xbc, 0x3c, 0x1f, 0x7, 0xff, 0xbc, 0x1e, 0x3f, 0xf8, 0xef, 0x8f, 0x7, 0xbc, 0x3c, 0x1f, 0x7, 0xbf, 0xbc, 0x1e, 0x3f, 0xf8, 0xe7, 0x8f, 0x7, 0xbc, 0x3c, 0x1f, 0x7, 0xbf, 0xbc, 0x1e, 0x3f, 0xf8, 0xe7, 0xcf, 0xf, 0x3c, 0x3c, 0x1f, 0x7, 0x9f, 0xbc, 0x1e, 0x7f, 0xfc, 0xe3, 0xcf, 0x3f, 0x3e, 0x7c, 0x1f, 0x7, 0x9f, 0x9e, 0x3c, 0x78, 0x3c, 0xe3, 0xef, 0xfe, 0x3f, 0xfc, 0xff, 0xe7, 0x9f, 0x9f, 0xfc, 0x78, 0x3e, 0xe1, 0xef, 0xfc, 0xf, 0xf8, 0xff, 0xe7, 0x8f, 0x8f, 0xf8, 0x70, 0x1e, 0xe1, 0xef, 0xf0, 0x7, 0xe0, 0xff, 0xe7, 0x8f, 0x87, 0xe0 };
void setup() {
Serial.begin(9600);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;) {
// Don't proceed, loop forever
}
}
display.clearDisplay();
display.drawBitmap(16, 0, bitmap, BITMAP_WIDTH, BITMAP_HEIGHT, SSD1306_WHITE);
display.display();
}
void loop() {}
После загрузки изображения в Arduino вы увидите на экране:
![]()
Работа со шрифтами
Как таковой работы со шрифтами в редакторе нет.
Но для метеостанции, которую я делал, очень нужно было отображать показания температуры и некоторые символы.
На самом деле дисплей SSD1306 не имеет встроенной поддержки шрифтов. Всё, что вы отображаете, — это bitmap-изображения.
Это значит, что и каждый символ шрифта — это маленькая bitmap-картинка, которая просто отображается в нужном месте дисплея.
Этот метод не очень подходит для работы с библиотеками U8g2 и Adafruit, так как у них своя система кодирования шрифтов. Разве что вы захотите отображать каждый символ отдельной картинкой.
Но в моем случае, поскольку я писал свой драйвер дисплея, я добавил к нему поддержку определяемых шрифтов.
Фокус в том, что из редактора можно выгрузить в код на Си не только целое изображение, но и его часть. Таким образом, мы можем собрать свой шрифт, выгружая нужные символы.
![]()
Для этого нужно открыть bitmap-изображение, выделить нужную область с помощью кнопки «Область» и нажать кнопку «Экспорт в C». Будет экспортирована только выделенная часть изображения.
![]()
Отображение данных на дисплее метеостанции:
![]()
Итоги
![]()
Работа над драйверами для метеостанции заслуживает отдельной статьи на Хабре. Она затянулась на продолжительное время и стала настоящим приключением.
Bitmap Editor помог мне завершить проект метеостанции на Arduino.
В дальнейшем я планирую развивать и улучшать его. Возможно, в какой-то из версий появится полноценная работа со шрифтами для Arduino-библиотек.
Присоединяйтесь к разработке проекта! Поддержите проект звёздами на GitHub.
Спасибо за прочтение и удачных вам самоделок на Arduino!
