Estardyn 0.96 インチ IPS LCD TFT ディスプレイモジュール 160x80 HD 65K SPI インターフェイス ST7735S2026/08/21

アリエクのEstarDyn Factory Storeで ”Estardyn 0.96 インチ IPS LCD TFT ディスプレイモジュール 160x80 HD 65K SPI インターフェイス ST7735S 3.3V Raspberry Pi DIY プロジェクト用”を買ってみました。カラーで¥300也。



Adafruit_ST7735.h を見ると 160x80ドットの初期化に、それっぽいのが2つあったので
INITR_MINI160x80_PLUGIN
INITR_MINI160x80
試してみると INITR_MINI160x80 これが良いようでした。INITR_MINI160x80_PLUGIN これは隅にスジが入ってずれて表示されました。

スケッチ
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>

//SPIピン定義
#define TFT_BLK          8   // BLK
#define TFT_CS           9   // CS
#define TFT_DC          10   // DC
#define TFT_RST         11   // Reset
#define TFT_MOSI        12   // SDA
#define TFT_SCK         13   // SCL

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

void setup(void)
{
  pinMode(TFT_BLK, OUTPUT);              //バックライトにGPIOを使用する
  digitalWrite(TFT_BLK, HIGH);           //バックライト オン

  //SPIピン設定
  SPI.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS);

  tft.initR(INITR_MINI160x80);             //ST7735初期化
 
  tft.fillScreen(ST77XX_BLACK);               //背景の塗りつぶし

  tft.setRotation(0);                         //画面回転
  tft.setTextSize(2);                         //サイズ

  tft.setCursor(0, 0);                       //カーソル位置                      
  tft.setTextColor(ST77XX_RED);              //赤
  tft.printf("Red\n");
  tft.setTextColor(ST77XX_GREEN);            //緑
  tft.printf("Green\n");
  tft.setTextColor(ST77XX_BLUE);             //青
  tft.printf("Blue\n");
}

void loop()
{
}

スケッチの結果
赤の指定なのに青。青が赤になっています。
調べてみると同じようなディスプレモジュールでもいろいろあるようです。。。
RGB 16ビットのデータフォーマットにはRGB565とBGR565があるそうで、これを直せば良いみたいです。
ST7735Sの仕様書をみたら、RGB-BGR ORDERというものがあります。
このビットをBGRにすればよいと思うので、このレジスタを設定する箇所を探せば良さそうです。
このレジスタのアドレスと思われる ST77XX_MADCTL という定義があったので検索すると
Adafruit_ST7735.cpp のinitRとsetRotationで使われていました。
確認のためsetRotationのあとにMADCTLレジスタを書き換えてみました。
このレジスタを読み出せればRGBビットだけ1にすればよさそうなのですが、インターフェースに読み出しのピンがないようなので、
値を上書きすることにしました。ですので上位4ビットは画面の回転設定に影響するのでsetRotationの引数に合わせて値を決めました。
(どのビットを立てるかはAdafruit_ST7735.cppを参考)

変更箇所 setRotationの後
  tft.setRotation(0);                         //画面回転
  //RGB-BGR ORDER (setRotationがMADCTLを書き換えている)
  uint8_t data = 0xC8;  //0:0xC8 1:0xA8 2:0x08 3:0x68 画面の回転方向による
  tft.sendCommand(ST77XX_MADCTL, &data, 1);

変更スケッチの結果

ちなみにsetRotaionが役に立っていないようですが、ほかの設定があるようで、レジスタの値を引数に合わせて設定しないとダメでした。
もうちょっと解析して、Adafruit_ST7735.cppを別の名前にしてローカルで作り直すか、setRotationをオーバーライドするかして、
かっこよくしたほうがよさそうです。
とりあえず楽そうだったので、setRotationをオーバーライド。


#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>

//SPIピン定義
#define TFT_BLK          8   // BLK
#define TFT_CS           9   // CS
#define TFT_DC          10   // DC
#define TFT_RST         11   // Reset
#define TFT_MOSI        12   // SDA
#define TFT_SCK         13   // SCL

class MyST7735 : public Adafruit_ST7735 {
public:
  using Adafruit_ST7735::Adafruit_ST7735;   // コンストラクタを継承

  // setRotation をオーバーライドして追加処理
  void setRotation(uint8_t m) override {
    Adafruit_ST7735::setRotation(m);    //元の実装を呼び出す
  //追加の処理 RGB->BGR
    uint8_t data = 0xC8;
    switch (m) {
      case 0:
        data = 0xC8;
        break;
      case 1:
        data = 0xA8;
        break;
      case 2:
        data = 0x08;
        break;
      case 3:
        data = 0x68;
        break;
    }
    sendCommand(ST77XX_MADCTL, &data, 1);
  }
};

//Adafruit_ST7735 tft = Adafruit_ST7735(&SPI, TFT_CS, TFT_DC, TFT_RST);
MyST7735 tft = MyST7735(&SPI, TFT_CS, TFT_DC, TFT_RST);

void setup(void)
{
  pinMode(TFT_BLK, OUTPUT);              //バックライトにGPIOを使用する
  digitalWrite(TFT_BLK, HIGH);           //バックライト オン

  //SPIピン設定
  SPI.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS);

  tft.initR(INITR_MINI160x80);             //ST7735初期化
 
  tft.fillScreen(ST77XX_BLACK);               //背景の塗りつぶし

  tft.setRotation(0);                         //画面回転
  tft.setTextSize(2);                         //サイズ

  tft.setCursor(0, 0);                       //カーソル位置                      
  tft.setTextColor(ST77XX_RED);              //赤
  tft.printf("Red\n");
  tft.setTextColor(ST77XX_GREEN);            //緑
  tft.printf("Green\n");
  tft.setTextColor(ST77XX_BLUE);             //青
  tft.printf("Blue\n");
}

void loop()
{
}

一応使えそうですが、ほかにも問題が起こるかもしれません。