12セグメント カナフォントをハード化する
写真で見ると文字が白とびしちゃうので露出補正で暗くしていますが、実際は明るい部屋でも綺麗に表示されます。
3ヶ月前ぐらいに見かけたとあるツイート
突然脳がなんかを受信して、こんな12セグメントのカタカナのフォントを思いつきました
— ByNEET (@ByNEET) 2019年1月7日
読めるか読めないかギリギリのライン。 pic.twitter.com/WN5AAEAu7z
やってみよう
回路図
当初、8ビットシフトレジスタ 74HC595 を2個使い、各セグメントを2個のLEDで点灯するよう回路図とアートワークを作ったのですが、どうせこれカラー表示したくなるよね、ということで WS2812B に変更。
基板1枚に WS2812B を24個(各セグメント2個×12セグメント)。数珠つなぎになった信号線の両端にコネクタを配置し、基板同士を連結できるようにします。
基板アートワーク
基板外形
基板が安く作れる最大寸法 100mm×100mm に収めます。
A面
B面
部品が15°単位で傾いているのでグリッドをかなり細かくしないと思い通りのところに置けません。
基板入荷
A面
B面
この12セグメントの表示形式に名前は付いていないようなので、基板名は SnowCrystal としました。
部品実装
スペーサー
各セグメントの形状を出すためのスリット兼LEDの光を均一にするスペーサーです。
高さは 10mm, 15mm, 20mm の3種類を試したところ、15mmが良さそうでした。
3Dプリンタで出力。基板に重ねてネジどめ。
Arduino で点灯させる
スケッチの一部
#define NUM_DIG 5 // 接続した文字数 #define NUM_SEG 12 // ディジットあたりのセグメント数 #define NUM_PPS 2 // 各セグメントに使用するWS2812Bの数 Pixels Per Segment #include <Adafruit_NeoPixel.h> Adafruit_NeoPixel pix = Adafruit_NeoPixel(NUM_PPS * NUM_SEG * NUM_DIG, PIN_PIX, NEO_GRB + NEO_KHZ800);
dig番の文字の seg番のセグメントを rgb色 にセット
void set_seg(uint8_t dig, uint8_t seg, uint32_t rgb) { for (uint8_t i = 0; i < NUM_PPS; i++) { pix.setPixelColor(NUM_PPS * NUM_SEG * dig + NUM_PPS * seg + i, rgb); } }
dig番の文字に patternの文字を rgb色 にセット
void set_dig(uint8_t dig, uint16_t pattern, uint32_t rgb) { for (uint8_t seg = 0; seg < NUM_SEG / 2; seg++) { set_seg(dig, seg, pattern >> (13 - seg) & 1 ? rgb : 0); } for (uint8_t seg = NUM_SEG / 2; seg < NUM_SEG; seg++) { set_seg(dig, seg, pattern >> (11 - seg) & 1 ? rgb : 0); } }
フォントを作る
const PROGMEM uint16_t font_map[256] = { 0, // 0 0, // 1 /* 中略 */ 0, // 46 0, // 47 B000111 << 8 | B100100, // 48 0 B000001 << 8 | B100100, // 49 1 B101101 << 8 | B010010, // 50 2 B101101 << 8 | B011000, // 51 3 B000010 << 8 | B100110, // 52 4 B101100 << 8 | B101000, // 53 5 B101111 << 8 | B001010, // 54 6 B000011 << 8 | B100100, // 55 7 B101101 << 8 | B011011, // 56 8 B111101 << 8 | B010001, // 57 9 /* 中略 */ 0, // 175 0, // 176 B100001 << 8 | B110100, // 177 ア B000000 << 8 | B010110, // 178 イ B011010 << 8 | B110001, // 179 ウ B001100 << 8 | B010101, // 180 エ B000000 << 8 | B110111, // 181 オ B010000 << 8 | B110110, // 182 カ B100001 << 8 | B101110, // 183 キ B100001 << 8 | B010010, // 184 ク B000011 << 8 | B001101, // 185 ケ B000100 << 8 | B000101, // 186 コ B000010 << 8 | B110110, // 187 サ B101100 << 8 | B000001, // 188 シ B000001 << 8 | B101100, // 189 ス B001000 << 8 | B110110, // 190 セ B011000 << 8 | B000001, // 191 ソ 0, // 192 0, // 193 /* 中略 */ 0, // 254 0, // 255 };
1バイトカナ文字(半角カナ)を Serial.println()
すると戻りは3バイトなので、下位1バイトを使って font_map
の配列からパターンを取り出す
uint16_t font(byte ascii) { return pgm_read_word(&font_map[ascii]); }
byte code = 'ア'
としたときに、「ア」の下位1バイトだけ取り出して変数 code に代入してくれれば良いのですが、narrowing conversion
のエラーが出るPCとコンパイルが通るPCがあります。キャスト面倒だから通して欲しいんだけど何が違うんだろう?
紙を被せて完成
2mmの白いアクリルでは、滲んでピンボケみたいになってしまいました。
アクリルをコピー用紙に変えたらシャキッと表示できました。
まとめ
while 文の無限ループが含まれているのでスケッチの全文公開はやめとこ(笑)
フォントのパターンは、こちらのブログで紹介されているものを再現しています。
12セグメントカタカナフォント|ニートが頑張るブログ