見出し画像

7seg+NANO(2) シフトレジスタ

7seg+NANO(1)でNANOからのコントロールを試みたが、ケタ数が3ケタのときはチラついたり暗くなったりした。そこで今度はシフトレジスタU74HC595Aを使ってみた。


0 シフトレジスタ

 流れは以下の通り
 ① $${\overline{\text{SRCLR}}}$$ → LOW(初期化)→HIGH(戻す)
   または、$${\overline{\text{SRCLR}}}$$を5Vに繋いでおく
 ② SERとSRCLKを使ってシリアルデータをパラレルに変換
 ③ RCLK → HIGH($${Q_A ~ Q_B}$$から出力)→ LOW(戻す)

1 予行演習(LED8個)

 ピンの割り当て
  SER = 8、RCLK = 9、SRCLK = 10、(SRCLR = 11)
  SRCLK はNANOではなく5Vに繋いでも問題なかった。

/*  NANO_shift_register_02.ino

     シフトレジスタでLEDを制御する ①
     https://www.msyoukai.com/robot/arduino_011/#l13

    Arduino NANO                          serial port is COM3 for hp_PC.
                      1・     ・VIN             3,11 is interfered by tone().
                      0・     ・GND             A6,A7 is analog only.
                  Reset・     ・Reset
                    GND・     ・5V
                      2・     ・A7
                      3・     ・A6
                      4・     ・19/A5
                      5・     ・18/A4
                      6・     ・17/A3
                      7・     ・16/A2
      74HC595_SER <-- 8・     ・15/A1
     74HC595_RCLK <-- 9・     ・14/A0
    74HC595_SRCLK <--10・     ・AREF
    74HC595_SRCLR <--11・     ・3.3V
                     12・ USB ・13

    U74HC595A
          LED_b <-- Qb/1・ 〇 ・16/VCC ---> 5V
          LED_c <-- Qc/2・    ・15/Qa ----> LED_a
          LED_d <-- Qd/3・    ・14/SER ---> NANO_8
          LED_e <-- Qe/4・    ・13/OE ----> GND
          LED_f <-- Qf/5・    ・12/RCLK --> NANO_9
          LED_g <-- Qg/6・    ・11/SRCLK -> NANO_10
          LED_h <-- Qh/7・    ・10/SRCLR -> 5V
            GND <- GND/8・    ・9/Qh'
*/

int const SER = 8;  // ピンの割り当て
int const RCLK = 9;
int const SRCLK = 10;
//int const SRCLR = 11; // SRCLRは5Vに繋いでもよい

void setup() {
  pinMode(SER, OUTPUT); // 出力設定
  pinMode(RCLK, OUTPUT);
  pinMode(SRCLK, OUTPUT);
//  pinMode(SRCLR, OUTPUT);
//  digitalWrite(SRCLR, LOW); //初期化
//  digitalWrite(SRCLR, HIGH);
}

byte data[8] = {
  B10000000,
  B01000000,
  B00100000,
  B00010000,
  B00001000,
  B00000100,
  B00000010,
  B00000001,
};

void loop() {
  for (int i = 0; i < 8; i++) {
//    digitalWrite(SRCLR, LOW); //初期化
//    digitalWrite(SRCLR, HIGH);
    digitalWrite(RCLK, LOW);  //シリパラ変換
    shiftOut(SER, SRCLK, LSBFIRST, data[i]);
//    shiftOut(SER, SRCLK, MSBFIRST, data[i]);  // データの向きが逆になる
    digitalWrite(RCLK, HIGH);
    delay(100);
  }
}

2 予行演習(LED16個、カスケード接続)

 次にシフトレジスタを2個カスケード接続してLED18個の制御を試みた。
 接続はSERの経路は直列、RCLKとSRCLKは並列にする。
  NANO_8   => (1)SER、(1)Qh' => (2)SER 
  NANO_9   => (1)RCLK & (2)RCLK
  NANO_10 => (1)SRCLK & (2)SRCLK

/*  NANO_shift_register_03.ino

     シフトレジスタ (74HC595) のカスケード接続

    Arduino NANO                          serial port is COM3 for hp_PC.
                      1・     ・VIN             3,11 is interfered by tone().
                      0・     ・GND             A6,A7 is analog only.
                  Reset・     ・Reset
                    GND・     ・5V
                      2・     ・A7
                      3・     ・A6
                      4・     ・19/A5
                      5・     ・18/A4
                      6・     ・17/A3
                      7・     ・16/A2
      74HC595_SER <-- 8・     ・15/A1
     74HC595_RCLK <-- 9・     ・14/A0
    74HC595_SRCLK <--10・     ・AREF
    74HC595_SRCLR <--11・     ・3.3V
                     12・ USB ・13

    U74HC595A(1)
         LED_b <-- Qb/1・ 〇 ・16/VCC <--- 5V
         LED_c <-- Qc/2・    ・15/Qa ----> LED_a
         LED_d <-- Qd/3・    ・14/SER <--- NANO_8
         LED_e <-- Qe/4・    ・13/OE ----> GND
         LED_f <-- Qf/5・    ・12/RCLK <-- NANO_9 & (2)12/RCLK
         LED_g <-- Qg/6・    ・11/SRCLK <- NANO_10 & (2)11/SRCLK
         LED_h <-- Qh/7・    ・10/SRCLR <- 5V
           GND <- GND/8・    ・9/Qh' ----> (2)14/SER

    U74HC595A(2)
        LED_b2 <-- Qb/1・ 〇 ・16/VCC <--- 5V
        LED_c2 <-- Qc/2・    ・15/Qa ----> LED_a2
        LED_d2 <-- Qd/3・    ・14/SER <--- (1)9/Qh'
        LED_e2 <-- Qe/4・    ・13/OE ----> GND
        LED_f2 <-- Qf/5・    ・12/RCLK <-- NANO_9 & (1)12/RCLK
        LED_g2 <-- Qg/6・    ・11/SRCLK <- NANO_10 & (2)11/SRCLK
        LED_h2 <-- Qh/7・    ・10/SRCLR <- 5V
           GND <- GND/8・    ・9/Qh'            
*/

int const SER = 8;  // ピンの割り当て
int const RCLK = 9;
int const SRCLK = 10;
//int const SRCLR = 11; // SRCLRは5Vに繋いでもよい

void setup() {
  pinMode(SER, OUTPUT); // 出力設定
  pinMode(RCLK, OUTPUT);
  pinMode(SRCLK, OUTPUT);
  //  pinMode(SRCLR, OUTPUT);
  //  digitalWrite(SRCLR, LOW); //初期化
  //  digitalWrite(SRCLR, HIGH);
}

byte data_1[16] = {
  B10000000,  B01000000,  B00100000,  B00010000,
  B00001000,  B00000100,  B00000010,  B00000001,
  B00000000,  B00000000,  B00000000,  B00000000,
  B00000000,  B00000000,  B00000000,  B00000000,
};

byte data_2[16] = {
  B00000000,  B00000000,  B00000000,  B00000000,
  B00000000,  B00000000,  B00000000,  B00000000,
  B10000000,  B01000000,  B00100000,  B00010000,
  B00001000,  B00000100,  B00000010,  B00000001,
};

void loop() {
  for (int i = 0; i < 16; i++) {
    //    digitalWrite(SRCLR, LOW); //初期化
    //    digitalWrite(SRCLR, HIGH);
    digitalWrite(RCLK, LOW);  //シリパラ変換
    shiftOut(SER, SRCLK, LSBFIRST, data_2[i]);
    shiftOut(SER, SRCLK, LSBFIRST, data_1[i]);
    //    shiftOut(SER, SRCLK, MSBFIRST, data[i]);  // データの向きが逆になる
    digitalWrite(RCLK, HIGH);
    delay(100);
  }
}

3 予行演習(LED16個、シフトレジスタ1個)

 配線は以下の通り

  Qa~Qd:LEDの-側をLOW
  Qe~Qh:LEDの+側をHIGH にしてLEDを点灯させる

 データの例

/*  NANO_shift_register_04.ino(1個で16LED)

    Arduino NANO                          serial port is COM3 for hp_PC.
                      1・     ・VIN             3,11 is interfered by tone().
                      0・     ・GND             A6,A7 is analog only.
                  Reset・     ・Reset
                    GND・     ・5V
                      2・     ・A7
                      3・     ・A6
                      4・     ・19/A5
                      5・     ・18/A4
                      6・     ・17/A3
                      7・     ・16/A2
      74HC595_SER <-- 8・     ・15/A1
     74HC595_RCLK <-- 9・     ・14/A0
    74HC595_SRCLK <--10・     ・AREF
  (74HC595_SRCLR <--)11・     ・3.3V
                     12・ USB ・13

    U74HC595A
      LED-_3,7,11,5  <-- Qb/1・ 〇 ・16/VCC ---> 5V
      LED-_2,6,10,14 <-- Qc/2・    ・15/Qa ----> LED-_4,8,12,16
      LED-_1,5,9,10  <-- Qd/3・    ・14/SER ---> NANO_8
       LED+_1,2,3,4  <-- Qe/4・    ・13/OE ----> GND
         LED+5,6,7,8 <-- Qf/5・    ・12/RCLK --> NANO_9
     LED+_9,10,11,12 <-- Qg/6・    ・11/SRCLK -> NANO_10
    LED+_13,14,15,16 <-- Qh/7・    ・10/SRCLR -> 5V
                 GND <- GND/8・    ・9/Qh'
*/

int const SER = 8;  // ピンの割り当て
int const RCLK = 9;
int const SRCLK = 10;
//int const SRCLR = 11; // SRCLRは5Vに繋いでもよい

void setup() {
  pinMode(SER, OUTPUT); // 出力設定
  pinMode(RCLK, OUTPUT);
  pinMode(SRCLK, OUTPUT);
  //  pinMode(SRCLR, OUTPUT);
  //  digitalWrite(SRCLR, LOW); //初期化
  //  digitalWrite(SRCLR, HIGH);
}

byte data[16] = {
  B11101000,  B11011000,  B10111000,  B01111000,
  B11100100,  B11010100,  B10110100,  B01110100,
  B11100010,  B11010010,  B10110010,  B01110010,
  B11100001,  B11010001,  B10110001,  B01110001,
};

void loop() {
  for (int i = 0; i < 16; i++) {
    //    digitalWrite(SRCLR, LOW); //初期化
    //    digitalWrite(SRCLR, HIGH);
    digitalWrite(RCLK, LOW);  //シリパラ変換
    shiftOut(SER, SRCLK, LSBFIRST, data[i]);
//        shiftOut(SER, SRCLK, MSBFIRST, data[i]);  // データの向きが逆になる
    digitalWrite(RCLK, HIGH);
    delay(100);
  }
}

これでシフトレジスタの大体の仕様はわかった。
いよいよ7セグでやってみる。

4 やっと本番4ケタ7セグ(シフトレジスタ1個)

デジットのワゴンで買った4ケタの12ピンの7セグを使用。(TOF-3407HS-B と表記されている) 通電して調べた各ピンの割当てと配線を以下に示す。

/*  NANO_shift_register_05.ino(4ケタ7セグ)

     シフトレジスタで4ケタ7セグを制御する

    Arduino NANO                          serial port is COM3 for hp_PC.
                      1・     ・VIN             3,11 is interfered by tone().
                      0・     ・GND             A6,A7 is analog only.
                  Reset・     ・Reset
                    GND・     ・5V
                      2・     ・A7
                      3・     ・A6
                      4・     ・19/A5
                      5・     ・18/A4
                      6・     ・17/A3
                      7・     ・16/A2
      74HC595_SER <-- 8・     ・15/A1
     74HC595_RCLK <-- 9・     ・14/A0
    74HC595_SRCLK <--10・     ・AREF
    74HC595_SRCLR <--11・     ・3.3V
                     12・ USB ・13

    U74HC595A
              b <-- Qb/1・ 〇 ・16/VCC ---> 5V
              c <-- Qc/2・    ・15/Qa ----> a
              d <-- Qd/3・    ・14/SER ---> NANO_8
              e <-- Qe/4・    ・13/OE ----> GND
              f <-- Qf/5・    ・12/RCLK --> NANO_9
              g <-- Qg/6・    ・11/SRCLK -> NANO_10
             DP <-- Qh/7・    ・10/SRCLR -> 5V
            GND <- GND/8・    ・9/Qh'

    TOF-3407HS-B
          1/e・ --> Qe
          2/dig1000・<-- NANO_7
           3/dig100・<-- NANO_6
                4/d・--> Qd
                5/g・--> Qg
            6/dig10・<-- NANO_5
                7/b・--> Qb
                8/a・--> Qa
                9/f・--> Qf
            10/dig1・<-- NANO_4
              11/DP・-->Qh
               12/c・--> Qc            
*/
#include <MsTimer2.h>

int const dig_1 = 4;  // ピンの割り当て
int const dig_10 = 5;
int const dig_100 = 6;
int const dig_1000 = 7;

int const SER = 8;  // ピンの割り当て
int const RCLK = 9;
int const SRCLK = 10;
//int const SRCLR = 11; // SRCLRは5Vに繋いでもよい

int num = 0; // 表示する数
int old_num;
int t = 10; // スキャンする時間(usec) //10usecでチラつかないが、暗くて見えない
int t2 = 0;

void setup() {
  Serial.begin(9600);
  pinMode(dig_1, OUTPUT); // 出力設定
  pinMode(dig_10, OUTPUT);
  pinMode(dig_100, OUTPUT);
  pinMode(dig_1000, OUTPUT);
  pinMode(SER, OUTPUT); // 出力設定
  pinMode(RCLK, OUTPUT);
  pinMode(SRCLK, OUTPUT);
  //  pinMode(SRCLR, OUTPUT);
  //  digitalWrite(SRCLR, LOW); //初期化
  //  digitalWrite(SRCLR, HIGH);
  //  disp_num(1234);
  MsTimer2::set(500, count_up); // 500msごとにオンオフ
  MsTimer2::start();

}

void count_up() {
  num++;
}

byte data[10] = {
  B00000011,
  B10011111,
  B00100101,
  B00001101,
  B10011001,
  B01001001,
  B01000001,
  B00011111,
  B00000001,
  B00001001,
};

void disp_num(int i) {
  int d_1000, d_100, d_10, d_1;
  d_1000 = i / 1000;
  d_100 = (i - 1000 * d_1000) / 100;
  d_10 = (i - 1000 * d_1000 - 100 * d_100) / 10;
  d_1 = i - 1000 * d_1000 - 100 * d_100 - 10 * d_10;
  Serial.print("i= ");  Serial.println(i);
  Serial.print("d_1000= ");  Serial.println(d_1000);
  Serial.print("d_100= ");  Serial.println(d_100);
  Serial.print("d_10= ");  Serial.println(d_10);
  Serial.print("d_1= ");  Serial.println(d_1);

  digitalWrite(RCLK, LOW);  //シリパラ変換  // 千位
  shiftOut(SER, SRCLK, LSBFIRST, data[d_1000]);
  //    shiftOut(SER, SRCLK, MSBFIRST, data[i]);  // データの向きが逆になる
  digitalWrite(RCLK, HIGH);
  digitalWrite(dig_1000, HIGH);
  delayMicroseconds(t);
  digitalWrite(dig_1000, LOW);

  delayMicroseconds(t2);

  digitalWrite(RCLK, LOW);  //シリパラ変換  // 百位
  shiftOut(SER, SRCLK, LSBFIRST, data[d_100]);
  //    shiftOut(SER, SRCLK, MSBFIRST, data[i]);  // データの向きが逆になる
  digitalWrite(RCLK, HIGH);
  digitalWrite(dig_100, HIGH);
  delayMicroseconds(t);
  digitalWrite(dig_100, LOW);

  delayMicroseconds(t2);

  digitalWrite(RCLK, LOW);  //シリパラ変換  // 十位
  shiftOut(SER, SRCLK, LSBFIRST, data[d_10]);
  //    shiftOut(SER, SRCLK, MSBFIRST, data[i]);  // データの向きが逆になる
  digitalWrite(RCLK, HIGH);
  digitalWrite(dig_10, HIGH);
  delayMicroseconds(t);
  digitalWrite(dig_10, LOW);

  delayMicroseconds(t2);

  digitalWrite(RCLK, LOW);  //シリパラ変換  // 一位
  shiftOut(SER, SRCLK, LSBFIRST, data[d_1]);
  //    shiftOut(SER, SRCLK, MSBFIRST, data[i]);  // データの向きが逆になる
  digitalWrite(RCLK, HIGH);
  digitalWrite(dig_1, HIGH);
  delayMicroseconds(t);
  digitalWrite(dig_1, LOW);

  delayMicroseconds(t2);
}

void loop() {
  //  for (int i = 0; i < 1000; i++) {
  disp_num(num);
  Serial.println(num);
  //    delay(1000);
}

結果は、7segLEDのまとめでも書いた通り各ケタの点滅をチラつかなくなるまで(10μsec)速くすると表示が暗くて見えない。
これを解決する方法として
・コモンの抵抗値を下げる → ケタ数が多いとNANOの最大出力を超えるかも
・トランジスタで増幅する
が考えられる。
まずコモンの抵抗値を1kΩから330Ωにしてみた。しかし少し明るくなっただけでチラつかないのは10μsecだった。
各セグメントに流れる電流は抵抗が1kohmのとき
 (5-1.8)V/1kohm=3.2×10^{-3}=3.2mA 
330Ωのときは(5-1.8)V/330ohm=9.7×10^{-3}=9.7mA
である。0を表示するとき6つのセグメントに電流が流れるのでアノードから3.2×6=19.2mA、9.7×6=58.2mAの電流を供給することになり、NANOのmax20mAに近いか超えてしまう。シフトレジスタを触ったらアチチだった。これ以上セグメントの抵抗値を下げることは難しい。

おわりに

結果をまとめる。シフトレジスタはNANOと3本の線だけで情報のやり取りをおこなうことができる優れものである。複数のシフトレジスタをカスケード接続することで大量のON・OFFを制御することができる。しかし、電流値はNANOと同様max20mA程度である。これはLED単体を順にチラつかせるなしでは問題はないが、ダイナミック点灯でケタ数の大きい7セグを制御するときには暗くて使いものにならない。これはシフトレジスタを使わない場合でも同様である。→  7seg+NANO(1)

下のようにセグメントの前後にトランジスタを置くことが望ましいと思われる。上流(アノード)側に2SA1015(PNP型)、下流側に2SC1815(NPN型)のトランジスタを置く方法が考えられる。そのうち試したい。