ArduinoでTM1640を使ってみた
3ヶ月ほど前に秋月で取り扱いが始まったTM1640という7セグメントLED用のドライバICをArduinoで使ってみた
7セグメント用LEDドライバーIC(最大16個) TM1640: 半導体 秋月電子通商-電子部品・ネット通販
TM1640
マイコンからデータを書き込んでやれば自動でダイナミック点灯してくれる便利なICです
7セグメントLED(ドット含めて8セグメント)を最大16個まで制御することができます
構造上アノードコモンでもカソードコモンでもどちらでも問題なさそうです
ドットマトリクスLED
今回は結線が面倒なので7セグメントLEDではなくドットマトリクスLEDを点灯させることにしました
ドットマトリクスLEDのピンアサインがバラバラに配置されていて結構面倒でした
結線は大して複雑ではなくSEGxはアノード、GRIDxはカソードに接続するだけであとはマイコンにクロックとデータの入力を接続するだけで終わります
ライブラリ
TM1640の制御ライブラリは一応あることはあるのですがTM1638の派生としてあって7セグメントLEDに特化したものだったのでドットマトリクスでも制御できるように作りました
クロックもデータも何もないときはHIGHにしておき送信するときは一度データをLOWに落としてからクロックに合わせてアドレスや表示データを送信します
最初そこに気づかなかったため1時間ぐらい光らねえなあと悩んでしまいました
あと一部のドットを光らせようと一列だけの書き換え時になぜかほかの列のドットまで光る現象が見られました
よくわからないので全て書き換えることで誤魔化しました
光らせた
とりあえず顔っぽいのを配列で用意して表示してみました
かわいい(*´∇`*)
8x8のドットマトリクスLEDなので8x16の場合や一応7セグメントLEDのも書いて動くとは思いますが動作確認はしてません…
サンプルコード
そのうちどっかに上げたいと思いますがとりあえず面倒なので以下に記載
MyTM1640.hとMyTM1640.cppを以下のサンプルコードの保存場所に追加してあげると動きます
#define CLKPIN 7 #define DATPIN 8 #include "MyTM1640.h" MyTM1640 dots(CLKPIN,DATPIN,7); void setup() { Serial.begin(115200); dots.clear(); } int i = 0; void loop() { dots.setDot(i%8,(i%64)/8,(i<64)?1:0); dots.show(); i=(i+1)%128; }
MyTM1640.h
#ifndef MyTM1640_h #define MyTM1640_h #include "Arduino.h" class MyTM1640 { public: MyTM1640(byte PIN_DAT, byte PIN_CLK, byte brightness); virtual void setBrightness(int brightness); virtual int getBrightness(); //Dot Matrix LED virtual void setDot(byte x, byte y, byte dot); virtual void setLine(byte x, byte line); //7Segment LED virtual void setNum(int num,int x); virtual void show(); virtual void clear(); private: virtual void send(byte data); virtual void sendData(byte addr, byte data); virtual void sendCmd(byte cmd); byte _pin_dat; byte _pin_clk; byte brightness; byte data[16]; byte font[16] = { 0b00111111,//0 0b00000110,//1 0b01011011,//2 0b01001111,//3 0b01100110,//4 0b01101101,//5 0b01111101,//6 0b00100111,//7 0b01111111,//8 0b01101111,//9 0b01110111,//a 0b01111100,//b 0b00111001,//c 0b01011110,//d 0b01111001,//e 0b01110001 //f }; }; #endif
MyTM1640.cpp
#include "MyTM1640.h" #include "Arduino.h" MyTM1640::MyTM1640(byte PIN_CLK, byte PIN_DAT, byte brightness) { this->_pin_dat = PIN_DAT; this->_pin_clk = PIN_CLK; this->brightness = brightness; pinMode(PIN_CLK, OUTPUT); pinMode(PIN_DAT, OUTPUT); digitalWrite(PIN_CLK, HIGH); digitalWrite(PIN_DAT, HIGH); sendCmd(0x40); sendCmd(0x8f); clear(); }; void MyTM1640::setBrightness(int brightness) { sendCmd(0x88 | min(7, brightness)); } int MyTM1640::getBrightness(){ return min(7, brightness); } void MyTM1640::setDot(byte x, byte y, byte dot) { if ((0x1 & dot) == 1) { data[x] |= 0x1 << y; } else { data[x] &= ~(0x1 << y); } } void MyTM1640::setLine(byte x, byte line) { data[x] = (byte)line; } void MyTM1640::show() { sendCmd(0x40); digitalWrite(_pin_dat, LOW); send(0xC0); for (int i = 0; i < 16; i++) { send(data[i]); } digitalWrite(_pin_dat, HIGH); } void MyTM1640::setNum(int num,int x) { MyTM1640::setLine((byte)num,MyTM1640::font[x]); } void MyTM1640::send(byte data) { for (int i = 0; i < 8; i++) { digitalWrite(_pin_clk, LOW); digitalWrite(_pin_dat, data & 1 ? HIGH : LOW); data >>= 1; digitalWrite(_pin_clk, HIGH); } } void MyTM1640::sendCmd(byte data) { digitalWrite(_pin_dat, LOW); send(data); digitalWrite(_pin_dat, HIGH); } void MyTM1640::clear() { sendCmd(0x40); digitalWrite(_pin_dat, LOW); send(0xC0); for (int i = 0; i < 16; i++) { send(0x00); } digitalWrite(_pin_dat, HIGH); } void MyTM1640::sendData(byte addr, byte data) { //Fixed Mode sendCmd(0x44); digitalWrite(_pin_dat, LOW); send(0xc0 | addr); send(data); digitalWrite(_pin_dat, HIGH); }
追記
2018/08/24
7セグメントLEDで表示させてみたところフォントのビットの上下が逆だったのと関数名setCharはどう考えても数値をセットしてたのでsetNumに修正しました
種類にもよるかもしれないが最高輝度で光らせていると電流不足か何かで落ちた…
MacBook Proからの給電なのでその影響かも?