ひとしれずひっそり

主にソフトに関することをメモしていきます。過程をそのまま書いていたりするので間違いが含まれます。鵜呑みしない様に。

1.9インチ 91セグメント I2C電子ペーパモジュール(3)

後は温度をe-Paperに表示するのみ。

前回の表示はサンプルそのままだったが、温度表示できる様にする必要がある。

初期化で何をしているか理解できていないが、EPD_1in9_Write_Screen(DSPNUM_1in9_W0)の前までは必須の様だ。
その途中までにすると表示した時に一旦ブラックアウトしてから表示される様になるので。

void setup_epd_1in9()
{
    GPIOInit();
    EPD_1in9_init();
    EPD_1in9_lut_5S();
    EPD_1in9_Write_Screen(DSPNUM_1in9_off);
    delay(500);

    EPD_1in9_lut_GC();
        EPD_1in9_Write_Screen1(DSPNUM_1in9_on);
    delay(500);
    
    EPD_1in9_Write_Screen(DSPNUM_1in9_off);
    delay(500);
    
    EPD_1in9_lut_DU_WB();
}

EPD_1in9_Write_Screen()にセグメントのON/OFFをセットしたバッファを渡すと表示する様だ。
EPD_1in9_Write_Screen1()もあって中程でWire.write(0x00);Wire.write(0x03);の違いだけで今は分かっていない。こちらは初期化で1回使っているだけなのでEPD_1in9_Write_Screen()だけで問題ないのではないかということにしよう。

バッファは15バイトになっている。
以下は全点灯、1の表示、8の表示のパターンで、恐らく1バイト目が温度の100の位の数値でそこを1桁目として、以降2バイトずつ2桁目、3桁目、..6桁目となっていそう。
最後の14、15バイト目はバッテリーや単位の表示ではないかと思われる。

unsigned char DSPNUM_1in9_on[]   = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,       };  // all black
unsigned char DSPNUM_1in9_W1[]   = {0xff, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00,       };  // 1
unsigned char DSPNUM_1in9_W8[]   = {0x00, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x3f, 0x00, 0x00,       };  // 8

桁と文字を指定して表示するルーチンを作ってみた。
サンプルの0から9までのパターンを利用して該当する桁のデータを引っ張ってきてセットするようにしている。

void display_digit(unsigned char buff[], int digit, char num) {
    static unsigned char *buffers[] = {
        DSPNUM_1in9_W0,
        DSPNUM_1in9_W1,
        DSPNUM_1in9_W2,
        DSPNUM_1in9_W3,
        DSPNUM_1in9_W4,
        DSPNUM_1in9_W5,
        DSPNUM_1in9_W6,
        DSPNUM_1in9_W7,
        DSPNUM_1in9_W8,
        DSPNUM_1in9_W9
    };

    if (digit == 0) {
        switch (num) {
            case '1':
                buff[0] = buffers[num - '0'][0];
                break;
            default:
                buff[0] = 0x00;
                break;
        }
    } else {
        unsigned int loc = digit * 2 - 1;
        switch (num) {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                buff[loc] = buffers[num - '0'][loc];
                loc++;
                buff[loc] = buffers[num - '0'][loc];
                break;
            default:
                buff[loc] = 0x00;
                loc++;
                buff[loc] = 0x00;
        }
    }
}

全桁の表示は一旦文字列にして桁ごとに前のルーチンを呼び出す様にしている。
e-Paperは頻繁に書き換えるのはあまり良くないとどこかで見た事があるので、変化がある場合のみ更新する様にした。

#define EPD_BUFF_SIZE    15

void display() {
    static unsigned char ex_buff[EPD_BUFF_SIZE] = {0};
    static unsigned char buff[EPD_BUFF_SIZE]    = {0};
    char str[16] = {0};
    
    sprintf(str, "%5.1f%5.1f", temperature, humidity);

    display_digit(buff, 0, str[0]);
    display_digit(buff, 1, str[1]);
    display_digit(buff, 2, str[2]);
    display_digit(buff, 6, str[4]);
    display_digit(buff, 3, str[6]);
    display_digit(buff, 4, str[7]);
    display_digit(buff, 5, str[9]);

    if (memcmp(ex_buff, buff, EPD_BUFF_SIZE) != 0) {
        Serial.println("update");
        EPD_1in9_Write_Screen(buff);
        delay(500);
        memcpy(ex_buff, buff, EPD_BUFF_SIZE);
    }
}

予想に反して桁の順番は次の様になっていた。

Wikiにちゃんと書いてた。
dotと%は5bit目で0x20をorすれば良さそう。
他も書いてある。

1.9inch Segment e-Paper Module Manual - Waveshare Wiki

これで表示できた。

 /* dot & % */
    buff[2 * 2] |= 0x20;
    buff[4 * 2] |= 0x20;
    buff[5 * 2] |= 0x20;

    /* c or f */
    buff[13] = 0x5;     // Celsius
    // buff[13] = 0x6;      // Fahrenheit

    /* bluetooth */
    buff[13] |= 0x08;

    /* battery */
    buff[13] |= 0x10;

バッテリーは残量表示はないので、不足してきたら点灯させる様にすれば良さそう。

スリープ処理を入れて温湿度計は一応完成。

M5Stamp picoで1.9inch Segment e-Paper Moduleのサンプルプログラムを試して見る。からの温湿度計に · GitHub