フォト
2019年9月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          
無料ブログはココログ

表示器制御関連

2019年8月 2日 (金)

SSD1322搭載3.12インチ OLEDの動作確認

AliexpressでコントローラSSD1322搭載 3.12インチ OLEDディスプレイを入手しました。

入手サイト
TZT Real OLED Display 3.12" 256*64 Dots Graphic LCD Module Display Screen LCM Screen SSD1322 Controller Support SPI
01_20190802090601

$20.70と少々お高いですが、以前に比べるとお手頃な価格になってきました。

実際の製品

届いた製品です。0.96インチ(上)と比較するとやはり大きいです。
Dscn1942

マニュアル類の付属がないため、製品販売ページの情報をもとに使い方は調べる必要があります。
購入先の業者に問い合わせても良いと思います。


製品仕様について

てっきりモノクロ(単色)だと思っていたのですが、
SSD1322の仕様を調べると、1ドット当たり4ビットの16階調表示でした。
256x64ドット、1ドットあたり4ビットのためバッファを使う方式でのプログラム実装では
バッファサイズは8kバイト必要となります。

2x16のピンヘッダでの接続となります。
インタフェースとしては、SPIの他にパラレル接続も可能です。
Photo_20190802094501
デフォルトではパラレル接続モードになっています。
裏のシルク印刷の設定をみてSPI(4SPI)接続に変更しました(R6の抵抗を取ってR5につける)。
Dscn1976

SPI(4SPI)で利用する場合、モジュールのピンヘッダのうち、下記のピンを利用します。
(Reset、CS、DCはArduinoの任意のピンでOK)
02_20190802094201
Arduinoでの動作確認

利用ライブラリ

ググって探して、次のライブラリを試してみました。
1) U8glib V2 library for Arduino
    https://github.com/olikraus/U8g2_Arduino
2) Arduino library for 256x64 OLED ER-OLED032-1 (SSD1322 driver)
    https://github.com/cvonk/arduino-SSD1322

接続はこんな感じです。
Dscn1977
結論を先に述べると、1)のU8glibの利用がお勧めです。
16階調表示には対応していないですが、フレームバッファ使わない方式にも対応しています。
下記の画像はU8glibを使った動作です。

Dscn1961
Dscn1965
Dscn1966
表示がとても綺麗です。文字の表示にも、もちょうど良いサイズです。

U8glibのサンプルスケッチをコンパイルする使う場合、コメントアウトされている下記を有効にします。
   U8G2_SSD1322_NHD_256X64_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); // Enable U8G2_16BIT in u8g2.h

U8glibでも、フルサイズのバッファを使う場合、バッファサイズとして2kバイトが必要です。
Arduino Unoでは利用出来ません。Arduino MEGA2560で利用出来ました。

SPI接続では、OLEDモジュールからの表示内容の読み出しが出来ないため
表示している内容に追記するような場合は、Arduino側でバッファが必要となります。
バッファを使いない場合、グラフィック描画時に制約が発生します。

2)のライブラリはAdafruit_SSD1306がベースのライブラリなのですが、
古いAdafruit_GFXを使っているためか、Adafruit_GFXのメンバ変数参照でコンパイルエラーが
発生し、ライブラリソースの修正が必要でした(このあたりの対応は省略します)。

さらにバッファとして最低2kバイト(単色利用時)が必要です。Arduino Unoでは利用出来ません。
Arduino MEGA2560ではとりあえず動きました。

Dscn1970

16階調での利用は、バッファサイズ8kバイトが必要なため、Arduino MEGA2560でも利用出来ませんでした。


まとめ

このSSD1322搭載の本製品、ドットサイズが256x64、16階調、表示が綺麗で見やすいのです。
文字を表示にも適したサイズです。
ただし、16階調(1ドット4ビット)は、メモリ消費が多くなり、ちょっと使いにくいです。

16階調の表示の評価として、何か写真っぽいのを表示を試して見たいと思います。

2019年7月 8日 (月)

4連8x8ドットLEDマトリックスを試してみる 続編(2)

以前書いた記事「4連8x8ドットLEDマトリックスを試してみる 続編」に関して
スクロール表示ではなく、固定メッセージを表示したいとの質問があり、ちょっとやってみました。

ハードウェア構成は、前回のSDカードモジュールを使わず、SDカードシールドを使っています。
この方が結線が楽ちんですね。SDカードシールドは意外と安いです。

Dscn1883

動作している様子



スケッチ: ダウンロード - max7219_test3a.zip

  別途自作ライブラリ sdfonts を利用しています。
   ・sdfonts : Arduino用漢字フォントライブラリ SDカード版
     https://github.com/Tamakichi/Arduino-KanjiFont-Library-SD


スケッチを直接貼り付けて掲載したかったのですが、
ArduinoのHTML形式コピーのスケッチを貼るとココログの編集画面が100%暴走するようになり、
掲載出来なくなってしまいました。
まだまだ、リニューアルの後遺症が残っているようです。

代わりに、GitHub(gist)を使って掲載します。


追記

このスケッチで利用している、ビットマップ操作を行う処理、
機能強化&ライブラリ化してGitHubに登録していたことをすっかり忘れていました。
しかも、マニュアルを作成せず、登録しただけ...

 ・Arduino ビットマップ操作ライブラリ
    https://github.com/Tamakichi/libBitmap

暇をみて、ドキュメントを追記しますです。

2019年7月 7日 (日)

豊四季タイニーBASIC for Arduino機能拡張版の修正中(4)

豊四季タイニーBASIC for Arduino機能拡張版(+ VFD MW25616L対応)の修正、
前回から、美咲フォントの漢字選定の変更やらダイエットやらを行いましした。
(コード見直しで500バイトくらいダイエット出来たのですが、機能追加で差し引き0です)

・Tamakichi/ttbasic_MW25616L
   ブランチ(随時更新) https://github.com/Tamakichi/ttbasic_MW25616L/tree/update_to_v007

見た目的には、前回とあまり変わらないのですが、修正で"埼玉"が表示出来るようになりました。

動いている様子



プログラム


10 NINIT ARRAY,64
20 NBRIGHT 1
30 FOR N=1 TO 5
40 C=RND(255)
50 FOR I=0 TO 3
60 NCLS 0
70 NLINE I,I,7-I,7-I,C,1
80 WAIT 150
90 NEXT
100 NEXT
110 NMSG 80,RGB(7,0,0),"こんにちは、埼玉♪"
120 NMSG 80,RGB(0,0,3),"今日は、7月7日です。"
130 GOTO 30


色々と悩んだ挙句、次のフォントを選定しました。
年号、季節、時刻、天気、方向、単位、地形、色を強化しました。

01_20190707203001

フォントは約5kバイト容量を喰うため、他の機能をOFFにする必要があります。
オプション指定で、フォントの利用を無効にすることも出来ます。

また、英数記号・カタカナ・ひらがな 288文字のみ利用可能とするオプション指定も
用意しました。この場合は3kバイト程度の消費となります。

NeoPixel制御はこれくらいにして、次はタイマー割り込み機能に着手します。


2019年6月27日 (木)

豊四季タイニーBASIC for Arduino機能拡張版の修正中(3)

豊四季タイニーBASIC for Arduino機能拡張版(+ VFD MW25616L対応)の修正中です。
前回から、さらにNeoPixcelを制御するコマンドを追加しました。

・Tamakichi/ttbasic_MW25616L
   ブランチ(随時更新) https://github.com/Tamakichi/ttbasic_MW25616L/tree/update_to_v007

02_20190627200601

NeoPixel的には1個のLEDあたり、24ビット色なのですが、今回は、メモリ制約等を考慮して、8ビット色としました。
また制御できるLEDは最大で64個までとしました。

NeoPixelのリボン・スティック形状(ストレート)、リング形状、8x8ドットマトリックス形状に対応しました。

追加コマンド(×は未実装、いずれ対応する予定)
 補足: コマンドの更新flgは、デフォルト値が1、0を指定した場合はバッファへの書き込みのみで、表示に反映しません。
         NUPDATEで、バッファ内容を表示に反映出来ます。

■ 初期設定
   NINIT バッファアドレス,ピクセル数
   バッファアドレスには、仮想アドレスを指定します。1ピクセルあたり1バイト必要です。

■ 輝度設定
   NBRIGHT 輝度
   輝度は0(低)~5(高)の範囲で指定します。

■ 表示クリア
   NCLS [更新flg]

■ 指定LEDの色設定
   NSET 番号,色[,更新flg]
   番号はLEDのピクセル番号(0~)、色は0~255(RGB関数を使うと便利)

■ 8x8マトリックスの指定位置にピクセル設定
   NPSET X,Y,色[,更新flg]

■ 8x8マトリックスにメッセージ文表示
   NMSG 色,速度,メッセージ文
   速度はスクロール時のウェイト時間(ミリ秒単位)

■ 8x8マトリックスを指定方向に1ピクセルスクロール
   NSCROLL 方向[,更新flg]

■ 8x8マトリックス ライン描画
   NLINE X1,Y1,X2,Y2,色[,モード] [,更新flg]
   モードは、0:直線(デフォルト)、1:矩形、2:矩形塗りつぶし

■ バッファ表示反映
  NUPDATE

■ LEDの表示をシフト
   NSHIFT 方向[,更新flg]
   LEDの表示を1つずらします。
   先頭のLEDの色は最後尾のLEDに設定されます。ループとなります。

■ 8ビット色コード取得
  RGB(赤,青,緑)

■ 8x8マトリックス 指定座標色コード取得
  NPOINT(X,Y)

結線


NeoPixel


Arduino


1 VDD


5V


2 DOUT


(未接続)


3 VSS(GND)


GND


4 DIN


MOSI(11ピン)



NeoPixelを制御するプログラムの例

01_20190627201201

動いている様子

色々とメッセージを表示してみたのですが、
やはり、文字が足りません。漢字はもう少し選定を見直す必要があります。

まだまだ、色々とと見直し中です。
う~ん、メモリが足りず中々厄介です。


追記 2019/06/28

1メートル 30個LED搭載テープ(リボン)を制御してみました。

Dscn1862

プログラムで2点(赤と青)を往復運動させています。



プログラムはこんな感じです。


10 NINIT MEM,30
20 NBRIGHT 5
30 NCLS
40 NSET 0,RGB(0,0,3)
50 NSET 1,RGB(7,0,0)
60 N=0:D=0
70 NSHIFT D
80 N=N+1
90 IF N=28 N=0:IF D=0 D=1 ELSE D=0
100 WAIT 30
110 GOTO 70

10行で、NeoPixel用のメモリ領域として、仮想アドレスMEMから30個分30バイトを確保しています。
20行で、輝度を最大の5にしています。
30行で、念のためすべての表示をクリア
40行、50行で0番目、1番目のLEDに青、赤の色を設定して表示しています。
60行のNはNSHIFTコマンドの実行回数のカウント用、DはNSHIFTの方向引数です。
70行のNSHIFT Dは、LEDの表示を前または後ろに1つ分移動します。
80行で移動数をカウント、
90行で方向転換するための判定と、方向Dの値を逆方向に設定しています。
100行はウェイト
110行は70行にジャンプして繰り返し表示

プログラム次第で色々と面白い動き、表示が出来ると思います。

追記 2019/06/29 

1メートル 30個LED搭載テープ(リボン)制御のその2です。
全LEDを一括更新する例として、全LEDを0.5秒間隔で赤、緑、青と変化させています。

Dscn1864

動いている様子



プログラムはこんな感じです。


10 NINIT MEM,30:NBRIGHT 3
20 NCLS
30 @(0)=RGB(7,0,0),RGB(0,7,0),RGB(0,0,3)
40 C=0
50 FOR I=0 TO 29
60 NSET I,@(C),0
70 NEXT I
80 NUPDATE
90 C=C+1:IF C=3 C=0
100 WAIT 500
110 GOTO 50

50行~70行で全LEDの色を設定しています。
60行のNSET I,@(C),0 で各LEDの色の設定をしているのですが、
3番目の引数の0を指定することで、バッファのみの書き込みとなります。
80行のNUPDATEで一括してバッファの内容をNeoPixelに反映させています。

60行は、次の処理と等価です。
 POKE MEM+I,@(C)
10行のNINITで指定したアドレスのデータに直接値を設定して、
NUPDATEで表示に反映させることも出来ます。


上記に、輝度制御を追加したバージョン



プログラムはこんな感じです。


10 NINIT MEM,30:NBRIGHT 0
20 NCLS
30 @(0)=RGB(7,0,0),RGB(0,7,0),RGB(0,0,3)
40 C=0
50 FOR I=0 TO 29
60 NSET I,@(C),0
70 NEXT I
80 NUPDATE
90 C=C+1:IF C=3 C=0
100 WAIT 200
110 FOR I=1 TO 5:NBRIGHT I:NUPDATE:WAIT 200:NEXT I
120 NBRIGHT 0:NUPDATE
130 GOTO 50

110行~120行で輝度を変化させる処理を行っています。
NBRIGHTコマンドで輝度を指定します。表示への反映はNUPDATEの実行します。

NBRIGHTコマンドはちょっと見直そうと思います。
 ・NUPDATEを呼び出さずに、表示に反映
 ・輝度を-3 ~ 5 として、マイナス値で減光出来るようにする

2019年6月 1日 (土)

Arduino STM32でキャラクタ液晶ディスプレイを使う

現在ちびちびと Arduino STM32 リファレンス 日本語版 を整備しているにですが、
今回、標準ライブラリの LiquidCrystalライブラリの部分を追記しました。

このライブラリはHD44780コントローラ(互換品含む)を使った
キャラクタ液晶ディスプレイ用のライブラリです。

動作確認として、実際にBluePillボードで制御してみました。

02_5  

利用したキャラクタ液晶ディスプレイ
1602A-V2aitendoでも販売されています)
   表示文字数 16桁×2行 、バックライト付きSTN液晶ディスプレイ
   Aliexpressでは、2ドル以下で購入出来ます。

久しぶりに、パラレル接続のキャラクタ液晶ディスプレイを使いました。
色々と忘れていて、コントラスト調整に戸惑ってしまいました。

今回はとりあえず、4ビットモードで利用しました。
動作電源が5Vのため、BluePillボードの5Vで利用可能なピンを利用しました。
下記がその結線です。

結線表

1602A-V2端子 接続先 備考
VSS BluePill - GND  
VDD BluePill - 5V  
V0 20kΩ半固定抵抗(GND接続) コントラスト調整用
RS BluePill - PA8 5Vトレラントピン利用
RW BluePill - GND LOW(GND)でWモード固定
E BluePill - PA9 5Vトレラントピン利用
D0 (未接続)  
D1 (未接続)  
D2 (未接続)  
D3 (未接続)  
D4 BluePill - PB6 5Vトレラントピン利用
D5 BluePill - PB7 5Vトレラントピン利用
D6 BluePill - PB8 5Vトレラントピン利用
D7 BluePill - PB9 5Vトレラントピン利用
A BluePill - 5V バックライトLED用
K BluePill - GND バックライトLED用


動作確認に利用したスケッチ

#include <LiquidCrystal.h>
#define LCD_RS  PA8
#define LCD_E   PA9
#define LCD_D4  PB6
#define LCD_D5  PB7
#define LCD_D6  PB8
#define LCD_D7  PB9
uint8_t font[]= {
  0b00001010,
  0b00001110,
  0b00011111,
  0b00010101,
  0b00011111,
  0b00011111,
  0b00001110,
 0b00000000,
};
LiquidCrystal lcd(LCD_RS,LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
void setup() {
  lcd.begin(16, 2);
  lcd.createChar(1,font);
  lcd.clear();
  lcd.cursor();
  lcd.blink();
  lcd.setCursor(0, 0);
  lcd.print("Hello, world!");
  lcd.setCursor(0, 1);
  lcd.print("\xc8\xba\x20\xc6\x20\xba\xdd\xca\xde\xdd\xdc\x01");
}
void loop() { }

スケッチは、LiquidCrystalクラスのインスタンス lcd をピン割り付けを指定して生成し、
begin()にて利用開始します。

4ビットモードだと結線数も少なく、割と簡単に制御出来ます。

LiquidCrystalライブラリ は、Printクラスの派生クラスのため、
Serialオブジェクトのような感じで、print()関数が利用出来ます。
数値等の出力も簡単に出来ます。

写真の 「ネコ ニ ホンバンワ」の半角カタカナ表示の部分は、
Arduino IDE環境の文字コードUTF-8コードのため、文字列をそのまま記述することはできません。
UTF-8で半角カタカナ1文字は、3バイトに置き換えられてしまい文字化けします。
ですので、文字コードを16進数表記で記述しています。

また、猫っぽいアイコンは、CGRAM領域にフォントデータを登録して表示しています。
CGRAM領域には、最大8文字(5x8ドット)登録することが出来ます。
lcd.createChar(1,font)にてその登録を行っています。
登録した文字は文字コード0~7にて指定出来ます。
(ただし、文字コード0は文字列終端子と被るのでwrite()で書く必要あり)

登録するフォントデータは8バイトですが、横5ドットは下位5ビットにて定義します。
縦は実際は7ドットのため、最後の8列目は0を設定します。

参考文献
 ・Adafruit Explore & Learn - Wiring a Character LCD
 ・HD44780U (LCD-II)

2019年3月21日 (木)

BluePillボードで4桁7セグLEDの制御

先日のArduino STM32用タイマー割り込みライブラリを使って、
BluePillボードを使って、4桁7セグLEDをダイナミック点灯にて制御してみました。

Dscn9818

動いている様子



以前、秋月電子で入手して放置していた 4桁7セグLEDはOSL40562-IG を利用しました。
このOSL40562-IGアノードコモンでVFが3.3Vと高く 少々使いにくです。

  ダイナミック接続4桁高輝度緑色7セグメントLED表示器 アノードコモン アノード共通接続 OSL40562-IG

  01


03

とりあえず、次のような回路で駆動させてみました。

02

BluePillボードの5Vトレラント対応のピンを使って駆動させます。
各LEDに流れる電流は5mA程度にしています。
I = (5[V] - Vf[V] ) / 330[Ω]  = (5 - 3.3) /330 = 0.00515[A] ≒ 5[mA]

各桁セグメントDIG1 ~ DIG4は、LED8個分の40mAが流れます。 
BluePillボードでは20mAまでしか流せないため、PNPトランジスタ 2SA1015を使って
駆動させるようにしました。

スケッチ
//
// 4桁高輝度緑色7セグメントLED表示器(アノードコモン) OSL40562-IG の制御
// 2019/03/17 たま吉さん 
// 利用パーツ
//  BluePillボード
//  4桁7セグメントLED  OSL40562-IG x 1
//  桁制御用トランジスタ    2SA1015L-GR x 4
//  LED電流制御用抵抗       330Ω x 8
//  トランジスタベース抵抗  10kΩ x 4
//

#include "TimerEvent.h"

// タイマー割り込み管理
TimerEvent ticker;     
#define REFTIME 4

// デジタルピンの定義
#define DIG1  PB12
#define DIG2  PB13
#define DIG3  PB14
#define DIG4  PB15
#define SEGA  PB3
#define SEGB  PB4
#define SEGC  PB6
#define SEGD  PB7
#define SEGE  PB8
#define SEGF  PB9
#define SEGG  PB10
#define SEGP  PB11

// 桁表示ON・OFF
#define DIG_ON   0
#define DIG_OFF  1

// セグメント表示ON・OFF
#define SEG_ON   0
#define SEG_OFF  1

// セグメントビット定義
#define BIT_A 0b10000000
#define BIT_B 0b01000000
#define BIT_C 0b00100000
#define BIT_D 0b00010000
#define BIT_E 0b00001000
#define BIT_F 0b00000100
#define BIT_G 0b00000010
#define BIT_P 0b00000001

// フォントの定義
const uint8_t font[12] = {
  BIT_A|BIT_B|BIT_C|BIT_D|BIT_E|BIT_F,       // 0
  BIT_B|BIT_C,                               // 1
  BIT_A|BIT_B|BIT_G|BIT_E|BIT_D,             // 2
  BIT_A|BIT_B|BIT_G|BIT_C|BIT_D,             // 3
  BIT_F|BIT_B|BIT_G|BIT_C,                   // 4
  BIT_A|BIT_F|BIT_G|BIT_C|BIT_D,             // 5
  BIT_A|BIT_F|BIT_E|BIT_D|BIT_C|BIT_G,       // 6
  BIT_A|BIT_B|BIT_C,                         // 7
  BIT_A|BIT_B|BIT_C|BIT_D|BIT_E|BIT_F|BIT_G, // 8
  BIT_A|BIT_B|BIT_C|BIT_D|BIT_F|BIT_G,       // 9
  0,                                         // ブランク
  BIT_G,                                     // -
};

// 桁制御ピン
const uint8_t pin_dig[4] = {
  DIG1, DIG2, DIG3, DIG4,
};

// セグメント制御ピン
const uint8_t pin_seg[8] = {
  SEGA, SEGB, SEGC, SEGD, SEGE, SEGF, SEGG, SEGP,
};

// 表示用データ
volatile uint8_t digit[4];

// タイマー割り込み呼び出し関数
void dinamic_update() {
  static uint8_t cnt = 0;
  for (uint8_t i = 0; i < 4; i++)
    digitalWrite(pin_dig[i], DIG_OFF); 
  for (uint8_t i = 0; i < 8; i++)  
     digitalWrite(pin_seg[i], digit[cnt] & (0x80>>i) ? SEG_ON:SEG_OFF);
  digitalWrite(pin_dig[cnt], DIG_ON); 
  cnt++; if (cnt == 4) cnt = 0;
}

// データのクリア
void cls() {
  digit[0] = 0; digit[1] = 0; digit[2] = 0; digit[3] = 0;
}

// 数値の設定
void setNumber(uint16_t n, uint8_t dt = 0) {
  if (n>9999)
    return;

  cls();
  uint8_t dec = 0;
  // 4桁目
  if (n >= 1000) {
    digit[0] =font[ n / 1000]; n = n % 1000; dec = 1;
  }
  // 3桁目
  if (n >= 100) {
    digit[1] = font[n / 100]; n = n % 100; dec = 1;
  } else if (dec) {
    digit[1] = font[0];
  }
  // 2桁目
  if (n >= 10) {
    digit[2] = font[n / 10]; n = n % 10; dec = 1;
  } else if(dec) {
    digit[2] = font[0];
  }
  // 1桁目
  digit[3] = font[n];

  // 小数点
  if(dt && dt <=4) {
    digit[4-dt] |= BIT_P;
  }
}

void setup() { 
  //  桁ピンの初期化
  for (uint8_t i = 0; i < 4; i++) {
    pinMode(pin_dig[i], OUTPUT_OPEN_DRAIN);
    digitalWrite(pin_dig[i], DIG_OFF);
  }

  //  セグメントピンの初期化
  for (uint8_t i = 0; i < 8; i++) {
    pinMode(pin_seg[i], OUTPUT_OPEN_DRAIN);
    digitalWrite(pin_seg[i], SEG_OFF);
  }

  // 表示データの初期化
  for (uint8_t i = 0; i < 4; i++) {
    digit[i] = 0;
  }

  // LEDダイナミック点灯用割り込み設定
  ticker.set(REFTIME, dinamic_update);  // REFTIME間隔で dinamic_update()を呼び出す
  ticker.start();                       // タイマー割り込み実行開始
}

void loop() {
  static uint16_t n = 0;
  setNumber (n,millis()%1000>500?1:0);
  delay(100);
  n++; if (n>9999) n = 0;
}

タイマー割り込みは4m秒間隔で実行させています。
一回の割り込みで4桁のうちの1つを表示させています。
全桁更新周期は 4m秒 x 4 = 16m秒 ≒ 1/60秒 です。
これは、人間の目がちらつきを感じない周期です。
これ以上遅くすると、ちらついて見えます。

電圧を5Vではなく、3.3Vにしても問題なく点灯出来ました。
VF 3.3Vとありますが、実際はもっと低い値のようです。

2019年2月22日 (金)

MSXのジョイスティックポートを使ったシリアル通信 (1)

MSXでジョイスティックポートを使ったシリアル通信が出来るらしいので、
事例を少々調べてみました。

シリアル通信が使えると、パソコンとの通信やArduinoとの連携等が出来るので、
色々とと楽しいことが出来ます。

ジョイスティックポートを使ったシリアル通信の事例

・Joy232
  HAKADAY.IO Print using RS232 on the joystick port of MSX computers
  https://hackaday.io/project/18552-joy232

  github - Danjovic/Joy232
  https://github.com/Danjovic/Joy232

・Akio Hiramatsu's Home Page - MSXでH8内蔵EEPROMを焼く
・FSW倉庫(通信) - アクロバット232

・JoyNet
  まとめサイト http://map.grauw.nl/resources/joynet/

まずは、一番簡単そうなJoy232を試してみました。


Joy232  Print using RS232 on the joystick port of MSX computers

01

joy232は、シリアル通信の出力のみ対応ですが、
BASICのLPRINTコマンドで出力することが出来るので、使い勝手が良いです。

早速試してみました。
ホームページの解説を参考にして、Dサブ9ピン コネクタで通信用コネクタを作りました。

Dscn9652 Dscn9653

USB-シリアル変換モジュールを使ってパソコンとの通信を試してみます。

Dscn9630

ホームページに公開されている、「STEP 1 Method 2」のBASICプログラムを、
MSX1(カシオ PV-7)で実行し、更にテスト用プログラム を実行してみました。

TeraTerm (通信速度 9600bps)にて、受信することが出来ました。

Term

MSXからの出力は、
  LPRINT "Hello,World"

みたいに、LPRINTコマンドで任意のデータを出力出来ます。

意外と簡単に出来ました。色々と遊べそうです。
Arduinoと通信を試そうと思い、
とりあえず、以前作成したLEDマトリックスを試してみました。

Dscn9658

シリアル通信でLEDマトリックスを制御できるモジュールです。
Arduino pro miniに8x8LEDマトリックスを直付けしただけです。
(LEDは定格許容範囲内の短いパルス出力では大きな電流を流せます)

Dscn9656

LPRINT "@?1234567890"
と実行すると、

Dscn9659

表示出来ました。

念のため、機種を切り替えてMSX2でも動作確認してみました。
結果は、...

動きません。MSX2が暴動しました。
調べてみると、マシン語プログラムの配置アドレスがまずいようです。
下記はプログラムの問題箇所の抜粋です。

60 EI=&HFAF5:SIZE=63
70 FOR A = EI TO EI+SIZE
80 READ B$: POKE A,VAL("&H"+B$)
90 NEXT A
100 REM
110 POKE &HFFB8,&HFA
120 POKE &HFFB7,&HF5
130 POKE &HFFB6,&HC3

LPRINTのフック(マシン語プログラム)の配置アドレス &hFAxxxx は
MSX2で新たにワーク領域と使われているようです。
基本的に &hF380H番地から&hFFFEH番地 はワーク領域なので使用禁止です。

プログラム自体はリロケータブルなようで、配置位置を&hF200 に変更したところ、
問題なく動作しました。

修正したプログラム(修正箇所のみ抜粋)

60 EI=&HF200:SIZE=63
70 FOR A = EI TO EI+SIZE
80 READ B$: POKE A,VAL("&H"+B$)
90 NEXT A
100 REM
110 POKE &HFFB8,&HF2
120 POKE &HFFB7,&H0
130 POKE &HFFB6,&HC3

Dscn9669

動いている様子



LEDマトリックスを制御しているMSX BASICプログラム
前半は1ドット単位の表示、後半はメッセージを1文字単位で
スクロール方向を変えて表示しています。

10 LPRINT "@?{}"
20 FOR Y=0 TO 7
30 FOR X=0 TO 7
40 LPRINT "@?{";CHR$(48+X);CHR$(48+Y);"1}"
50 NEXT X
60 NEXT Y
70 LPRINT "@?{}"
80 S$="Hello,Wrld.I love MSX!"
90 L=LEN(S$)
100 FOR I=1 TO L
110 R=INT(RND(1)*13)
120 LPRINT "@scrl ";R;",40"
130 LPRINT "@?";MID$(S$,I,1)
140 GOSUB 180
150 NEXT I
160 GOTO 100
170 END
180 TIME=0
190 IF TIME <20 GOTO 190
200 RETURN

上記のプログラムでは、シリアル通信の出力のみなので、
LEDマトリックスにコマンド送信した際の実行完了待ちが出来ないため
180行のサブルーチンで適当な時間待ちを行っています。

出力のみでも、十分遊べると思います。

2019年2月 2日 (土)

OLED(SSD1306)で美咲フォントを使った漢字表示

先日更新したArduino用フォントライブラリを使って、OLED(SSD1306)ディスプレイでの
漢字表示をやってみました。

OLEDは、0.96インチ ドライバSSD1306搭載 I2C接続タイプを使いました。

Dscn9578

0.96インチに8x8ドットの文字はちょっと小さいですが、表示出来ました。

Dscn9579

OLED制御には、AdafruitGFXAdafruit SSD1306ライブラリを使っています。

AdafruitGFXAdafruit SSD1306の使い方(インストール含む)については、
下記のお勧め参考文献を参照すると良いです。大変丁寧に解説されていています。

お勧め参考文献
Qiita - ArduinoでOLEDディスプレイを試す

その他関連サイト
adafruit/Adafruit_SSD1306
adafruit/Adafruit-GFX-Library
Learn The Adafruit_GFX library


サンプルスケッチ

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306_128_64.h>
#include <misakiUTF16.h>

Adafruit_SSD1306 OLED(128, 64, &Wire, -1); // OLEDドライバ作成
uint8_t font[8];                           // フォント格納バッファ

void setup() {
  Serial.begin(115200);
  if(!OLED.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("Cannot work."));
    for(;;); 
  }
  OLED.clearDisplay();

  // "あ"の描画
  getFontData(font, "あ");              // "あ"のフォントを取得 
  OLED.drawBitmap(0, 0, font,8,8,1);    // フレームバッファにフォント書き込み 
  OLED.display();                       // 画面更新

  // 文字列の表示
  char *str="Abcあいうえお、埼玉 "      // 文字列
            "日本語表示できるかな? " 
            "Arduinoで漢字表示"
            "出来ますよ!";
  char *ptr = str;                      // 文字列参照位置
  uint16_t x = 0, y = 8;                // 表示位置

  while(*ptr) {                         // 文字列分ループ
     ptr = getFontData(font, ptr,true); // 1文字分のフォント取得
     if (!ptr)
        break;                          // エラーの場合は終

     OLED.drawBitmap(x,y,font,8,8,1);   // フレームバッファにフォント書き込み 

     if (128-8 > x) {                   // 表示位置更新
       x+=8;
     } else {
       x=0;
       y+=8;
     }
  }
  OLED.display();                       // 画面更新
}

void loop() {
  // put your main code here, to run repeatedly:

}
 

サンプルスケッチのAdafruit SSD1306用ヘッダファイル"Adafruit_SSD1306_128_64.h"は
オリジナルの "Adafruit_SSD1306.h" をコピーして修正したものです。
Adafruit SSD1306ライブラリ、ヘッダファイルを修正することを前提としているため、
オリジナル版を残し、用途別のコピー&名前変更して使っています。

修正は、単に #define SSD1306_128_32 をコメントアウトして、
#define SSD1306_128_64を有効にしました。

フォントの表示はdrawBitmap()関数を使っています。
引数に表示座標、取得したフォントデータ(font)、フォントサイズ、色(=1:ドットオン)を
指定するだけで、簡単にフォント表示出来ます。
Arduinoのフラシュメモリの制約で教育漢字しかサポートしていませんが、
お手軽に漢字表示が出来ると思います。


追記

文字が小さいので文字を大きく表示してみました。

Dscn9581

改良スケッチ

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306_128_64.h>
#include <misakiUTF16.h>

Adafruit_SSD1306 OLED(128, 64, &Wire, -1); // OLEDドライバ作成
uint8_t font[8];                           // フォント格納バッファ

// ビットマップの拡大描画
void drawBitmapEx(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h,
                  uint16_t color,uint16_t bgcolor, uint16_t ex) {
  int16_t i, j,b=(w+7)/8;
  for( j = 0; j < h; j++) {
    for(i = 0; i < w; i++ ) { 
      if(*(bitmap + j*b + i / 8) & (128 >> (i & 7))) {
        // ドットあり
        if (ex == 1)  OLED.drawPixel(x+i, y+j, color); //1倍
        else          OLED.fillRect(x + i * ex, y + j * ex, ex, ex, color); // ex倍
      } else {
        // ドットなし
        if (ex == 1)  OLED.drawPixel(x+i, y+j, bgcolor);
        else          OLED.fillRect(x + i * ex, y + j * ex, ex, ex, bgcolor);
       }
     }
   }
}

void setup() {
  Serial.begin(115200);
  if(!OLED.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("Cannot work."));
    for(;;); 
  }
  OLED.clearDisplay();

  // "あ"の描画
  int16_t ex = 2;                       // 文字倍率
  getFontData(font, "あ");              // "あ"のフォントを取得 
  drawBitmapEx(0, 0, font,8,8,1,0,ex);  // フレームバッファにフォント書き込み 
  OLED.display();                       // 画面更新

  // 文字列の表示
  char *str="Abcあいうえお、埼玉 "      // 文字列
            "日本語表示できるかな? ";
  char *ptr = str;                      // 文字列参照位置
  uint16_t x = 0, y = 8*ex;             // 表示位置

  while(*ptr) {                         // 文字列分ループ
     ptr = getFontData(font, ptr,true); // 1文字分のフォント取得
     if (!ptr)
        break;                          // エラーの場合は終

     drawBitmapEx(x,y,font,8,8,1,0,ex); // フレームバッファにフォント書き込み 

     if (128-8*ex > x) {                // 表示位置更新
       x+=8*ex;
     } else {
       x=0;
       y+=8*ex;
     }
  }
  OLED.display();                      // 画面更新
}

void loop() {
  // put your main code here, to run repeatedly:

}

スケッチの変数 ex = 2 の値を変更することで3倍、4倍と変更出来ます。

2019年1月20日 (日)

4連8x8ドットLEDマトリックスを試してみる 続々編

4連8x8ドットLEDマトリックスを試してみる 続編」で質問があり、
前回のプログラムを少し修正して、4連8x8ドットLEDマトリックスモジュール
3連結、4連結をやってみました。

今回は、手持ちのSDカードシールド(SDカード・ロガーシールド)を利用しました。
前回のバージョンで未対応だった、16ドット以外のフォント、半角フォントに対応しました。

3連結 (24ドットフォントで表示)

Dscn9456

4連結(24ドットフォントで表示)

Dscn9460

4連結の2x2バージョン (16ドットフォントで表示)

Dscn9449

3連結 バージョンの動いている様子(動画)



4連結 2x2バージョンの動いている様子(動画)



実際の利用では、モジュールをキッチリと並べる必要があります。
それと、4連結 2x2の場合、横に結合する必要があるのですが、
私の所有しているものは、隙間が空きます。結合のために加工が必要そうです。


今回作成したスケッチ(プログラム)  ダウンロード max7219_test4.zip (6.5K)

いくつかのファイルに別れますが、取りあえずメイン部はこんな感じです。
コンパイルには別途、下記の必要です。
  ・sdfonts : Arduino用漢字フォントライブラリ SDカード版
    https://github.com/Tamakichi/Arduino-KanjiFont-Library-SD
   (SDカードには上記サイトに記載のフォントファイルを入れておく必要があります)

// max7219_test4.ino
// MAX7179ドライバーライブラリ動作チェック 4連マトリックスx最大4連結対応
// 2019/01/20 たま吉さん

#include <string.h>
#include <sdfonts.h>

#include "MAX7219_matrix.h"
#include "libmatrix.h"

// MAX7219接続
#define MAX7219_DIN   2 // DIN
#define MAX7219_CLK   4 // CLK
#define MAX7219_LOAD  3 // LOAD(CS)

// SDカード接続
#define MOSI_SD   11    // SDカードのMOISへ接続
#define MISO_SD   12    // SDカードのMISOへ接続
#define CLK_SD    13    // SDカードのCLKへ接続
#define CS_SD     10    // SDカードモジュールCSへ接続

// LEDマトリックスの定義(下記のうちとれか1つを1にして選択)
#define MODULE1x2  1    // 4連モジュール 横1x縦2 (横32x16ドット)
#define MODULE1x3  0    // 4連モジュール 横1x縦3 (横32x24ドット)
#define MODULE1x4  0    // 4連モジュール 横1x縦4 (横32x32ドット)
#define MODULE2x2  0    // 4連モジュール 横2x縦2 (横64x16ドット)

#if MODULE1x2 
#define   SCREENS   8   // MAX7219カスケード接続数
#define  SC_WIDTH  32   // マトリック表示横ドット数
#define  SC_HIGHT  16   // マトリック表示縦ドット数
#elif MODULE1x3
#define  SCREENS   12    // MAX7219カスケード接続数
#define  SC_WIDTH  32   // マトリック表示横ドット数
#define  SC_HIGHT  24   // マトリック表示縦ドット数
#elif MODULE1x4
#define  SCREENS   16    // MAX7219カスケード接続数
#define  SC_WIDTH  32   // マトリック表示横ドット数
#define  SC_HIGHT  32   // マトリック表示縦ドット数
#elif MODULE2x2
#define  SCREENS   16   // MAX7219カスケード接続数
#define  SC_WIDTH  64   // マトリック表示横ドット数
#define  SC_HIGHT  16   // マトリック表示縦ドット数
#endif

// 表示設定
#define  BRT       1    // LEDの輝度(0~7)
#define Y_POS      0    // フォント表示開始ライン(0~SC_HIGHT)

uint8_t fbuf[SC_WIDTH*SC_HIGHT/8];  // 表示用バッファ

// 表示用バッファを表示
void update_screen() {
  uint8_t* ptr = MAX7219_getBuffer(); 

#if MODULE1x2 || MODULE1x3 || MODULE1x4
  for (uint8_t i=0; i < 8; i++) { // 1個あたりのマトリックスの縦ライン数分のループ
    for (uint8_t j=0; j < SC_HIGHT/8; j++) {
      memcpy(&ptr[i*SCREENS+4*j], &fbuf[i*4+32*(SC_HIGHT/8-j-1)], 4);  
    }
  }
#elif MODULE2x2
  for (uint8_t i=0; i < 8; i++) { // 1個あたりの4連マトリックスの縦ライン数分のループ
    memcpy(&ptr[i*SCREENS+0], &fbuf[i*8+64], 8);
    memcpy(&ptr[i*SCREENS+8], &fbuf[i*8],    8);
  }
#endif
  MAX7219_update();  
}

// デモ
void demo(char *str, uint16_t font_size, uint8_t ypos) {
  uint8_t font[MAXFONTLEN];
  if(SDfonts.open()) {            // フォントのオープン
     Serial.println("Cannot open font's file");
  }
  SDfonts.setFontSize(font_size);    // フォントサイズの設定

  MAX7219_clear();
  while(1) {
    str = SDfonts.getFontData(font, str);  // フォントデータの取得
    if (!str)
      break;
    scrollInFont(fbuf, font, SDfonts.getWidth(), SDfonts.getHeight(),ypos, 30);
  }
  SDfonts.close(); 
}

// 1文字分スクロール挿入表示
void scrollInFont(uint8_t*ptr, uint8_t *fnt, uint8_t fw, uint8_t fh, uint8_t ypos, uint16_t dt) {
  for (int8_t t = 0; t < fw; t++) {
    scrollBitmap(ptr, SC_WIDTH, SC_HIGHT, B0001); // 左スクロール
    clearBitmapAt(ptr, SC_WIDTH, SC_HIGHT, SC_WIDTH-t-1, 0, fw, fh);
    setBitmapAt(ptr, SC_WIDTH, SC_HIGHT, SC_WIDTH-t-1, ypos, fnt, fw, fh);
    update_screen();
    delay(dt);
  }  
}

void setup() {
  Serial.begin(115200);
  if(SDfonts.init(CS_SD)) {     // フォント管理の初期化
     Serial.println("Cannot initialize SDfont library.");
  } else {
     Serial.println("Start.");
  }
  
  // マトリック表示ドライバの初期化
  MAX7219_init(MAX7219_DIN, MAX7219_CLK, MAX7219_LOAD, SCREENS, BRT);
}

void loop() {
  Serial.println("Now looping.");
  MAX7219_clear(); 
  // 文字列, フォントサイズ, フォント縦表示開始位置
#if MODULE1x2||MODULE2x2
  demo("16ドットフォント Saitama! こんにちは埼玉県!熱いぞ!埼玉県!",16, 0); 
  //demo("14ドットフォント Saitama! こんにちは埼玉県!熱いぞ!埼玉県!",14, 1); 
#elif MODULE1x3
  demo("24ドットフォント Saitama! こんにちは埼玉県!熱いぞ!埼玉県!",24, 0);  
#elif MODULE1x4
  demo("24ドットフォント Saitama! こんにちは埼玉県!熱いぞ!埼玉県!",24, 4);  
#endif
  delay(1000);
}

次の定義の変更することで、2連結、3連結、4連結、4連結2x2に対応出来ます

// LEDマトリックスの定義(下記のうちとれか1つを1にして選択)
#define MODULE1x2  1    // 4連モジュール 横1x縦2 (横32x16ドット)
#define MODULE1x3  0    // 4連モジュール 横1x縦3 (横32x24ドット)
#define MODULE1x4  0    // 4連モジュール 横1x縦4 (横32x32ドット)
#define MODULE2x2  0    // 4連モジュール 横2x縦2 (横64x16ドット)

また、demo()関数の引数で表示する文字列、フォントサイズ、フォントの縦位置を指定出来ます。
SDカードからフォント読み出しが若干遅い影響で、スクロールにおいてカクカク感があります。
SDfatに変更、フォントライブラリをフラシュメモリ版に変更で改善は出来るとは思いますが、
とりあえず、これで良しとします。

fbufは単純な表示用バッファで、バッファ更新後にupdate_screen()関数を呼び出すことで 表示に反映されます。
Adafruit_GFX_Libraryを使って派生クラスを実装すれば、比較的簡単に
グラフィック描画処理も追加出来ると思います。

この続編で、Arduino用Bitmap画像ロードライブラリsdbitmap を使って、
SDカードに保存したWindowsビットマップファイルを表示なんかも試してみたいと思います。

色々と試しましたが、縦に2個連結がちょうど良い感じです。


関連記事
・4連8x8ドットLEDマトリックスを試してみる 続々編 (この記事です)
4連8x8ドットLEDマトリックスを試してみる 続編
4連8x8ドットLEDマトリックスを試してみる

2019年1月 7日 (月)

Aliexpressで入手した「タッチスイッチボタン」の動作確認

Aliexpressで面白そうなタッチスイッチボタンを見つけたので入手し、試してみました。

購入した商品のサイト

    Capacitive Touch Switch Button RGB LED Sensor Switch Module

    01_2

到着した製品
 
   とりあえず、4個 (青、緑、赤、黄)を購入しました。

   02

  裏側

   03_2

  作り具合は、意外と良さそうです。はんだ付けも問題なしです。


動作確認

  まずは、掲載されている商品情報にて仕様を確認します。   

     商品購入サイト掲載情報

  04_2

    完全に勘違いしていました。

    単なるタッチセンサー的に使うモジュールかと思いきや、
    3.3V定電圧レギュレータ搭載のようです。しかも500mA流せるようです。

    単体のみで独立したスイッチとして利用出来るようです。
    安価な3.3V電源レギュレータとしても利用出来ますね。

    確認として、このモジュールのVCCGNDにUSBケーブルにて5V電源を供給し、
    OUTピンでLEDの点灯制御を行ってみました。

  ブレットボードでの実装
 
   05_2

  動いている様子

   

  問題なく動作しました。
  タッチにて、OUTピンのオン・オフの制御を行うことが出来ました。

  タッチする度にOUTの状態が切り替わります。
  状態を保持するトグルスイッチ的な用途に使えそうです。
 
  ただし、機械的なスイッチと違ってオフの時もタッチセンサー部分の稼働のために
  電力を消費します。測定してみると、0.66mAでした。

  06_2

  次に、タッチパネル部の発光時に流れる電流を測定しました。
  (OUTピンのLEDは外しています)
  7.5mA(タッチセンサー分も含む)でした。

  07_2

  思っていたほど消費量は少ないですが、
  電池駆動でのスイッチとしての利用は避けた方が良さそうです。

より以前の記事一覧