激安液晶駆動ログ
aitendoで激安液晶モジュールなんてものがあったから買ってみた
仕様的に動かしやすそうだからとりあえず遊んでみたログ
しよう?
この激安液晶モジュールはバックライトの有無とかで幾つかの種類がある
今回買ったのはTS119-5という型番だった
コントローラとバックライト付きの数字7+記号2桁の8セグ液晶モジュールらしい
コントローラはHT1621B,通信方式はSPI?,バックライトは3V駆動?のLED
ロジックも3Vで駆動するらしい
なんとか3VのTrinketでも動かせそう
まずはググったりデータシート(PDF注意)見たりしてみよう
はいせん
ピンアサインはLEDを表にして左から順に
CS | RD | WD | DATA | GND | VCC | ? | LED- | LED+ |
---|---|---|---|---|---|---|---|---|
- | - | - | - | - | ~5V | ? | - | ~5V |
となっているらしい
CS
Clock-Signal
かと思ってたらChip-Select
の略だったっていう
複数のデバイスを繋いだ時のチップ指定端子らしい
データシートを見たところHIGH
でOFF,LOW
でONになるとか
普通と逆なんねと思ったらIC内部でプルダウンしてあるから
これだけ繋ぐなら結線しなくていいようになっているとか?
とりあえず抜いて動かす
どうやらコマンドラインリセットにも使っているらしいから結線は必要
そして通信しない時はHIGHに固定しなきゃ駄目っぽい
Trinketの4
に挿した
RD
Read-Data
通信バスかと思ったらこっちがクロック制御だった
データを読む時のクロックを入れるらしい
データシートによると立ち下がりでCLKっぽい(DS:P13参照)
これも最初はとりあえず抜いておく
WD
Write-Data
通信バスかと思ったら(ry
書き込みに使う以外はRD
と同じなので説明省略
Trinketの6
に挿した
DATA
これが本当のバスライン
このピンにI/Oしてデータをやりとりするらしい
Trinketの8
に挿した
GND
グランドライン
そのままTrinketのGNDラインに繋いだ
VCC
ロジック電源
LEDと並列に繋いだから不安だけど消費電力少ないから多分平気
?
不明
調べてもどういうピンなのかわからなかった. そもそも結線されてない?
データシートに書いてある中でそれっぽいのはオシレータインプット(OSCI)だった
ググってみたらIRQっぽい?
これもとりあえずどこにも繋がないでおく
LED-
バックライトLEDのカソード
GNDラインに繋いだ
LED+
バックライトLEDのアノード
LEDも詳細がわからない とりあえず3V3OUTを繋げたら眩しいくらいに光った
一応怖いから47Ωの抵抗付けたけど暗いし抵抗要らないかもしれない(基板に実装されてるし)
つーしん
通信方式は販売ページにSPIって書いてあった
けど実際には独自形式のシリアル通信っぽい aitendoェ・・・
CSをLowにしてRD/WDでクロック送ってDATAで実データ(1bit)やりとりすればいいらしい
ただしクロックはWrite3.34μs/Read6.67μs(5V駆動時は半分?)以上のタイミングじゃないと駄目らしい(DS:P8参照)
とりあえず10μくらいで様子見る
たいみんぐ
具体的な通信方法とタイミングはデータシートに書いてある(DS:P13~16参照)
通信にはシーケンシャルアクセスとランダムアクセスがあるっぽい(DS:P13~P15参照)
どっちもCSをLOWにした半クロック後にWD/RDのクロックを開始してからID(3bit)を流して
その後にIDに対応した信号を流していく
通信が終わったらCSをHIGHにしておく
書き込むときはまた最初から繰り返し
ビット長はコマンドも読み書きも12bit
ビット長はコマンドが12bit(3+8+1)で,W/Rが13bit(3+6+4)だった
基本こんな感じらしい
こまんど
このチップは電源を入れただけじゃ起動しないらしい
ちゃんとコマンド入れて初期化しないと駄目だとか
コマンド一覧もデータシートにちゃんとある(DS:P18~P19参照)
初期化はLCD ON
してからBIAS 1/2
してやればいい?BIAS 1/3
でした
とりあえずコード書いて動かしてみる:
/* HT1621B Controlling Test */ //ピン定義 #define _PIN_CS 4 #define _PIN_RD 0 #define _PIN_WD 6 #define _PIN_DA 8 //クロックディレイ(MicroSec,1/2クロック) #define _CLK_DELAY 6 //シグナルID #define _CMD_SIGID (unsigned char)0b00000100//100 COMMAND #define _DRD_SIGID (unsigned char)0b00000110//110 READ #define _DWD_SIGID (unsigned char)0b00000101//101 WRITE //コマンドコード //最後に1bitのダミーデータを噛ませること #define _CMD_SYSEN (unsigned char)0b00000001//内蔵オシレータ起動 #define _CMD_LCDON (unsigned char)0b00000011//LCDバイアスジェネレータ起動 #define _CMD_TOPTM (unsigned char)0b11100000//Test Mode? //1/2 BIASモード #define _CMD_BIAS2_2C (unsigned char)0b00100000//2 commons #define _CMD_BIAS2_3C (unsigned char)0b00100100//3 commons #define _CMD_BIAS2_4C (unsigned char)0b00101000//4 commons void pinSetup(){ //CS初期化 pinMode(_PIN_CS, OUTPUT); digitalWrite(_PIN_CS, HIGH); //RD初期化 //pinMode(_PIN_RD, OUTPUT); //digitalWrite(_PIN_RD, HIGH) //WD初期化 pinMode(_PIN_WD, OUTPUT); digitalWrite(_PIN_WD, HIGH); //DATA初期化 pinMode(_PIN_DA, OUTPUT); digitalWrite(_PIN_DA, HIGH); } void writeSerialLine(unsigned char len, unsigned char data){ unsigned char _D; for(unsigned char i=len; i!=0; i--){//ID送信 _D = (unsigned char)( (data&(1<<(i-1))) >> (i-1) ); digitalWrite(_PIN_DA, (_D ? HIGH : LOW));//データセット digitalWrite(_PIN_WD, LOW);//WD立ち下げ delayMicroseconds(_CLK_DELAY);//半クロック待つ digitalWrite(_PIN_WD,HIGH);//WD立ち上げ delayMicroseconds(_CLK_DELAY);//半クロック待つ } } void transmit(unsigned char id,unsigned char cmd,unsigned char data){ //データ送信開始 delayMicroseconds(_CLK_DELAY);//連続して読んだ時のために最初にウェイトを入れておく digitalWrite(_PIN_CS, LOW);//CSを下げてデータ転送を開始 delayMicroseconds(_CLK_DELAY);//半クロック待つ writeSerialLine(3, id);//ID送信 switch(id){//オペランド処理 case _CMD_SIGID://コマンドの場合 writeSerialLine(8, cmd);//コマンド writeSerialLine(1, 0x00);//ダミーデータ case _DRD_SIGID://読み込みの場合 //writeSerialLine(5, cmd); //readSerialLine(4, data); case _DWD_SIGID: writeSerialLine(5, cmd & 0b00011111);//アドレス writeSerialLine(4, data & 0b00001111);//データ } digitalWrite(_PIN_CS, HIGH); } void initCmd(){ transmit(_CMD_SIGID, _CMD_SYSEN, 0x00); transmit(_CMD_SIGID, _CMD_LCDON, 0x00); //transmit(_CMD_SIGID, _CMD_TOPTM, 0x00); transmit(_CMD_SIGID, _CMD_BIAS2_2C, 0x00); } void testPrint(){ for(unsigned char c=0;32>c;c++){ transmit(_DWD_SIGID, c, 0b00001111); } } void setup() { pinSetup(); initCmd(); testPrint(); } void loop() { // put your main code here, to run repeatedly: }
m9(^Д^)
しかし動かない… ナンデ?
_D
をシリアルポートに吐き出してみたら数ビット余計に何か出力されてる…?
よく見たらswitch
の分岐にbreak
入ってないからフォールスルー起こしてらハハハ
入れてみたら正しい値が出力された
しかしそれでも動かない
そもそもロジックが駆動してない…?
シリアルに必死に値吐き続けても全然原因が突き止められない
タイミングは当っているはず…CSも動かしてるしWDもOK…クロックレートも遅いくらい…
コマンドの順番? それともバイアスの設定が悪い?
色々悩んであれやこれややってたらなんか薄らと画面が出てきたような…?
やったか?
もっとデバッグしてもっとミス見つけてた(6bit送信が5bit送信になってたりetc)なんとか駆動できた!!
ヤッター!!嬉しい!!
最終的にコードはこうなった:
/* HT1621B Controling Test */ //ピン定義 #define _PIN_CS 4 #define _PIN_RD 0 #define _PIN_WD 6 #define _PIN_DA 8 //クロックディレイ(MicroSec,1/2クロック) #define _CLK_DELAY 20 //シグナルID #define _CMD_SIGID (unsigned char)0b00000100//100 COMMAND #define _DRD_SIGID (unsigned char)0b00000110//110 READ #define _DWD_SIGID (unsigned char)0b00000101//101 WRITE //コマンドコード //最後に1bitのダミーデータを噛ませること #define _CMD_SYSDS (unsigned char)0b00000000//内蔵オシレータ&バイアスジェネレータ無効化 #define _CMD_SYSEN (unsigned char)0b00000001//内蔵オシレータ%バイアスジェネレータ起動 #define _CMD_LCDON (unsigned char)0b00000011//LCDバイアスジェネレータ起動 #define _CMD_RCOCL (unsigned char)0b00011000//内部オシレータ選択 //1/2 BIASモード #define _CMD_BIAS2_2C (unsigned char)0b00100000//2 commons #define _CMD_BIAS2_3C (unsigned char)0b00100100//3 commons #define _CMD_BIAS2_4C (unsigned char)0b00101000//4 commons //1/3 BIASモード #define _CMD_BIAS3_2C (unsigned char)0b00100001//2 commons #define _CMD_BIAS3_3C (unsigned char)0b00100101//3 commons #define _CMD_BIAS3_4C (unsigned char)0b00101001//4 commons void pinSetup(){ //CS初期化 pinMode(_PIN_CS, OUTPUT); digitalWrite(_PIN_CS, HIGH); //RD初期化 //pinMode(_PIN_RD, OUTPUT); //digitalWrite(_PIN_RD, HIGH) //WD初期化 pinMode(_PIN_WD, OUTPUT); digitalWrite(_PIN_WD, HIGH); //DATA初期化 pinMode(_PIN_DA, OUTPUT); digitalWrite(_PIN_DA, HIGH); } void writeSerialLine(unsigned char len, unsigned char data){ unsigned char _D; for(unsigned char i=len; i!=0; i--){//ID送信 _D = (unsigned char)( (data&(1<<(i-1))) >> (i-1) ); //_D = (unsigned char)( (data>>(len-i)) & 0x01 ); digitalWrite(_PIN_DA, (_D ? HIGH : LOW));//データセット //Serial.print("DATA:"); //Serial.flush(); //Serial.print((_D ? HIGH : LOW)); //Serial.flush(); digitalWrite(_PIN_WD, LOW);//WD立ち下げ //Serial.print("WD:LOW"); //Serial.flush(); delayMicroseconds(_CLK_DELAY);//半クロック待つ //Serial.println("3us Wait"); //Serial.flush(); digitalWrite(_PIN_WD, HIGH);//WD立ち上げ //Serial.print("WD:HIGH"); //Serial.flush(); delayMicroseconds(_CLK_DELAY);//半クロック待つ //Serial.println("3us Wait"); //Serial.flush(); } } void transmit(unsigned char id,unsigned char cmd,unsigned char data){ //データ送信開始 //Serial.println("3us Wait"); //Serial.flush(); delayMicroseconds(_CLK_DELAY);//連続して読んだ時のために最初にウェイトを入れておく digitalWrite(_PIN_CS, LOW);//CSを下げてデータ転送を開始 //Serial.print("CS:LOW"); //Serial.flush(); delayMicroseconds(_CLK_DELAY);//半クロック待つ //Serial.println("3us Wait"); //Serial.flush(); writeSerialLine(3, id);//ID送信 switch(id){//オペランド処理 case _CMD_SIGID://コマンドの場合 writeSerialLine(8, cmd);//コマンド writeSerialLine(1, 0x00);//ダミーデータ break; case _DRD_SIGID://読み込みの場合 //writeSerialLine(5, cmd); //readSerialLine(4, data); break; case _DWD_SIGID: writeSerialLine(6, cmd & 0b00111111);//アドレス writeSerialLine(4, data & 0b00001111);//データ break; } digitalWrite(_PIN_CS, HIGH); } void initCmd(){ transmit(_CMD_SIGID, _CMD_SYSDS, 0x00);//待機電力でRAMの値を保持するっぽいから一回終了させてやる transmit(_CMD_SIGID, _CMD_SYSEN, 0x00);//オシレータ&バイアスジェネレータ起動 transmit(_CMD_SIGID, _CMD_RCOCL, 0x00);//クロックジェネレータに内部オシレータを指定 transmit(_CMD_SIGID, _CMD_BIAS3_4C, 0x00);//バイアスモードセット(1/3-4commons) transmit(_CMD_SIGID, _CMD_LCDON, 0x00);//LCDのバイアスジェネレータ起動(不要?) } void testPrint(){ for(unsigned char c=0;32>c;c++){ transmit(_DWD_SIGID, c, 0x00);//塗り潰し } } void setup() { //Serial.begin(9600); pinSetup();//ピン設定 initCmd();//初期化 testPrint();//ピン書き込み } void loop() {//1bitずつ増やしていく // put your main code here, to run repeatedly: for(int c=0;16>c;c++){ for(int i=0;16>i;i++){ transmit(_DWD_SIGID, c, i); delay(25); } } for(int c=0;64>c;c++){ transmit(_DWD_SIGID, c, 0x00); } }
適当実装だから多分色々間違ってる(データ書き込みが逆さになってたりSYS_EN
だけで十分っぽかったり)けど
動いたからとりあえず一段落
やっぱり自分で動かすのって楽しい(死んだ目で)
たぶんつづく
参考にしたページ
[失敗]mrubyでAitendo 99円液晶 - Qiita
ここで99円液晶の存在を知った
Overview | Introducing Pro Trinket | Adafruit Learning System
Adafruit公式のTriknetProのページ
Arduino 日本語リファレンス
Arduinoリファレンスの和訳
Arduino のすすめ
Arduinoのピンの役割や使い方について
オームの法則
LEDの抵抗について
LEDの抵抗値計算
LEDの抵抗値計算器
morecat_lab » Segment LCDを試す
ピンアサインについて
VikiWiki - TS119-5
謎の7番ピンについて
TN液晶8セグモジュールを使う
駆動電圧について(3V3でもOK)
ハム三昧: LCD-TS174をPICによりドライブ
クロックサイクルの最低値について
LCDのバイアスについて(pdf注意)
99%おぼえ書き: TS119-3 制御デモ スケッチ
モードコマンドの順番について(結局他人のライブラリ見てしまった…)