Skocz do zawartości

E-paper 2.9 (aka Waveshare black-red-white) poszukiwana biblioteka


DeadGeneratio

Pomocna odpowiedź

Jak w temacie, zaufałem marce WeAct pod względem mikrokontrolerów, ale niestety ciężko z znalezieniem biblioteki do 2,9 calowego modułu wyświetlacza w technologii e-paper, w wersji black, white and red. Chciałem wzorować się na module od waveshare, mają biblioteki do stm32 f103, ale tylko dla wersji black-white. Z kolei na githubie od WeAct, link obok: https://github.com/WeActStudio/WeActStudio.EpaperModule/tree/master nie ma wersji dla STM. Starałem się przejrzeć datasheet jak zrobiłem to dla czujnika ciśnienia i temperatury STH czy tam SHT31 i zrobiłem komplet funkcji które działały na jego podstawie, ale ten datashhet mnie niestety przerasta. Sądziłem, że będzie to najzwyklejszy ekran a to ma więcej funkcji niż stare telefony, a tak przynajmniej datasheet wygląda. Ma ktoś może taką bibliotekę, wie gdzie szukać bądź zetknął się już z tym modułem?

  • Lubię! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

(edytowany)

W screen.c mam:

#include "screen.h"
#include "fonts.h"

#include "stm32h7xx_hal.h"

a wcześniej gdy ustawiłem rozdrobnienie programu osobne pliki .c oraz .h

#include "screen.h"
#include "fonts.h"

#include "stm32h7xx_hal.h"
#include "spi.h"
#include "gpio.h"
  

Wiem, że to głupie z tym spi.h skoro ja tworzę tutaj instancję SPI, ale postanowiłem stworzyć początkowo w CUBE IDE instancję SPI, a potem w kodzie nie dodawać części odpowiedzialnej za inicjowanie SPI. To co teraz widać jest próbą stworzenia tej instancji bez pomocy CUBE IDE.

Plik screen.h wygląda następująco:

#ifndef INC_SCREEN_H_
#define INC_SCREEN_H_

#include "stm32h7xx_hal.h"

I oczywiście, w pliku main.c mam dołączenie screen.h

Edytowano przez DeadGeneratio
Link do komentarza
Share on other sites

Udało mi się zmodyfikować kod - SPI2 jest inicjalizowane przez CUBE IDE z zawartością analogiczną do tej co w kodzie:

void MX_SPI2_Init(void)
{

  /* USER CODE BEGIN SPI2_Init 0 */

  /* USER CODE END SPI2_Init 0 */

  /* USER CODE BEGIN SPI2_Init 1 */

  /* USER CODE END SPI2_Init 1 */
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  hspi2.Init.Direction = SPI_DIRECTION_1LINE;
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
  hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 0x0;
  hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  hspi2.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
  hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
  hspi2.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  hspi2.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  hspi2.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
  hspi2.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
  hspi2.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
  hspi2.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
  hspi2.Init.IOSwap = SPI_IO_SWAP_DISABLE;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI2_Init 2 */

  /* USER CODE END SPI2_Init 2 */

}

oraz wejścia/wyjścia GPIO także:

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, SPI2_RES_Pin|SPI2_DC_Pin|SPI2_CS_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pins : PBPin PBPin PBPin */
  GPIO_InitStruct.Pin = SPI2_RES_Pin|SPI2_DC_Pin|SPI2_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = SPI2_BUSY_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(SPI2_BUSY_GPIO_Port, &GPIO_InitStruct);

}

Przyszedł czas na testowanie wyświetlacza i mam mały zonk, bo niestety robię to na chłopski rozum z racji braku poradników bądź toturiali, a i z ekranem typu e-papier mam doczynienia pierwszy raz. Przeglądając plik screen.h:

#ifndef INC_SCREEN_H_
#define INC_SCREEN_H_

#include "stm32h7xx_hal.h"

#define EPD_W 128
#define EPD_H 296

#define EPD_OK 0
#define EPD_ERROR 1

#define EPD_ROTATE_0 0
#define EPD_ROTATE_90 90
#define EPD_ROTATE_180 180
#define EPD_ROTATE_270 270

#define EPD_COLOR_WHITE 0xFF
#define EPD_COLOR_BLACK 0x00
#define EPD_COLOR_RED EPD_COLOR_BLACK

#define EPD_FONT_SIZE8x6 (8)
#define EPD_FONT_SIZE12x6 (12)
#define EPD_FONT_SIZE16x8 (16)
#define EPD_FONT_SIZE24x12 (24)

#define EPD_DEEPSLEEP_MODE1 (0x01)
#define EPD_DEEPSLEEP_MODE2 (0x03)

#define EPD_W_BUFF_SIZE ((EPD_W % 8 == 0) ? (EPD_W / 8) : (EPD_W / 8 + 1))
    typedef struct
    {
        uint8_t *Image;
        uint16_t Width;
        uint16_t Height;
        uint16_t WidthMemory;
        uint16_t HeightMemory;
        uint16_t Color;
        uint16_t Rotate;
        uint16_t WidthByte;
        uint16_t HeightByte;
    } EPD_PAINT;
    extern EPD_PAINT EPD_Paint;

    uint8_t epd_init(void);
    uint8_t epd_init_partial(void);
    void epd_enter_deepsleepmode(uint8_t mode);
    void epd_init_internalTempSensor(void);
    void epd_update(void);
    void epd_update_partial(void);
    void epd_display(uint8_t *Image1, uint8_t *Image2);
    void epd_displayBW(uint8_t *Image);
    void epd_displayBW_partial(uint8_t *Image);
    void epd_displayRED(uint8_t *Image);

    void epd_paint_newimage(uint8_t *image, uint16_t Width, uint16_t Height, uint16_t Rotate, uint16_t Color);
    void epd_paint_setpixel(uint16_t Xpoint, uint16_t Ypoint, uint16_t Color);
    void epd_paint_selectimage(uint8_t *image);
    void epd_paint_clear(uint16_t color);
    void epd_paint_drawPoint(uint16_t Xpoint, uint16_t Ypoint, uint16_t Color);
    void epd_paint_drawLine(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend, uint16_t Color);
    void epd_paint_drawRectangle(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend, uint16_t Color, uint8_t mode);
    void epd_paint_drawCircle(uint16_t X_Center, uint16_t Y_Center, uint16_t Radius, uint16_t Color, uint8_t mode);
    void epd_paint_showChar(uint16_t x, uint16_t y, uint16_t chr, uint16_t size1, uint16_t color);
    void epd_paint_showString(uint16_t x, uint16_t y, uint8_t *chr, uint16_t size1, uint16_t color);
    void epd_paint_showNum(uint16_t x, uint16_t y, uint32_t num, uint16_t len, uint16_t size1, uint16_t color);
    void epd_paint_showChinese(uint16_t x, uint16_t y, uint16_t num, uint16_t size1, uint16_t color);
    void epd_paint_showPicture(uint16_t x, uint16_t y, uint16_t sizex, uint16_t sizey, const uint8_t BMP[], uint16_t Color);

#ifdef __cplusplus
}
#endif


#endif

widzę, że wypadałoby zainicjalizować ekran - epd_init(). Potem dla testu wykonuję epd_paint_clear(0xFF), czyli cały ekran czyszczę na dany kolor, a przynajmniej tak myślałem. Nic się nie działo więc dorzuciłem epd_update() oraz na koniec epd_enter_deepsleepmode(), ale ekran dostaje padaczki. Stwierdziłem, że okej, być może funkcja czyści ekran z tego tylko koloru co zadeklaruję, więc trzykrotnie wywołałem czyszczenie poszczególnego koloru, ale ekran dalej działa tak samo upośledzenie. Ktoś domyśla się co może być przyczyną? W załączniku nowy kod.

Nagranie działania ekranu: https://drive.google.com/file/d/1GSGuvmLHbmtp-CNvZ1q1f0HsIFLJ5cqm/view?usp=sharing

Namieszane_w_SPIv2.zip

Link do komentarza
Share on other sites

(edytowany)

Niestety z takim rozbudowanym albo tak napisanym dokumentem nie jestem w stanie sobie poradzić samodzielnie. Staram się analizować kod analogiczny dla APM i sprawdzać sobie funkcje poszczególne a nawet odtworzyć kod, ale idzie bardzo kiepsko.

Na pewno muszę zainicjować wyświetlacz. Z inżynierii wstecznej wychodzi, że należy wykorzystać rejestr 0x01, a następnie wysłać wartość 0x27, 0x01 oraz 0x01. W sumie czy należy nie wiem, ktoś tak zrobił i w ten sposób wyświetlacz zadziałał.

image.thumb.png.50a05ac0968e47bb372e9111b7674dda.png

Z kodu potem wynika, że na mikrokontrolerze przygotowana jest mapa bitowa, która potem jest wysyłana komendą epd_display, czyli rejestr 0x24 dla koloru czarno-białego i rejestr 0x26 dla czerwonego. Wysyłane są wtedy dane do RAMu. Ale najgorsze jest to, że skoro rozdzielczość wynosi z grubsza  100x300 to powinienem mieć około 30000 znaków w tablicy. A przykładowe obrazy w pliku bmp mają maksymalnie 4000 znaków.

Na samym końcu wywołać wysłanie zawartości RAMu z wyświetlacza na sam wyświetlacz do czego służy rejestr 0x21, a następnie wysłanie komendy przy DC = 1, 0b00000000 - screen poniżej z dokumentacji.

image.thumb.png.f6965266fdc101ca3b977c048ebefd6c.png

Po aktualizacji na pewno wejście w deepsleep mode, czyli 0x10, a potem DC = 1 oraz 0b00000001.

image.thumb.png.312410705c5803a8def085c1871de1a9.png

 

 

Edytowano przez DeadGeneratio
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.