シフトレジスタでATC対応速度計を動かしてみる

BVE 鉄道シミュレーターで自宅運転台を動かそう～ATC対応速度計を動かすでは

https://qiita.com/usashirou/items/e24372ef5e2d3bed4ce4

Raspberry Pi PicoのGPIOを直接動かす形でATCメータを動作させていました。
この方法のメリットはマイコン単体で完結できることです。
当然ながら存在しないGPIOのピンを動作させることができない為、おのずとGPIOのピン数が多いものを選択することとなります。
しかし、GPIOのピンが多いマイコンは割高だったり、入手困難な場合があります。
このため、GPIOのピンを増やすICを追加することが多いです。
GPIOのピンを増やす方法の一例として
・　IOエキスパンダ
・　シフトレジスタ
・　外部マイコン
があげられます。

シリアル、I2C、SPI、UARTなどで制御します。
今回は、シフトレジスタ74HC595を使用してGPIOの数を増やしてみましょう。
# シフトレジスタ74HC595とは？
__74HC595__ は、 __8bit__ のデータを書き込むことでGPIOのON/OFFを制御できるうえ、電圧は __3.3V、5V__ どちらにも対応しています。
__74HC595__ は秋月電子などで1個35~40円程度で販売されており、はんだ付けがしやすいDIP版があります。

https://akizukidenshi.com/catalog/g/gI-14053/

使用方法については下記サイトなどを参考にしてみてください。
 __シフトレジスタ (74HC595) と Arduino を使って複数の LED を制御する方法__ 

https://iot.keicode.com/arduino/arduino-shift-register-sn74hc595.php
# テストする
上記サイトを参考にしつつテストプログラムを動かしてみます。
最初に、マイコンから出力する電圧を規定します。
ESP32などであれば3.3Vを74HC595のVCCに印加します。
上記サイト通りOEはGND、SRCLRはVCCに接続します。
SERとRCLK、SRCLKを適宜接続します。
この状態で、1列分である8bitのデータを送り、LATCHピンがHIGH/LOW切替していることを確認します。
# プログラム
テストプログラムで動作確認しましょう。

__LATCH__ を __Low__ にし、 __shiftOut__ にデータを送り __LATCH__ を __High__ にする事でシフトレジスタを動かします。
テストプログラムのピンを接続しているピン番号に変更して動作させてみましょう。

```
//https://iot.keicode.com/arduino/arduino-shift-register-sn74hc595-cascading.php
const int PIN_SER   =  15;
const int PIN_LATCH  =  13;
const int PIN_CLK    = 12;

void setup() {
  pinMode( PIN_SER, OUTPUT );
  pinMode( PIN_LATCH, OUTPUT );
  pinMode( PIN_CLK, OUTPUT );

  byte b1 = B11010001;

  digitalWrite(PIN_LATCH, LOW);
  shiftOut(PIN_SER, PIN_CLK, LSBFIRST, b1);
  digitalWrite(PIN_LATCH, HIGH);
}

void loop() { 
}
````
# ピン設定コマンドshiftOut
74HC595を設定するコマンド __shiftOut__ は以下のように記述します。

 __shiftOut(dataPin, clockPin, bitOrder, value)__
__MSBFIRST__ か __LSBFIRST__ かはピンの順番で変わってきますので注意してください。

http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=2369
# トランジスタアレイでの確認
次に、出力ピンの先にTD62083などを接続して試してみましょう。
最終的に24VのON/OFFが制御できることを目的としますので、ここで確実に動作確認することをお勧めします。
特に、__出力先のIC等が5V以下は認識しない場合、動作しません__ ので、注意が必要です。
TD62083のデータシートを見ると出力オン検出の入力電圧が2.5V～30Vであることがわかります。
（逆に出力オフは0~0.5Vです）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/03a5a8ac-7961-06b3-96f9-749f4df83a0c.png)
* 引用元：https://akizukidenshi.com/download/ds/toshiba/TD62083APG.pdf
# シフトレジスタを動かすには
サンプルプログラムを動かせましたが、実際に使うために変化させる必要があります。
__8bit__ は __0~255__ をビットデータとして __b00000000～b11111111__ で指定します。
普段使う数字の1を入れても１とはならず __00110001__ となります。
この為、手前から３，４，８のピンがONになります。
これは１が __Int__ や __String__ として認識しており、 __Byte__ と認識されていない為です。
# 複数のシフトレジスタを動かす
次にシフトレジスタを複数接続しましょう。
このプログラムでは
* 1個目:全消灯
* 2個目：5，8個目がHigh
* 3個目：１，４～８個目がHigh
* 4個目：3~6個目がHigh
* 5個目：1，2，7，8個目がHigh
となります。
 __shiftOutは奥から順番にセット__ されるので
* 5個目
* 4個目
* 3個目
* 2個目
* 1個目
となります。
また __MSBFIRST__ と __LSBFIRST__ を変える事でHighになるピンの位置が変わる事も確認しましょう。

```
//https://iot.keicode.com/arduino/arduino-shift-register-sn74hc595-cascading.php

const int PIN_SER   =  15;
const int PIN_LATCH  =  13;
const int PIN_CLK    = 12;
const int PIN_SCLR    = 14;

void setup() {
  Serial.begin(115200);

  pinMode( PIN_SER, OUTPUT );
  pinMode( PIN_LATCH, OUTPUT );
  pinMode( PIN_CLK, OUTPUT );
  pinMode( PIN_SCLR, OUTPUT );
  byte b1 = B00000000;
  byte b2 = B00001001;
  byte b3 = B10011111;
  byte b4 = B00111100;
  byte b5 = B11000011;

  delay(100);
  digitalWrite(PIN_SCLR, HIGH);

  digitalWrite(PIN_LATCH, LOW);
  shiftOut(PIN_SER, PIN_CLK, LSBFIRST, b1);
  shiftOut(PIN_SER, PIN_CLK, LSBFIRST, b2);
  shiftOut(PIN_SER, PIN_CLK, LSBFIRST, b3);
  shiftOut(PIN_SER, PIN_CLK, LSBFIRST, b4);
  shiftOut(PIN_SER, PIN_CLK, LSBFIRST, b5);

  digitalWrite(PIN_LATCH, HIGH);
  Serial.print(b1);
  Serial.print(b2);
  Serial.print(b3);
  Serial.print(b4);
  Serial.print(b5);

  Serial.print("Test End ");
}

void loop() {
}
```
# シフトレジスタボード
様々なマイコンで使えるようにシフトレジスタ用のボードを製作してみました。

![DSC_0182 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/90fe9b94-9dec-3201-c17c-470eae93315c.jpeg)

これでシフトレジスタが使えるようになりました。
続いてBVEと連携してみましょう。

https://qiita.com/usashirou/items/0d158b839f7465465eb3