ARDUINO Вывод картинки через spi

автобус

✩✩✩✩✩✩✩
7 Июн 2025
3
0
Привет! Это мой первый проект, решил сделать фоторамку на которой будут крутиться картинки. Начать решил с простого - у меня есть 160 на 128 tft экран на st7735, модуль для чтения карты памяти и Ардуино нано (тут не уверен что это именно Ардуино, но работать с ней у меня получается).
Вот так выглядит вся моя конструкция
IMG_20250607_160638.jpg

Вроде подключил правильно - и дисплей и карта памяти по отдельности работают.
А вот чтобы работало все вместе и картинка из карты памяти выводилась на дисплейчик у меня не вышло. Выводится всякий мусор
IMG_20250607_160743.jpg

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

Мои попытки вывести картинку:
#include <Adafruit_GFX.h>

#include <Adafruit_ST7735.h>

#include <SPI.h>

#include <SD.h>

#define TFT_CS   10

#define TFT_DC   9

#define TFT_RST  8

#define SD_CS    4

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

 

void setup(void) {

  Serial.begin(9600);

  tft.initR(INITR_BLACKTAB);

  tft.setRotation(3);

 

  tft.fillScreen(ST7735_BLUE);

 

  Serial.println("Initializing SD card...");

  if (!SD.begin()) {

    Serial.println("failed!");

    return;

  }

  Serial.println("OK!");

  drawBMP("busv3.bmp", 0, 0);

}

void drawBMP(const char *filename, uint16_t x, uint16_t y) {

  File bmpFile = SD.open(filename);

 

  if (!bmpFile) {

    Serial.println("File not found");

    return;

  }

  bmpFile.seek(54); // Пропускаю заголовок

  uint16_t buffer[160];

 

  for (int row = 127; row >= 0; row--) {

    bmpFile.read((uint8_t*)buffer, 320);

    

    tft.startWrite();

    tft.writePixels(buffer, 160);

    tft.endWrite();

  }

 

  bmpFile.close();

  Serial.println("Image loaded");

}

 

void loop() {

}

 

// end of code.

Надеюсь вениками сильно бить ну будут
 

Вложения

poty

★★★★★★✩
19 Фев 2020
3,480
994

@автобус, судя по изображению, есть нарушения в структуре чтения. Изображение должно быть приведено к считываемой размерности, глубина цвета должна быть 16 бит и т.д.
 
  • Лойс +1
Реакции: автобус

asaitov

✩✩✩✩✩✩✩
16 Янв 2024
28
9
В формате BMP заголовочная часть не всегда занимает 54 байта. В заголовке по адресу 0x0a есть специальное поле, в котором хранится адрес начала пиксельных данных. В вашем файле по этому адресу лежит число 66. Это можно проверить, если из размера файла вычесть размер пиксельных данных: 41026 - 128 * 160 * 2 = 66. То есть конкретно для вашего файла, нужно пропустить 66 байт, прежде, чем читать пиксели.

Можно изменить код следующим образом:
C++:
// вместо
// bmpFile.seek(54); // Пропускаю заголовок

// добавить
uint32_t bfOffBits; // адрес начала пиксельных данных
bmpFile.seek(0x0a); // прыгаем до места, где хранится этот адрес
bmpFile.read(&bfOffBits, 4); // читаем адрес
bmpFile.seek(bfOffBits); // прыгаем до начала пиксельных данных
Код не проверял, но идея должна быть понятна.
 
  • Лойс +1
Реакции: автобус

автобус

✩✩✩✩✩✩✩
7 Июн 2025
3
0
@poty @asaitov спасибо за наводки
Действительно, с bmp форматом все не так просто как я думал. Оказывается сама картинка может сжиматься, это указано в заголовке compression. И в моем случае там какие-то битовые маски, так что без промежуточных преобразований обойтись вроде не выйдет. Ну и на остальные заголовки думаю не будет лишним смотреть
Завтра попробую накидать утилиту для нарезки картинок в более простой формат, чтобы для чтения с ардуинки никакой логики не требовалось
 

Stamp

★✩✩✩✩✩✩
12 Янв 2021
64
34
@автобус, Есть специальные программы для нарезки картинок. Достаточно будет прямым поливом выводить.
Img2Lcd
ImageConverter565 - мне эта больше нравится
 
  • Лойс +1
Реакции: автобус

автобус

✩✩✩✩✩✩✩
7 Июн 2025
3
0
@Stamp, а я тут уже с ffmpeg заморочился). Но у меня другая проблема теперь - у меня почему-то при работе с дисплейчиком байты картинки перестают читаться. Ну т.е. функция read почему-то начинает возвращать -1 после первого чтения