フォト
2019年5月
      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 31  
無料ブログはココログ

表示器制御関連

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

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

2018年12月22日 (土)

Aliexpressの安価なキャラクタ液晶モジュールの動作確認

Aliexpressで安価なキャラクタ液晶モジュールを見つけ、購入しました。

1602 16x2 HD44780 for Arduino Character LCD /w IIC/I2C Serial Interface Adapter Module DIY KIT

01

16文字 x 2行 のパラレル接続の液晶モジュールと I2C変換モジュールがセットで$2.17です。

到着した製品

梱包も中身も特に問題なし。

Dscn9168

Dscn9169

基板の刻印や、乗っているICを調べてみると、それぞれのモジュールは、
・フィリップス社製PCF8574(8-bit I/O expander for I2C-bus)搭載モジュール
・1602A(16x2 コントローラHD44780)
のようです。

aitendoで販売されている、下記の製品とまったく同じもののようです。
液晶I/Fモジュール(I2C) [IFB-I2C-8574]   
STNキャラクタ液晶(16x2) [1602A-V2] の青色(1602A-V2-B)バージョン

説明書が無いのですが、裏側にはんだ付けするだけで良いようです。

Dscn9171

左側の4つの端子(I2C、GND、5V)だけで制御出来ます。
可変抵抗でLEDバックライトの調整が出来るようです。

早速、はんだ付けしてArduinoに接続して動作確認してみました。

Dscn9189

手持ちのデジカメでは、今一ちゃんと撮れていませんが、
見た目は写真よりも文字がくっきり表示出来き、視野角も広いです。

Dscn9185

動作確認には、下記のライブラリを利用しました。

利用ライブラリ
・LiquidCrystal_I2C
  https://github.com/johnrickman/LiquidCrystal_I2C

動作確認スケッチ

ライブラリに添付のサンプルプログラムのHelloWorldを少々修正しただけです。
(4行表示するメッセージを2行表示に修正)

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup() {
  lcd.init();                        // initialize the lcd 
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print(" Hello, world!");
  lcd.setCursor(0,1);
  lcd.print(" LCD 1602A(I2C)");
}  


void loop() {

}

安くてお手軽に使えて良い製品です。
このモジュールは、MSX用のテープ・ドライバ CASDuinoを製作に使う予定です。

2018年11月20日 (火)

RobotDyn STM32 Miniボード(Blue Pill互換)でJPEG画像表示

RobotDyn STM32 Miniボード(Blue Pill互換)でJPEG画像の表示をやってみました。
(BluePillより面積が狭いので、ブレッドボードで多線が出来ます)

グラフィック液晶モジュール は、
ILI9341搭載(SPI接続)+ SDカードスロット付きのものを利用しました。

Dscn9014

グラフィック液晶モジュールのスロットに刺したSDカードに
320x240ドット JPEG形式のフルカラー画像を配置し、それを表示しています。
開発環境はArduino STM32を利用しています。

JPEG表示は、Arduino UNOではSRAMの容量的に無理(バッファに2kバイト必要)ですが、

Blue Pillでは比較的簡単に表示出来ました。

動いている様子

これくらいの、速度で表示出来ればOKでしょう。

構成

03
※クリックすると拡大表示します

結線表
04
利用したテスト画像(test1.jpg)

Test1


スケッチは下記のサイトのESP8266用のJPEG画像表示スケッチを
参考にしました。

参考にしたサイト
・楽しくやろう。 ESP8266でJPEG画像をTFT LCDに表示する
   https://blog.boochow.com/article/427690966.html


利用ライブラリ

・JPEGデコーダーライブラリ
   MakotoKurauchi/JPEGDecoder
 https://github.com/MakotoKurauchi/JPEGDecoder
 
   ※fdfat対応にJPEGDecoder.cppの一部を修正しています。

   修正
    ・
#include <SD.h> を #include <SdFat.h> に変更
   
・ その下に
       extern SdFat SD;
      を追加

スケッチ
(こちらからも参照出来ます Tamakichi/stm32_jpeg_tft.ino)

//
// Arduino STM32 TFT(ILI9341) SPI接続 jpeg画像表示サンプル
//
// 参考にしたサイト
//  元にしたスケッチ
//  ・楽しくやろう。 ESP8266でJPEG画像をTFT LCDに表示する
//    https://blog.boochow.com/article/427690966.html
//  ライブラリ
//  ・MakotoKurauchi/JPEGDecoder
//    https://github.com/MakotoKurauchi/JPEGDecoder
//  Jpegに関する情報
//  ・JPEG/MCU
//    https://monobook.org/wiki/JPEG/MCU
//

#include <SPI.h>
#include <Adafruit_GFX_AS.h>
#include <Adafruit_ILI9341_STM.h>
#include <SdFat.h>
#include <JPEGDecoder.h>

// SDカード(SPI2利用)
#if ENABLE_EXTENDED_TRANSFER_CLASS == 1
  SdFatEX  SD(2);
#else
  SdFat  SD(2);  
#endif

#define SPI_SPEED SD_SCK_MHZ(36) // バスクロック
#define SD_CS PB0                // SDカード選択

// TFT制御用ピン (SPI1利用)
#define TFT_CS  PA0
#define TFT_RST PA1
#define TFT_DC  PA2

// TFT制御用オブジェクト
Adafruit_ILI9341_STM tft = Adafruit_ILI9341_STM(TFT_CS, TFT_DC, TFT_RST);

void setup() {
  Serial.begin(115200);
  delay(200);
  
  if (!SD.begin(SD_CS,SPI_SPEED)) {
    Serial.println("failed!");
  }
 
  tft.begin();
  tft.setRotation(3);
  tft.fillScreen(ILI9341_BLUE);
  Serial.println("OK!");

  jpegDraw("/test1.jpg"); // 320x240ドットフルカラー画像の表示
}

void jpegDraw(char* filename) {
 char str[100];
 uint8_t *pImg;
 int x,y,bx,by;
 
 // Decoding start
 JpegDec.decode(filename,0);
 uint16_t buf[JpegDec.MCUWidth*JpegDec.MCUHeight];
 uint16_t pos = 0;

 // Image Information
 Serial.print("Width     :");
 Serial.println(JpegDec.width);
 Serial.print("Height    :");
 Serial.println(JpegDec.height);
 Serial.print("Components:");
 Serial.println(JpegDec.comps);
 Serial.print("MCU / row :");
 Serial.println(JpegDec.MCUSPerRow);
 Serial.print("MCU / col :");
 Serial.println(JpegDec.MCUSPerCol);
 Serial.print("Scan type :");
 Serial.println(JpegDec.scanType);
 Serial.print("MCU width :");
 Serial.println(JpegDec.MCUWidth);
 Serial.print("MCU height:");
 Serial.println(JpegDec.MCUHeight);
 Serial.println("");
 
 sprintf(str,"#SIZE,%d,%d",JpegDec.width,JpegDec.height);
 Serial.println(str);

  // Raw Image Data
  while( JpegDec.read() ){    // MCU毎の描画処理
    pImg = JpegDec.pImage ;   // MCUブロックの先頭アドレス
    pos = 0;                   // バッファ位置初期化
    
    // MCUブロック描画ウィンドウの設定
    tft.setAddrWindow(JpegDec.MCUx * JpegDec.MCUWidth,
                      JpegDec.MCUy * JpegDec.MCUHeight,
                      JpegDec.MCUx * JpegDec.MCUWidth+JpegDec.MCUWidth-1,
                      JpegDec.MCUy * JpegDec.MCUHeight+JpegDec.MCUHeight-1);
 
    // ウィンドウ領域へのデータ転送
    for( by = 0; by < JpegDec.MCUHeight; by++)
      for( bx = 0; bx < JpegDec.MCUWidth; bx++, pImg += JpegDec.comps, pos++)
        buf[pos] = (JpegDec.comps == 1) ? 
         tft.color565(pImg[0], pImg[0], pImg[0]) : tft.color565(pImg[0], pImg[1], pImg[2]);
    tft.pushColors(buf, JpegDec.MCUWidth*JpegDec.MCUHeight, 0); 
  }
}
   
void loop() {
}

スケッチは高速化優先で、MCU内の端数画像には考慮していません。

SDカード利用のためのライブラリは、SdFatを利用しています。
SDカードアクセスのパフォーマンス改善のために、SdFatConfig.hの設定を修正しています。

変更
#define ENABLE_EXTENDED_TRANSFER_CLASS 1

2018年11月 7日 (水)

豊四季Tiny BASIC for Arduino STM32で日本語フォント利用対応中

先日作成した「Arduino用SJIS漢字フォントライブラリ SDカード版」を
豊四季Tiny BASIC for Arduino STM32に組み込んで日本語表示対応を試みています。

(現時点の修正案は下記のリンク先にまとめています。
  ttbasic_arduino_stm32のプロジェクトのissues#58にまとめています^^)

日本語表示が出来れば、簡単なアドベンチャーゲームが作成出来ると思います。


日本語表示表示の雰囲気は次のような感じです。

OLED版の表示デモ


プログラムソース

10 'OLED日本語表示デモ
20 @(0)=8,10,12,14,16,20,24
30 S="吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。"
40 L=LEN(S)
50 FOR J=0 TO 6
60 Z=@(J):X0=0:X=X0:Y=0
70 CLS 1
80 FOR I=1 TO L
90 R=KFONT(MEM,ASC(S,I),Z)
100 BITMAP X,Y,MEM,0,Z,Z,1
110 IF (X+Z*2+1)>(GW-1) X=0:Y=Y+Z ELSE X=X+Z+1
120 IF Y+Z>GH-1 I=L
130 NEXT I
140 WAIT 500
150 NEXT J
160 GOTO 160

プログラムはKFONT関数で1文字ずつフォントデータを取得して表示しています。
フォントをSDカードから逐次参照して表示しているため、表示は遅いです。

表示専用のKANJIコマンドを追加予定です。
これを使えばもう少しプログラムが短くなり、表示も早くなると思います。

OLEDの他に、NTSC画面、TFT画面にも表示出来ます。


NTSCビデオ出力画面での表示デモ

プログラムソース

5 CONSOLE 0
10 CLS
20 S="日本語表示にほんご"
30 L=LEN(S):X0=0:X=X0:Y=30:@(0)=8,10,12,14,16,20,24
35 FOR J=0 TO 6
40 FOR I=1 TO L
50 R=KFONT(MEM,ASC(S,I),@(J))
60 BITMAP X,Y,MEM,0,@(J)/R,@(J),1
70 X=X+@(J)/R+0
80 NEXT I
90 X=X0:Y=Y+@(J)+10
100 NEXT J
110 GOTO 110

プログラムの日本語入力は、NTSC、OLED、TFT画面では入力出来ないため、
シリアル接続したTeraTermにて行います。

01


TFT版ではカラー表示に対応しています。

Dscn8965

2018年9月25日 (火)

3Dプリンターでの試行錯誤 その2

3Dプリンタ利用の練習として、
以前製作した下の写真 「I2C接続 16x8ドット LEDマトリックス」のケースを製作してみました。

 

Dscn4264_2

 

Dscn4266_2

 

3D図形の作成はTinkercadにて行いました。
形状は単純なので、割と簡単に作成出来ました。

 

03

 

ここで、寸法は実際の寸法よりも、縦横0.4mmほど大きくしています。
試行錯誤の結果、ノズル幅分の約0.4mm小さくなることが分かり、その調整をしています。

データを、STL形式でエクスポートして3Dプリンタに読み込ませて出力開始、
1時間ほどで出力出来ました。

 

Dscn8857

 

寸法はドンピシャ、ジャストフィットで収まりました。
いい感じにできました。

 

Dscn8864

とりあえずIchigoJamで動作、問題無く動作しました。
基板剥き出しから一転して、ちょっとおしゃれな感じになりました。

 

Dscn8877

動作はこんな感じです。

 



3Dプリンタ、色々と活用出来そうです。

2018年8月 6日 (月)

アクティブマトリクス蛍光表示管の実験用表示モジュールの試用 (3)

前回のアクティブマトリクス蛍光表示管の実験用表示モジュールの改訂版、
MW25616L実験表示モジュールver.2の利用の続きです。

改訂版では、I2C接続用端子が新たに追加さました。

01 03

下からGNDVCCA4(SDA)A5(SCL)D2が割り付けられており、
付属のRTCモジュール(DS3231利用)が直接接続出来ます。

02

前回に引き続き、豊四季タイニーBASIC for Arduino機能拡張版(以降豊四季Tiny BASIC拡張版と略称)にて
動作確認をしてみます。

DATEコマンドで時刻を参照すると、当然正しく無いですが参照できました。

01_2

SETDATEコマンドで正しい時刻を設定します。

02_2


次に、下記のプログラムにてVFDに時刻を表示してみます。
10 VCLS:VBRIGHT 100
20 GETTIME H,M,S
30 VMSG 0,#-2;"現在の時刻は";H;"時";M;"分";S;"秒です"
40 WAIT 1000
50 VSCROLL 256,-1
60 GOTO 20

動かして見ると、表示内容を更新する毎にノイズが乗るような感じで乱れたりします。

04

05

旧バージョンでも試してみましたが、同様の現象が発生しました。
う~ん、BASICインタプリタのバグか?

雰囲気的に「データ転送時のデータ化け」っぽく、
調査していくと、VFDふぁんさんが公開しているサンプルソースのコメントに
ヒントがありました。

どうも、輝度設定(VBRIGHTコマンド)に影響するようです。
輝度を最大輝度の設定(VBRIGHT 255)にすると正常に表示出来ました。

VFDの輝度はディスプレイイネーブル(EN)をPWMを使ってオン・オフ(表示のオンオフ)して
調整しているのですが、これがスイッチングノイズを発生させて影響を及ぼすようです。

VFDの供給元のノリタケの技術サポート公開資料の
「アクティブマトリクス型CL-VFD アプリケーションノート - インターフェースインターフェースについて」

  スイッチングノイズによる誤動作(データ誤取込)を防止するため、
  データ書き込み中はENをH→L、あるいはL→Hに変えないでください。

との記載がありました。

ということで、データ転送中は輝度設定を255(最大輝度)にしなければならないことが
分かりました。利用の際の制約事項ですね。以後気を付けることにします。


問題解決後の実際の動作の様子




プログラムの自動起動の設定

利用の都度、プログラムをRUNコマンドで実行させるのはちょっと面倒です。
電源ON後、時刻表示プログラムをロードして実行するようにしたいですね。

豊四季Tiny BASIC拡張版には保存したプログラムを電源ON時に自動起動する機能があります。
デフォルトでは、自動起動判定用ピンD7HIGHの場合、内部EEPROMに保存されているプログラムを実行します。

RTCモジュール端子のD2RTCモジュールSQW(割り込み通知用の入力)用ですが、
この信号はアクティブLOWなので、RTCモジュールを接続した状態で起動すると
D2は常にHIGHとなります。これは利用出来ますね。

D2を、豊四季Tiny BASIC拡張版の自動起動判定用ピンに利用し、
RTCモジュールが接続されていれば、電源ON時はD2HIGHなので自動起動出来ます。

そこで、スケッチのttconfig.hAutoPinの設定を7から2に変更して書き込みます。

08

書き込み後、現在時刻表示プログラムをコピペしてSAVEコマンドで保存します。
VBRIGHT 255の修正は忘れずに)

09_2

ダイソーの300円 モバイルバッテリーをつなげて動かしてみました。

06

保存してプログラムが自動起動して、時刻を表示してくれました。
いい感じで動いてくれました。
単体で動作出来るのは良いですね。

07

折角ここまで来たので、何か実用的なものを作ってみましょう。
次に、I2C接続の湿度・温度センサーもつなげて時刻・湿度・温度を表示出来るように
したいと思います。


より以前の記事一覧