TN液晶8セグモジュールを使う(TS119)


前回、TN液晶8セグモジュール(TS206V1)を紹介しましたが、その後 TS119-5も購入しましたので紹介します。
TS206/TS206V1と比べるとさらに小型のモジュールです。
上がTS206 下がTS119-5 どちらもバックライト付きです。


液晶ですが8セグなので、決まったパターンしか表示できません。
TS119-5は、以下のように⓪からGの表示領域を持つモジュールです。
かなりトリッキーな表示となっています。
8セグの表示パターンは以下のようになっています。


⓪の表示領域は小文字の8セグ表示です。
ドットの代わりに「1」を表示します。
数字を表示する場合「 0」から「19」までを表示することができます。


@の表示領域は大文字の8セグ表示です。
ドットの代わりにコロンを2箇所に表示します。
コロンを1つだけ表示することはできません。


Aの表示領域は大文字の8セグ表示です。
ドットの代わりに右上に「H」を表示します。


Bの表示領域は大文字の8セグ表示です。
ドットの代わりに左下に「時計マーク」を表示します。


Cの表示領域は大文字の8セグ表示です。
ドットの代わりに左上に「ビックリマーク」を表示します。


Dの表示領域は大文字の8セグ表示です。
ドットの代わりに右下に「方位マーク(??)」を表示します。


EFの表示領域は大文字の8セグ表示です。
ドットは左側に表示します。


Gの表示領域には以下の特殊文字を表示することができます。
下の写真は全ての文字を表示した状態ですが、この中から組み合わせて表示可能です。



全てのセグメントを表示すると以下のようになります。



表示するセグメントを操作することでこのように数字やマイナスなどを表示することができます。






Gの領域と組み合わせて表示すると、以下のようになります。








Arduino用のライブラリがこち らに 公開されています。
Arduinoで使う場合の結線は以下の通りです。
TS119 Arduino
1(CS) IO2
2(RD) N/C
3(WR) IO3
4(DT) IO4
5(VSS) GND
6(VDD) 5V
7(IRQ) N/C
8(LED-K) GND
9(LED-A) 5V

Arduinoのコードは以下の通りです。
こちらに 公開されているサンプルコードをベースにしています。
/*
 * \file HT1621-test.ino
 * \brief Simple test sketch for the HT1621 class.
 * \author Enrico Formenti
 * \date 4 february 2015
 * \version 1.0
 * \copyright BSD license, check the License page on the blog for more information. All this text must be
 *  included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#include "HT1621.h" // https://github.com/marc-gist/HT1621

// refere to Macduino website for pin connections and their meaning
HT1621 ht(2,3,4);  // CS RW DATA


/*  TS119 Address map
 * 
 *  +---+---+---+---+---+---+---+---+---+
 *  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |   |
 *  |   |   |   |   |   |   |   |   | 8 |
 *  +---+---+---+---+---+---+---+---+---+
 *
 *  Address 0-7 is 8 segments
 * 
 *       a
 *       -
 *    f | | b
 *       -  <-g
 *    e | | c
 * h->.  -
 *       d
 *      
 *   a = 0x80
 *   b = 0x08
 *   c = 0x02
 *   d = 0x10
 *   e = 0x20
 *   f = 0x40
 *   g = 0x04
 *   h = 0x01
 *  
 *
 */

uint8_t pattern[] = {
  B11111010, // 0
  B00001010, // 1
  B10111100, // 2
  B10011110, // 3
  B01001110, // 4
  B11010110, // 5
  B11110110, // 6
  B10001010, // 7
  B11111110, // 8
  B11011110, // 9
  B00000100, // -
  B00010000, // _
  B00000000  // Space
 };

void setNum(uint8_t adr, uint8_t num, bool dot=0) {
  if (dot) {
    ht.write(adr, pattern[num] | B00000001);
  } else {
    ht.write(adr, pattern[num]);
  }
}

void setup() {
  Serial.begin(115200);
 
  ht.begin();
 
  ht.sendCommand(HT1621::RC256K);
  ht.sendCommand(HT1621::BIAS_THIRD_4_COM);
  ht.sendCommand(HT1621::SYS_EN);
  ht.sendCommand(HT1621::LCD_ON);

  // clear memory
  for(int digit=0; digit<9; digit++)
    ht.write(digit,0);

  // all digit ON
  for(int digit=0; digit<9; digit++) {
    ht.write(digit, 0xff);
    delay(100);
  }
  delay(10000);


  // all 0 to 9
  for(int num=0;num<10;num++) {
    for(int digit=0; digit<8; digit++) {
      setNum(digit,num);
   }
  delay(1000);
  }
 
  setNum(0,0);
  setNum(1,1);
  setNum(2,2);
  setNum(3,3);
  setNum(4,4);
  setNum(5,5);
  setNum(6,6);
  setNum(7,7);
  delay(5000);
 
  setNum(0,2,1); // with dot
  setNum(1,3);
  setNum(2,4);
  setNum(3,5);
  setNum(4,6);
  setNum(5,7);
  setNum(6,8);
  setNum(7,9);
  delay(5000);
 

}

void loop() {
}

UNOで実行してみました。


ATtiny85でも問題なく動きます。


ATtiny84を使うとワイヤーは6本で済みます。




RaspberryPiで使う場合の結線は以下の通りです。
TS119-5 Raspberry
1(CS) GPIO27
2(RD) N/C
3(WR) GPIO18
4(DT) GPIO17
5(VSS) GND
6(VDD) 5V(*)
7(IRQ) N/C
8(LED-K) GND
9(LED-A) 5V

(*) VDDは3.3Vでも動きますが、ほとんど文字が見えません。

Raspberryのコードは以下の通りです。こちらにも上げておきます。
表示の基本的なコードはArduino用のこ ち らのライブラリから移植しました。
/*  TS119 Address map
 * 
 *  +---+---+---+---+---+---+---+---+---+
 *  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |   |
 *  |   |   |   |   |   |   |   |   | 8 |
 *  +---+---+---+---+---+---+---+---+---+
 *
 *  Address 0-7 is 8 segments
 * 
 *       a
 *       -
 *    f | | b
 *       -  <-g
 *    e | | c
 * h->.  -
 *       d
 *      
 *   a = 0x80
 *   b = 0x08
 *   c = 0x02
 *   d = 0x10
 *   e = 0x20
 *   f = 0x40
 *   g = 0x04
 *   h = 0x01
 *
 *
 */

#include <stdio.h>
#include <stdint.h>
#include <wiringPi.h>

uint8_t _DATA_pin;
uint8_t _RW_pin;
uint8_t _CS_pin;

#define DATA 0
#define RW   1
#define CS   2

#define TAKE_CS()    digitalWrite(_CS_pin, LOW)
#define RELEASE_CS() digitalWrite(_CS_pin, HIGH)


uint8_t pattern[] = {
   0xfa, // 0
   0x0a, // 1
   0xbc, // 2
   0x9e, // 3
   0x4e, // 4
   0xd6, // 5
   0xf6, // 6
   0x8a, // 7
   0xfe, // 8
   0xde, // 9
   0x04, // -
   0x10, // _
   0x6e, // H
   0xf4, // E
   0x70, // L
   0xec, // P
   0x00  // Space
};

enum Commands {
    SYS_DIS   = 0x00, /*!< System disable. It stops the bias generator and the system oscillator. */
    SYS_EN    = 0x02, /*!< System enable. It starts the bias generator and the system oscillator. */
    LCD_OFF   = 0x04, /*!< Turn off the bias generator. */
    LCD_ON    = 0x06, /*!< Turn on the bias generator. */
    TIMER_DIS = 0x08, /*!< Disable time base output. */
    WDT_DIS   = 0x0a, /*!< Watch-dog timer disable. */
    TIMER_EN  = 0x0c, /*!< Enable time base output. */
    WDT_EN    = 0x0e, /*!< Watch-dog timer enable. The timer is reset. */
    CLR_TIMER = 0x18, /*!< Clear the contents of the time base generator. */
    CLR_WDT   = 0x1c, /*!< Clear the contents of the watch-dog stage. */

    TONE_OFF  = 0x10, /*!< Stop emitting the tone signal at the tone pin. \sa TONE2K, TONE4K */
    TONE_ON   = 0x12, /*!< Start emitting tone signal at the tone pin. Tone frequency
is selected using commands TONE2K or TONE4K. \sa TONE2K, TONE4K */
    TONE2K    = 0xc0, /*!< Output tone is at 2kHz. */
    TONE4K    = 0x80, /*!< Output tone is at 4kHz. */

    RC256K    = 0x30, /*!< System oscillator is the internal RC oscillator at 256kHz.  */
    XTAL32K   = 0x50, /*!< System oscillator is the crystal oscillator at 32768Hz. */
    EXT256K   = 0x38, /*!< System oscillator is an external oscillator at 256kHz. */

    //Set bias to 1/2 or 1/3 cycle
    //Set to 2,3 or 4 connected COM lines
    BIAS_HALF_2_COM  = 0x40, /*!< Use 1/2 bias and 2 commons. */
    BIAS_HALF_3_COM  = 0x48, /*!< Use 1/2 bias and 3 commons. */
    BIAS_HALF_4_COM  = 0x50, /*!< Use 1/2 bias and 4 commons. */
    BIAS_THIRD_2_COM = 0x42, /*!< Use 1/3 bias and 2 commons. */
    BIAS_THIRD_3_COM = 0x4a, /*!< Use 1/3 bias and 3 commons. */
    BIAS_THIRD_4_COM = 0x52, /*!< Use 1/3 bias and 4 commons. */

    IRQ_EN    = 0x10, /*!< Enables IRQ output. This needs to be excuted in SPECIAL_MOD E. */
    IRQ_DIS   = 0x10, /*!< Disables IRQ output. This needs to be excuted in SPECIAL_MO DE. */

    // WDT configuration commands
    F1 = 0x80, /*!< Time base/WDT clock. Output = 1Hz. Time-out = 4s. This needs to be excuted in SPECIAL_MODE. */
    F2 = 0x42, /*!< Time base/WDT clock. Output = 2Hz. Time-out = 2s. This needs to be excuted in SPECIAL_MODE. */
    F4 = 0x44, /*!< Time base/WDT clock. Output = 4Hz. Time-out = 1s. This needs to be excuted in SPECIAL_MODE. */
    F8 = 0x46, /*!< Time base/WDT clock. Output = 8Hz. Time-out = .5s. This needs to be excuted in SPECIAL_MODE. */
    F16 = 0x48, /*!< Time base/WDT clock. Output = 16Hz. Time-out = .25s. This needs to be excuted in SPECIAL_MODE. */
    F32 = 0x4a, /*!< Time base/WDT clock. Output = 32Hz. Time-out = .125s. This needs to be excuted in SPECIAL_MODE. */
    F64 = 0x4c, /*!< Time base/WDT clock. Output = 64Hz. Time-out = .0625s. This needs to be excuted in SPECIAL_MODE. */
    F128 = 0x4e, /*!< Time base/WDT clock. Output = 128Hz. Time-out = .03125s. This needs to be excuted in SPECIAL_MODE. */

    //Don't use
    TEST_ON   = 0xc0, /*!< Don't use! Only for manifacturers. This needs SPECIAL_MODE. */
    TEST_OFF  = 0xc6, /*!< Don't use! Only for manifacturers. This needs SPECIAL_MODE. */

    COMMAND_MODE = 0x80, /*!< This is used for sending standard commands. */
    READ_MODE = 0xc0, /*!< This instructs the HT1621 to prepare for reading the internal RAM. */
    WRITE_MODE = 0xa0, /*!< This instructs the HT1621 to prepare for writing the internal RAM. */
    READ_MODIFY_WRITE_MODE = 0xa0, /*!< This instructs the HT1621 to prepare for reading/modifying batch of internal RAM adresses. */
    SPECIAL_MODE = 0x90 /*!< This instructs the HT1621 to prepare for executing a special command. */

};


void HT1621_begin(uint8_t cs, uint8_t rw, uint8_t data)
{
    _DATA_pin = data;
    _RW_pin = rw;
    _CS_pin = cs;

    pinMode(_DATA_pin, OUTPUT);
    pinMode(_RW_pin, OUTPUT);
    pinMode(_CS_pin, OUTPUT);
 
    digitalWrite(_CS_pin, HIGH);
    digitalWrite(_RW_pin, HIGH);
    digitalWrite(_DATA_pin, HIGH);
}

void HT1621_writeBits(uint8_t data, uint8_t cnt)
{
    uint8_t i;

    for(i=0;i<cnt;i++,data <<=1)
    {
        digitalWrite(_RW_pin, LOW);
        delayMicroseconds(20);
        digitalWrite(_DATA_pin, data&0x80 ? HIGH : LOW);
        delayMicroseconds(20);
        digitalWrite(_RW_pin, HIGH);
        delayMicroseconds(20);
    }
}

void HT1621_write(uint8_t address, uint8_t data)
{
    TAKE_CS();
    HT1621_writeBits(WRITE_MODE, 3);
    HT1621_writeBits(address<<3, 6); // 6 is because max address is 128
    HT1621_writeBits(data, 8);
    RELEASE_CS();
}


void HT1621_sendCommand(uint8_t cmd)
{
    TAKE_CS();
    HT1621_writeBits(COMMAND_MODE, 4);
    HT1621_writeBits(cmd, 8);
    RELEASE_CS();
}

void HT1621_init()
{
//    HT1621_sendCommand(RC256K);
    HT1621_sendCommand(BIAS_THIRD_4_COM);
    HT1621_sendCommand(SYS_EN);
    HT1621_sendCommand(LCD_ON);
}

void HT1621_clear(uint8_t places)
{
   uint8_t i;
   for (i = 0; i < places; i++)
     HT1621_write(i, 0);
}

void HT1621_setNum(uint8_t adr, uint8_t num) {
   HT1621_write(adr, pattern[num]);
}

void HT1621_setDotNum(uint8_t adr, uint8_t num) {
   HT1621_write(adr, pattern[num] | 0x01);
}

int main(int argc, char **argv) {
   int i;

   if(wiringPiSetup() == -1) {
     printf("Setup Fail\n");
     return 1;
   }

   HT1621_begin(CS,RW,DATA);
   HT1621_init();
   // clear memory
   HT1621_clear(9);

   for(i=0; i<6; i++) {
     HT1621_clear(8);
     HT1621_write(i, 0xff);
     printf("address=%d\n",i);
     getchar();
   }
   HT1621_clear(9);
   HT1621_write(6, 0xff);
   HT1621_write(7, 0xff);
   getchar();
   HT1621_clear(9);
   HT1621_write(8, 0xff);
   getchar();

   // all digit ON
   HT1621_clear(9);
   for(i=0; i<12; i++) {
     HT1621_write(i, 0xff);
   }
   getchar();

   HT1621_clear(9);
   HT1621_setNum(0,0);
   HT1621_setNum(1,1);
   HT1621_setNum(2,2);
   HT1621_setNum(3,3);
   HT1621_setNum(4,4);
   HT1621_setNum(5,5);
   HT1621_setNum(6,6);
   HT1621_setNum(7,7);
   getchar();

   HT1621_setNum(0,16);
   HT1621_setNum(1,8);
   HT1621_setNum(2,9);
   HT1621_setNum(3,10);
   HT1621_setNum(4,12); // H
   HT1621_setNum(5,13); // E
   HT1621_setNum(6,14); // L
   HT1621_setNum(7,15); // P
   getchar();

   HT1621_setNum(0,16);
   HT1621_setDotNum(1,16); // with colon
   HT1621_setNum(2,1);
   HT1621_setDotNum(3,2); // with clock mark
   HT1621_setNum(4,3);
   HT1621_setNum(5,4);
   HT1621_setNum(6,5);
   HT1621_setNum(7,6);
   getchar();

   HT1621_setNum(0,16);
   HT1621_setNum(1,16);
   HT1621_setNum(2,16);
   HT1621_setNum(3,16);
   HT1621_setNum(4,1);
   HT1621_setNum(5,2);
   HT1621_setDotNum(6,3);
   HT1621_setNum(7,4);
   HT1621_write(8,0x0c); // V
   getchar();
   HT1621_write(8,0x11); // A
   getchar();
   HT1621_write(8,0x0f); // W
   getchar();
   HT1621_clear(9);
}

TS174NBL(バックライト無し)とTS174(バックライト有り)も安売りしていたので入手しましたが、全て上のコードで動きました。
セグメントに表示できる文字も全く同じですが、TS174の方がフォントの線が太いです。
左からTS119-3 TS174NBL(バックライト無し) TS174(バックライト有り)


但し、バックライト付きモデルの視野角は非常に狭く、正面から見ないとほとんど見えません。

ほぼ正面

斜め45度ぐらい

斜め45度ぐらい バックライトなし

斜め30度ぐらい どちらも見えない

斜め30度ぐらい バックライトなし

斜め45度ぐらい 少し遠くから
Raspberryではなく、OrangePiを使っているのがばれますね。

TS174NBLの方が遠くからでもはっきり見えますが、先に紹介したTS206V1の方が視野角は広いです。
左がTS206V1 右がTS174NBL

ほぼ正面

斜め45度ぐらい

斜め30度ぐらい TS174NBLは識別できません。

TS174のバックライト付きはTS119とはLED-KとLED-Aのピン位置が逆です。
TS119 TS174 Raspberry
1(CS) 1(CS) GPIO27
2(RD) 2(RD) N/C
3(WR) 3(WR) GPIO18
4(DT) 4(DT) GPIO17
5(VSS) 5(VSS) GND
6(VDD) 6(VDD) 5V(*)
7(IRQ) 7(IRQ) N/C
8(LED-K) 8(LED-A) 5V
9(LED-A) 9(LED-K) GND

また、バックライトを有効にするためには基板裏のR2をショートする必要が有ります。


バックライトをつけて正面から見るとほとんど文字を識別できません。
この角度から見る必要が有ります。


次回はTS125を紹介します。