フォト
2018年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    
無料ブログはココログ

2018年5月23日 (水)

梅澤無線電機さんの「電子倶楽部60」を購入してみました

電子工作関連のブログを色々と読みあさっていたところ、
梅澤無線電機さんの「電子倶楽部60」を発見、レトロな雰囲気につられてポッチってしまいました。

個人的な趣味として電子工作をやってますが、アナログ回路はあまり得意でなないので、
勉強しようと、教材を探していたんですよね。

梅澤電機株式会社 - 電子倶楽部60

01

関連情報
電子倶楽部60

価格は税込みで1,058円ですが、送料に868円かかりました。

注文して2、3日で商品が到着しました。さっそく開封してみます。

到着した商品

外箱は手抜きのない立派な箱です。
これなら、子供さんへのプレゼントとしても使えそうです。

Dscn7930

箱の裏

Dscn7932


開封

箱の中はこんな感じで入ってます。

Dscn7933

本体

値段の値段の割には、しっかりした作りです。
上面ボードの材質は、ボール紙ですが厚さが1ミリあり樹脂化粧していて丈夫そうです。
付属品として、ケーブル類とクリスタルイヤホン等が付いています。

Dscn7935

バーアンテナ、ポリバルコン、トランジスター、ダイオードがあるので鉱石ラジオや
1・2石トランジスターラジオなんかも作れそう。

搭載しているパーツ類、個別に買った場合1058円じゃすまないとおもいますね。

テキスト類

36ページの冊子がついています。意外としっかした内容のテキストです。

Dscn7943

60種類の実験回路が掲載されています。
色々と面白そうな実験が出来そうです。

Dscn7945

Dscn7944

Dscn7937

裏はこんな感じです。電池ボックスがあります。
うらは若干チープ間がありますが、良しとしましょう^^

Dscn7940

子供のころ、学研の電子ブロックを持っていたのですが、
あれって電子部品を直感的に結線出来ず、ブロックの配置に悩んでしまいました。
このワイヤー直結の方が楽ちんです。ブレッドボードとの併用もできますね。

ArduinoやIchigojam等のマイコンと組み合わせての利用にも良さそうです。
Lチカや音出し、リレーを使った実験等はこのボードを使って出来そうです。

2018年5月22日 (火)

NeoPixel(WS2812B)の制御 その2

前回行った、ArduinoによるNeoPixel(WS2812B)の制御の続きです。
前回の処理の一部をSPIを利用する方式に書き換えました。

SPIを使っているため、出力ピンはMOSIピン(D11)固定となりますが、
前回よりも安定したクロックでの出力となりました。

  04

前回の信号生成の条件を考慮し、

02

03

SPIのクロックを8MHzとした場合、1クロック幅は0.125μ秒となります。
このクロック幅を元に利用して、

   T0H、T1L : 0.375μ秒 (3クロック分)
   T0L、T1H : 0.625μ秒 (5クロック分)

として利用します。値としては、「Data transfer time」の表の有効範囲から
少々ずれていますが、問題無いようです。

ちょうど0、1の送信とも8クロック分になりSPIの送信単位の8ビットにマッチします。

01
NeoPixelに1ビット送信するのに、SPIを利用して1バイト送れば良いことになります。
    0 : 0b11100000
    1 : 0b11111000



修正したスケッチ

前回のスケッチでNeoPixelの初期化とデータ送信を行っている
NeoInit() 、NeoUpdate()をSPIを利用する方式に修正しました。

//
// Neopixelの制御 SPIバージョン by たま吉さん  2018/05/22
//

#include <SPI.h>

//***************
// 定数
//***************

#define PIXCELNUM   16           // Neopixel ピクセル数(LED数)
#define PIN         11           // Neopixel 制御用ピン番号
#define NEOSPI_0    0b11100000   // 1ビット 値0
#define NEOSPI_1    0b11111000   // 1ビット 値1
#define NEOSPI_RST  0b00000000   // REST

//***************
// グローバル変数
//***************
uint8_t buf[PIXCELNUM*3];     // Nexpixel用ピクセル色データ(ピクセル数 x 24ビット)

//***************
// 関数
//***************
// Neopixel初期化
void NeoInit() {
  memset(buf, 0, PIXCELNUM*3); // バッファの初期化

  // SPIの初期化
  SPI.setBitOrder(MSBFIRST);            // 最上位ビットから送信
  SPI.setClockDivider(SPI_CLOCK_DIV2);  // クロック 8MHz
  SPI.setDataMode(SPI_MODE1);           // アイドル時 LOW、立上りエッジ時送信
  SPI.begin();                          // 開始
}

// Neopixelへのデータ送信
void NeoUpdate() {
  // RESET送信
  SPDR = NEOSPI_RST;              // SPIデータ送信
  while(!(SPSR & (1 << SPIF))) ;  // 送信完了待ち
  delayMicroseconds(50);

  // ピクセル数x24ビット送信
  for (uint8_t i = 0; i < PIXCELNUM*3; i++) {
    for (uint8_t j = 0; j < 8; j++) {
      SPDR = buf[i] & (0x80>>j) ? NEOSPI_1:NEOSPI_0; // SPIデータ送信
      while(!(SPSR & (1 << SPIF))) ;                 // 送信完了待ち
    }
  }
}

// Neopixelの表示クリア
void NeoCLS() {
    memset(buf, 0, PIXCELNUM*3); // バッファの初期化
    NeoUpdate();                 // 表示更新
}

// 指定したピクセルの色を設定
void NeoSetRGB(uint8_t no, uint8_t R, uint8_t G, uint8_t B, uint8_t flgUpdate=false) {
  if (no < PIXCELNUM) {
    buf[no*3+0] = R;
    buf[no*3+1] = G;
    buf[no*3+2] = B;    
  }
  if (flgUpdate)
    NeoUpdate();
}

// ピクセルのシフト
void ShiftPixel() {
  uint8_t tmpbuf[3];
  memmove(tmpbuf,buf,3);
  memmove(buf, buf+3, (PIXCELNUM-1)*3);
  memmove(buf+(PIXCELNUM-1)*3,tmpbuf,3);
  NeoUpdate();
}

void setup() {
  
  NeoInit();  // Neopixcelの初期化
  NeoCLS();   // Neopixcelの表示クリア
  
  NeoSetRGB(0, 128,0,0,true); // No.0のピクセルを赤
  NeoSetRGB(1, 0,128,0,true); // No.1のピクセルを緑
  NeoSetRGB(2, 0,0,128,true); // No.2のピクセルを青
}

void loop() {
 delay(80);
 ShiftPixel(); // ピクセルをシフトして更新表示
}

SPIによるデータ送信は、関数呼び出しだと処理が間に合わないと判断し、
データレジスタSPDRに送信データをセットし、ステータスレジスタSPSRを参照して
送信完了待ちを行っています。

次回は8x8ドットマトリックスタイプのNeopixelを使ってもう少し複雑なことをやろうかと思います。


参考にしたサイト
Todotaniのはやり物Log - SPIの基本動作とArduinoでの使い方
しなぷすのハード製作記 - 「SPI」の解説
garretlab - Arduinoで遊ぶページ - SPI関連レジスタ
Stupiddog - ArduinoでSPI通信を行う方法
株式会社インデペンデンスシステムズ横浜 - Arduino UnoでSPI通信(その1)Arduino Uno2台で通信
QEEWiki - SPI (Serial Peripheral Interface)

2018年5月20日 (日)

NeoPixel(WS2812B)の制御

Arduino UnoでNeoPixel(WS2812B)の制御をライブラリ無しで行ってみました。
まずは手持ちのリング形状16個LEDのタイプを制御してみました。

Dscn7924

動いている様子



スケッチ

//
// Neopixelの制御 by たま吉さん  2018/05/20
//

//***************
// 定数
//***************

#define PIXCELNUM   16        // Neopixel ピクセル数(LED数)
#define PIN         2         // Neopixel 制御用ピン番号

//***************
// グローバル変数
//***************
uint8_t buf[PIXCELNUM*3];     // Nexpixel用ピクセル色データ(ピクセル数 x 24ビット)
volatile uint8_t * NeoOutReg; // Neopixcel出力レジスタ
uint8_t  NeoBitOut;           // Neopixcelセットビット
uint8_t  NeoBitMask;          // Neopixcelクリア用マスク

//***************
// 関数
//***************

// Neopixel初期化
void NeoInit() {
  memset(buf, 0, PIXCELNUM*3); // バッファの初期化

  // 出力ピンの初期化
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN, LOW);
  NeoOutReg  = portOutputRegister(digitalPinToPort(PIN));  // Neopixcel出力レジスタ
  NeoBitOut  = digitalPinToBitMask(PIN);  // Neopixcelセットビット
  NeoBitMask = ~NeoBitOut;                // Neopixcelクリア用マスク
 }

// Neopixelへ1を出力
inline void NeoOut_1() {
  *NeoOutReg |= NeoBitOut;   // HIGHの出力
  asm volatile(
     "nop"    "\n\t"
     "nop"    "\n\t"     
     "nop"    "\n\t"
     "nop"    "\n\t"     
  );
  *NeoOutReg &= NeoBitMask;  // LOWの出力
}

// Neopixelへ0を出力
inline void NeoOut_0() {
  *NeoOutReg |= NeoBitOut;   // HIGHの出力
  *NeoOutReg &= NeoBitMask;  // LOWの出力
  asm volatile(
     "nop"    "\n\t"
     "nop"    "\n\t"     
     "nop"    "\n\t"
     "nop"    "\n\t"     
     "nop"    "\n\t"
     "nop"    "\n\t"     
     "nop"    "\n\t"     
     "nop"    "\n\t"
  );  
}

// Neopixelへのデータ送信
void NeoUpdate() {
  uint8_t testbit = 0b10000000;
  *NeoOutReg &= NeoBitMask;  // LOWの出力
  delayMicroseconds(50);
  cli(); 
  for (uint8_t i = 0; i < PIXCELNUM*3; i++) {
    if (buf[i] & 128) NeoOut_1(); else  NeoOut_0();
    if (buf[i] &  64) NeoOut_1(); else  NeoOut_0();
    if (buf[i] &  32) NeoOut_1(); else  NeoOut_0();
    if (buf[i] &  16) NeoOut_1(); else  NeoOut_0();
    if (buf[i] &   8) NeoOut_1(); else  NeoOut_0();
    if (buf[i] &   4) NeoOut_1(); else  NeoOut_0();
    if (buf[i] &   2) NeoOut_1(); else  NeoOut_0();
    if (buf[i] &   1) NeoOut_1(); else  NeoOut_0();
  }
 sei();
}

// Neopixelの表示クリア
void NeoCLS() {
    memset(buf, 0, PIXCELNUM*3); // バッファの初期化
    NeoUpdate();                 // 表示更新
}

// 指定したピクセルの色を設定
void NeoSetRGB(uint8_t no, uint8_t R, uint8_t G, uint8_t B, uint8_t flgUpdate=false) {
  if (no < PIXCELNUM) {
    buf[no*3+0] = R;
    buf[no*3+1] = G;
    buf[no*3+2] = B;    
  }
  if (flgUpdate)
    NeoUpdate();
}

// ピクセルのシフト
void ShiftPixel() {
  uint8_t tmpbuf[3];
  memmove(tmpbuf,buf,3);
  memmove(buf, buf+3, (PIXCELNUM-1)*3);
  memmove(buf+(PIXCELNUM-1)*3,tmpbuf,3);
  NeoUpdate();
}

void setup() {
  NeoInit();  // Neopixcelの初期化
  NeoCLS();   // Neopixcelの表示クリア
  
  NeoSetRGB(0, 128,0,0,true); // No.0のピクセルを赤
  NeoSetRGB(1, 0,128,0,true); // No.1のピクセルを緑
  NeoSetRGB(2, 0,0,128,true); // No.2のピクセルを青
}

void loop() {
 delay(80);
 ShiftPixel(); // ピクセルをシフトして更新表示
}

制御を行うためのプロトコル自体は非常に簡単です。
1ポートからLOW or HIGHを指定したタイミングで出力するだけです。

リセット(RET)コード送信後、1つのLED(ピクセル)毎に24ビット分の0 or 1の送信、
複数のLEDの場合、24ビットxLED数分のデータを送信します。

02

リセット(RET)コードは、Treset(50μ秒)間 LOWを出力、
1ビット 0 を送信(0 code)は、T0H間HIGHを出力後、T0L間LOWを出力、
1ビット 1 を送信(1 code)は、T1H間HIGHを出力後、T1L間LOWを出力、
します。

だだし、このタイミングがシビアです。

03

作成したスケッチでは、
   T0H、T1L : 0.375μ秒 (6クロック分)
   T0L、T1H : 0.625μ秒 (10クロック分)

をとしました。
値としては、「Data transfer time」の表の有効範囲から少々ずれていますが、
問題無いようです。

Arduino Unoはシステムクロックが16MHzで動作しています。
1クロックは 1/16000000 = 0.0625μ秒 となります。

わずか、6~10クロックというシビアなタイミングで信号を出力する必要があります。
今回は6~10クロックの待ち時間の調整はインラインアセンブラ命令でNOPを入れて
調整しました。

  *NeoOutReg |= NeoBitOut;   // HIGHの出力
が6クロック
  *NeoOutReg &= NeoBitMask;  // LOWの出力
が3クロック
要していることを考慮しています。

時間待ち中は割り込みを禁止しています。
割り込みが入ると動作に外乱が入り、データが化けます。
また、デジタル出力をdigitalWire()で行うと処理が間に合いません。
そこで、出力レジスタに直接、値を書き込んでいます。

まあ、これだとシリアル通信等、他に何も出来ません。
そこで、次の対策としてSPIを使って何とかしようと思います。

参考にしたサイト
uratan - WS2812B の駆動タイミングの限界調査
PICマイコンの小部屋 - 秋月でWS2812B買ってしまったので動かないかも知れないけれど作ってみた

2018年5月16日 (水)

ゲームボーイ(旧タイプ)のパーツ その2

前回からの続きです。
その後、ケースの他に液晶モジュールとそのカバーを追加注文し、部品が到着しました。
とりあえず、IchigoJamで稼働させてみる予定です。

到着したパーツ

Dscn7908

Dscn7910

追加注文したパーツ

・LCDモジュール
3.5インチ 4:3の画面だと選択枝がこれしかありませんでした。
Podofo 3.5" TFT LCD Display RGB LCD Display Module Kit

01

・LCD用のカバー
  プラスチックではなくガラス製です。
Glass For GameBoy Zero DMG-01 For Raspberry Pi Modify Glass Lens Protector

02


まずは、LCDディスプレイの動作チェック

LCD部とドライバーボードのセットです。NTSCビデオ入力で表示出来ます。
IchigoJamに接続して表示確認をしたところ、仕様では12V駆動ですが5Vで動作しました。
意外と視野角の広く、斜めからも良く見える液晶です。

Dscn7907

液晶パネルはLQ035NC111という、比較的入手しやすいパーツです。

さっそく、今回の試みで一番重要なLCDの組み込みをやってみました。
傷防止のマスキングテープを付けて、段差のある部分をカットします。
パネルカバーが載せられるように、若干フチを残します。

Dscn7912

マスキングテープで仮止めして、一旦組み立ててみます。

Dscn7914

基板も装着

Dscn7917

ふたを閉めて、表示の確認をします。
LCDモジュールからケーブルを引き出して電源供給とビデオ信号入力を行っています。

Dscn7921

とりあえず、見栄えも良くいい感じに仕上がりました。
LCDカバーは購入して正解でした。

次に裏の電池ボックスからの電源供給をどうするか考えてみます。
Ichigojamを中にどう入れるかも検討します。

Dscn7922

他にもコネクタ類(キーボード、シリアル通信、外部電源)も何とかしたいですね。


2018年5月15日 (火)

micro:bitで8x8ドットNeopixelを使ったメッセージ表示

豊四季Tiny BASIC for micro:bit で 8x8ドットNeopixelによるメッセージ表示を実装しみました。

01

8x8ドットNeopixelは以前Aliexpressにて購入したものを使いました。

02

64個のNeopixelを駆動させるので、電源は電池から供給しています。

動いている様子



プログラムソース

10 'Neopixelで文字のスクロール表示
20 NPBEGIN 12,64
30 GOSUB "@CLSM"
40 S="こんにちは さいたま":N=RGB8(0,1,1) B=0:W=70:GOSUB "@MSG"
50 WAIT 500:NPCLS
60 S="これはNeoPixelによるメッセージ出力サンプルです"
70 N=RGB8(2,1,0):B=0:W=70:GOSUB "@MSG"
80 WAIT 500:GOTO 30
90 "@SCRL":'左スクロール
100 FOR Y0=0 TO 7
110 IF Y0&1 GOTO 170
120 FOR X0=6 TO 0 STEP -1
130 POKE MEM+Y0*8+X0+1,PEEK(MEM+Y0*8+X0)
140 NEXT X0
150 POKE MEM+Y0*8,0
160 GOTO 210
170 FOR X0=1 TO 7
180 POKE MEM+Y0*8+X0-1,PEEK(MEM+Y0*8+X0)
190 NEXT X0
200 POKE MEM+Y0*8+7,0
210 NEXT Y0
220 RETURN
230 "@INSC":'1文字分挿入スクロール
240 A=WADR(C)
250 FOR X1=0 TO 7
260 GOSUB "@SCRL"
270 FOR Y1=0 TO 7
280 IF PEEK(A+Y1)&($80>>X1) N0=N ELSE N0=B
290 IF Y1&1 POKE MEM+Y1*8+7,N0 ELSE POKE MEM+Y1*8,N0
300 NEXT Y1
310 NPPUT 0,MEM,64,1,1
320 WAIT W
330 NEXT X1
340 RETURN
350 "@MSG":'メッセージのスクロール表示
360 FOR I2=1 TO WLEN(S)
370 C=WASC(S,I2)
380 GOSUB "@INSC"
390 NEXT I2
400 RETURN
410 "@CLSM":'表示のクリア
420 FOR I3=0 TO 63:POKE MEM+I3,0:NEXT I3
430 NPPUT 0,MEM,64,1,1
440 RETURN

表示するメッセージは日本語に対応しています。
フォントは美咲フォントを利用しています。

8x8のピクセルは次のような順番で並んでいるため、、文字の表示やスクロール処理が
ちょっと面倒です。奇数行・偶数行でピクセル点灯の処理が異なります。

03

プログラムでは20行から80行で指定したメッセージを表示しています。
20行のNPBEGIN 12,64 は制御するピンとして12ピン、ピクセル数として64を指定、
30行のGOSUB "@CLSM" は表示用バッファの消去
40行、60行は次の変数にメッセージ等を設定し、GOSUB "@MSG"にてメッセージを
表示しています。

  変数
    S: メッセージ文字列
    N: 表示する文字色(RGB8関数で各R・G・Bの値を指定)
    B: 表示する文字の背景色(ここでは0:黒を指定)
    W: スクロール速度

50行、80行は消去及び時間待ちを行っています。
サブルーチンについては、説明を省略します。

2018年5月14日 (月)

豊四季Tiny BASIC for micro:bit をV0.08に更新しました

豊四季Tiny BASIC for micro:bit をV0.08に更新しました。
公開サイト
  https://github.com/Tamakichi/ttbasic_microbit

V0.07からの変更点
・シリアル通信をI/Oピン経由で行うUARTコマンドの追加
・キャラクタで直線・矩形・塗りつぶし四角を描画するCLINEコマンドの追加
・プログラム保存領域の増量(8本 ⇒ 16本)
・リファレンスマニュアルの見直し(問題点修正・追記)

今回の修正で、任意のピンにシリアル通信用のTxD、RxDを割り当ててシリアル通信を
行うことが出来るようになりました。

次の写真はUART 12,13,"921600"を実行して12ピンにRxD、13ピンにTxDを割り付けています。01

USB-シリアル変換モジュールが対応していれば、921600bpsの高速通信が利用出来ます。
ついでに今回追加したCLINEコマンドを使って矩形描画を行っています。

02


2018年5月 8日 (火)

ゲームボーイ(旧タイプ)のパーツ

ゲームボーイ(旧タイプ)のパーツがAliexpressやeBeyで出回っています。

02

01

古いゲームの傷ついたハウジング(外側ケース)やボタンを交換したりってニーズが
海外ではあるようです。

Pi Zeroとの記載があり、中にラズパイ Zeroを入れて利用する用途もあるようです。
私も「Arduinoや何かに使えるのでは?」と思い、幾つかパーツを注文しました。

私は、ゲームボーイ自体で遊んだことがなく、本物の使い勝手が分かりません。
そこで、中古を探して入手しました。
初代ゲームボーイ(DMG-01) 、amazonで3,290円でした。

Dscn7866

Dscn7867

状態はかなり良いです。
ゲームボーイは初めて手にしましたが、かなり頑丈な作りです。

ゲームは近くのHardOffで入手しました。

Dscn7874

テトリス 200円、それ以外は40円でした。

Dscn7871

テトリス、久々にやりました。液晶の表示も良好です。
問題無くプレイできました。
う~ん。面白い、操作性も抜群です。ハマってしまいました。

残念ながら、ハイスコアの保存で出来ないようです。
ゲームカーリッジ内のバッテリーバックアップが動作していないようです。

Dscn7873

カートリッジは特殊なねじで開けることが出来ません。
このタイプのドライバーをamazonで見つけ注文しました。

ゲームボーイ本体は調査のため解体して、基板の寸法等を調べる予定です。

2018/05/10 追記

工具が到着したので、早速ゲームカートリッジを分解してみました。

Dscn7876

以前ダイソーで購入したドライバーに嵌めて利用できました。

Dscn7877

テトリスを分解しみると、バックアップ電池はありませんでした。
ググってみると、どうやらテトリスはハイスコアを保持する機能は無いようです。
残念。

Dscn7878

とりあえず、遊戯王も分解してみました。
こちらには、バックアップ電池がありました。
ICが4つも搭載。グラフィック等を多用するためか、容量の大きいROMが搭載されているようです。

Dscn7880

2018年4月26日 (木)

Aliexpressで USBTinyISPの小型版を購入

Aliexpressにて USBTinyISPの小型のものが出回っているようで、入手しました。
USBTinyISP Programmer Module For Arduino

03

私が購入した時は、送料は無料だったのですが、現時点では若干値上がり&送料がかかります。

01


到着した製品(左)と所有していた従来のUSBTinyISP(右)

02

かなり小型です。Windows 10パソコンに接続したところ、問題なくUSBTinyISPと
認識してくれました。

ATtiny13Aの書込みには、今後これを使っていく予定です。

別途、6ピンのコネクタ付きのフラットケーブルがあると重宝します。
6 Pins 2.54mm Pitch JTAG AVR Download Cable

04



2018年4月24日 (火)

シフトレジスタ 74HC595の考察

電子工作で、8ビットシフトレジスタ74HC595をよく使います。
しかし、仕様を完全に理解していないで、他ブログや自分の過去の利用を流用し、
その場しのぎで利用していました。

Snapshot000003

「これじゃぁ、アカン、ちゃんと仕様と機能をちゃんと理解しよう」と思い、
調査しまとめることにしました。


まずは仕様の再確認

ピンレイアウト

Photo
メーカー毎に微妙にピン名称が異なります。
MC74HC595Aが分かり易い名称なので、データシートからピンレイアウトを
拝借し、修正しました。


ブロック図

Photo

内部的には、シフトレジスタストレージレジスタの構成になっています。

変化するシフトレジスタの8ビットパラレル出力をストレージレレジスタが
ラッチにて取り込んで、パラレル出力の状態を保持&出力します。

ストレージレジスタQAQHは3ステート(HIGHLOW、ハイインピーダンス)です。
SQHは2ステート(HIGHLOW)であるに注意)

Arduino Unoを使った実験

ブレッドボード上の8個のLEDを74HC595を使って制御します。

Dscn7854

接続は、74HC595のパラレル出力QAQHSQHにLEDを接続します。
各LEDには電流調整用に330Ωの抵抗を入れてGNDに接続しています。
各LEDはQAQHSQHの出力がHIGHの場合点灯し、LOWの場合に消灯します。

OUTPUT ENABLESERIAL DATA INPUTRESETSHIFT CLOCK, LATCH CLOCK
制御用の入力端子は、ArduinoのD10D11D2D13D3に接続します。

Photo_2

LEDの簡単な点灯制御

つぎの動画のように、8つLEDをチカチカさせる制御です。



スケッチ

// 利用ピンの定義
#define OUT_ENABLE   10
#define SERIAL_OUT   11
#define HC595_RESET   2
#define SHIFT_CLK    13
#define LATCH_CLK     3

// シフトレジスタへの8ビットデータのセット
void shift_dataOut(uint8_t data) {
  for (uint8_t i=0; i < 8; i++) {
    digitalWrite(SHIFT_CLK,LOW);
    digitalWrite(SERIAL_OUT, (data & (0x80>>i)));
    digitalWrite(SHIFT_CLK,HIGH);
  }
}

// シフトレジスタのデータリセット
void shift_reset() {
  digitalWrite(HC595_RESET,LOW);
  digitalWrite(HC595_RESET,HIGH);  
}

// シフトレジスタからストレージレジスタへのデータセット
void strage_update() {
  digitalWrite(LATCH_CLK,LOW);
  digitalWrite(LATCH_CLK,HIGH);  
}

// ストレージレジスタの出力有効
void strage_enable() {
  digitalWrite(OUT_ENABLE, LOW);
}

// ストレージレジスタの出力無効
void strage_disable() {
  digitalWrite(OUT_ENABLE, HIGH);
}

void setup() {
  // 利用ピンの初期化
  pinMode(OUT_ENABLE, OUTPUT);
  pinMode(SERIAL_OUT, OUTPUT);
  pinMode(HC595_RESET,OUTPUT);
  pinMode(SHIFT_CLK,  OUTPUT);
  pinMode(LATCH_CLK,  OUTPUT);

  // SHIFT CLOCK、LATCH CLOCKの設定
  digitalWrite(SHIFT_CLK,LOW);
  digitalWrite(LATCH_CLK,LOW);

  shift_reset();   // シフトレジスタの値リセット
  strage_update(); // シフトレジスタからストレージレジスタへの値セット
  strage_enable(); // ストレージレジスタの出力有効
  delay(2000);
}

void loop() {
  shift_dataOut(0b10101010);
  strage_update();
  delay(500);
  shift_dataOut(0b01010101);
  strage_update();
  delay(500);
}


スケッチの説明


①初期化 setup()
    (1)利用ピンの初期化
       74HC595の制御を行う5つのピンの出力設定を行っています。

    (2)SHIFT CLOCKLATCH CLOCKの設定
        初期値としてLOWの設定を行います。

    (3)シフトレジスタの値リセット
        shift_reset()関数を呼び出してシフトレジスタの値のリセットを行います。
        shift_reset()関数は次のように定義しています。

       // シフトレジスタのデータリセット
       void shift_reset() {
         digitalWrite(HC595_RESET,LOW);
         digitalWrite(HC595_RESET,HIGH);
       }   

        74HC595のリセットピンのLOWを設定してリセットを行った後、HIGHに戻しています。

    (4)ストレージレジスタへの値設定
        strage_update()関数を呼び出して、シフトレジスタの値をストレージレジスタに設定
        しています。
        strage_update()関数は次のように定義しています。    

      // シフトレジスタからストレージレジスタへのデータセット
      void strage_update() {
        digitalWrite(LATCH_CLK,LOW);
        digitalWrite(LATCH_CLK,HIGH);  
      }

        74HC595LATCH CLOCKに対して、LOWHIGHを行うことで、
        シフトレジスタの値をラッチしてストレージレジスタに取り込みます。

    (5)ストレージレジスタの出力有効
        strage_enable()関数を呼び出して、ストレージレジスタのパラレル出力QAQHSQH
        を有効にします。

        strage_enable()関数は次のように定義しています。

      // ストレージレジスタの出力有効
      void strage_enable() {
        digitalWrite(OUT_ENABLE, LOW);
      }

       74HC595OUTPUT ENABLELOWに設定することにより、
       出力を有効にしています。
       delay(2000)は、LEDの出力がリセットされていることを確認するために入れています。
       Arduinoのリセットボタンを押した直後、2秒間8個のLEDが消灯していることが確認できます。

②LEDの点灯ループ loop()
    8個のLEDに対して、2つのパターンの出力を0.5秒間隔で繰り返しています。
    shift_dataOut()関数は8個のLEDの点灯パターンを設定しています。
    shift_dataOut()関数は、シフトレジスタへの値の設定のみを行います。
    この関数を実行しても、LEDの表示には影響しません。
    shift_dataOut()関数は次のように定義しています。

   // シフトレジスタへの8ビットデータのセット
   void shift_dataOut(uint8_t data) {
      for (uint8_t i=0; i < 8; i++) {
        digitalWrite(SHIFT_CLK,LOW);
        digitalWrite(SERIAL_OUT, (data & (0x80>>i)));
        digitalWrite(SHIFT_CLK,HIGH);
     }
   }

    8ビットの値をシフトレジスタにセットするために8回繰り返し処理を行っています。
    1回毎の処理で1ビットの値をシフトレジスタにセットしています。
        (1)74HC595SHIFT CLOCKLOWにした状態にする
        (2)74HC595SERIAL OUTにセットしたい値をセットする
        (3)74HC595SHIFT CLOCKHIGHにして、SERIAL OUTの状態をラッチして
           1ビットをシフトレジスタにシフトインして取り込む。

    次にstrage_update()関数にてシフトレジスタの値をストレージレジスタにセットします。
    このタイミングでLEDの表示が更新されます。


LEDのPWMを使った明るさの制御

74HC595OUTPUT ENABLEPWMで制御することでLEDの明るさを制御することが出来ます。

スケッチのloop()deley(500)を次のように修正して、PWMにて徐々に暗くなるように
修正してみます。
実行すると、「ぽわー、ぽわー」を暗くなってからパターンが切り替わります。 

void loop() {
  shift_dataOut(0b10101010);
  strage_update();  
  for (int16_t i=0; i<256; i++) {
    analogWrite(OUT_ENABLE,i);
    delay(5);
  } 
  shift_dataOut(0b01010101);
  strage_update();
  for (int16_t i=0; i<256; i++) {
    analogWrite(OUT_ENABLE,i);
    delay(5);
  } 
}


ちょっとした疑問

74HC595
は連結(SQHを連結先の74HC595SERIAL DATA INPUTに接続)して
8ビット、16ビット、24ビットと桁数を増やすことが出来る仕様なのですが、
QHSQHが同じ値なので、
  「1個目の8ビット目と2個目の1ビット目が同じ値になってしまうのでは?」
と非常に疑問を感じます。

シフトレジスタ部の内部ロジック構造を見てみることにします。
シフトレジスタ部はDフリップ・フロップの連結構造です。

    Photo_3

(ロジック図はMC74HC595Aからの引用です)

74HC595内部の個々のDフリップ・フロップの連結と
連結する2個目の74HC595のDフリップ・フロップへの連結は
よく考えたら、差異はなくまったく同じになりますね。

下記の図は1個目の74HC595のシフトレジスタ部内のSRHと、2個目の74HC595
シフトレジスタ部内のSRAを接続したイメージです。

Dff_2

SERIAL CLOCKの立上りのタイミングでSERIAL DATA INPUTから読み込むデータを
D0、D2、D3...とすると、SQHSQAの状態は次のような感じにまります。
(時間軸は左が過去)

SQHがD5をラッチするタイミングでSQAのDにはD4が入力されているため、取り込むデータの
値は当然D4になります。

Photo_2

うぁ、良く考えたら当たり前で、こんな図を描いて考える必要もなかった。
  「Dフリップ・フロップ の連結で受け取るデータは前段のDフリップ・フロップの
   1クロック遅れたデータを受け取る」

ってことです。

まあ、これで疑問が解けたので良しとします。

2018年4月16日 (月)

ATtiny13AでI2C接続キャラクタLCDを利用する(4)

以前、挑戦ていた「ATtiny13AでI2C接続キャラクタLCDを利用する」を
Arduino 1.8.5 + MicroCore環境にてやってみました。

Dscn7826

キャラクタLCDは、秋月電子で購入したACM1602NI-FLW-FBW-M01を利用しています。
  ・I2C接続キャラクタLCD 16x2行白色バックライト付(ACM1602NI-FLW-FBW-M01)

以前コメントで頂いた、問題点の対応とRaulさんオリジナル版の
   Coding Laboratory - I2C on an AVR using bit banging

で指摘されている点の対応修正を行いました。
それと、可能な限り高速化をおこないました。

動いている様子

スケッチサイズは、MicroCoreのcore_settings.hにて利用しない機能を無効化することで
660バイトに抑えることが出来ました。

Ide

I2Cが使えると、電子工作の幅が広がりますね。

このスケッチは下記からダウンロードできます。
ダウンロード ATtiny13_I2CLCD.zip (4.7K)

«ATtiny13Aで赤外線リモコン受信センサーを使う(2)