小学生の頃に半田付けしたくらいの自分が、自作キーボード作成のためのハード(TC74HC595AP)を実際に操作した


前書き

自作キーボードのキーマトリクス実現のため、
1つの入力をパラレル出力にする必要がある。
(これはAruduinoのピン数制約を回避するため。18ピンくらいあるのでArduinoLeonardoでは。81キーくらいは特に何も工夫しなくてもキー捜査できると思う。)

ラズパイでこれを実現されている方がいるが、Arduinoでは実際にどのように操作すればいいのか、またシフトレジスタの動作仕様確認のため、実際に動かした。

目的

  • 前回の調査に従い、SCK(入力/シフト)、SCLR(入力クリア)、RCK(出力/ラッチ)の動作を確認する。

やったこと

  • 0pinを入力に見立てる
  • 2~4pinを制御に見立てる(2…SCLR、3…SCK、4…RCK)
  • 6~13pinを出力に見立てる(6=A、7=B、…、13=H)
  • 出力をシリアル出力し、ビットがちゃんとシフトしていることを目で確認する。
  • 出力のどれかにLEDをつけてチカチカさせる(出力=1は通電していることの確認)

わかったこと

  • 出力1をしているときのICには電気が流れている。
  • どうせセットで使う(LOW⇨HIGHの電圧操作をしないと制御できない)ので、SCKのONとOFFは関数化したほうがいい(多分RCKも電圧捜査処理は一緒がいい)
  • 入力のビット列を読み取り、シフトする (例:X00Y0Z00>0X00Y0Z>00X00Y0)ソースを考えたけど、キーマトリクス検知だけを考えたら、2のn乗になる数字(10000000(128)とか00001000(8))を、ぐるぐる繰り返す&SCK+RCKするだけでいい。
  • ググると「shiftOut(dataPin,clockPin,bitOrder,value)」関数がシフトレジスタを使う上で便利そうだが、あまり活用しなくてよさそうかも。(前述のビット列ぐるぐるだけでいいので)
  • SCLRはキーマトリクス捜査の仕組みには不要(VCCにつないで常時1にしておけばおk)

ソース

初期ビット列を出力後、SCK&RCKを繰り返す。
(ゼロ埋め的なものをしているはず。アウトプットと構成回路を失念してしまいました…。)

tc74hc595
int input=0;
int RCKPin=4; 
int SCKPin=3;
int SCLRPin=2;
int BitA=6;
int BitB=7;
int BitC=8;
int BitD=9;
int BitE=10;
int BitF=11;
int BitG=12;
int BitH=13;

//出力したいビット列
String inputArray=("10001010");
String tmp="dummy";

void setup() {
  Serial.begin(9600);
  pinMode(BitA, INPUT);
  pinMode(BitB, INPUT);
  pinMode(BitC, INPUT);
  pinMode(BitD, INPUT);
  pinMode(BitE, INPUT);
  pinMode(BitF, INPUT);
  pinMode(BitG, INPUT);
  pinMode(BitH, INPUT);
  pinMode(input, OUTPUT);
  pinMode(RCKPin, OUTPUT);
  pinMode(SCKPin, OUTPUT);
  pinMode(SCLRPin, OUTPUT);
}

void loop() {
  delay(1000);

  Serial.print("input=");
  Serial.println(inputArray);

  digitalWrite(SCKPin,LOW);
  digitalWrite(RCKPin,LOW); 
  digitalWrite(SCLRPin, HIGH);  
  printOut("first");

  //インプットの桁数だけ繰り返す
  for(int i=0;i<inputArray.length();i++){
    //インプットのi桁数が1のとき、インプット用ピンをHIGHにする
    //(共通)SCKピンをHIGHにし書き込む。(&出力先を次のビット列にする)
    tmp=inputArray[i];
    if(tmp.equals("1")){
       digitalWrite(input,HIGH); 
       digitalWrite(SCKPin,HIGH);
       digitalWrite(SCKPin,LOW);
       digitalWrite(input,LOW);
    }else{
       digitalWrite(SCKPin,HIGH);
       digitalWrite(SCKPin,LOW);
    }

  }
  //以降SCKとRCKのみ
  putSCK();
  printOut("2nd");
  putSCK();
  printOut("3rd");
  putSCK();
  printOut("4th");
  putSCK();
  printOut("5th");
  putSCK();
  printOut("6th");
  putSCK();
  printOut("7th");
  putSCK();
  printOut("last");

  //while(1); //block repeat
}

//TC74HC595の各出力
void printOut(String guide){ 
  Serial.print(guide);
  Serial.print("=");
  Serial.print(digitalRead(BitA));
  Serial.print(digitalRead(BitB));  
  Serial.print(digitalRead(BitC));  
  Serial.print(digitalRead(BitD));  
  Serial.print(digitalRead(BitE));  
  Serial.print(digitalRead(BitF));  
  Serial.print(digitalRead(BitG));  
  Serial.print(digitalRead(BitH));  
  Serial.println();  

}

//SCK信号送出
void putSCK(){
  digitalWrite(SCKPin,HIGH);
  digitalWrite(SCKPin,LOW);
  digitalWrite(RCKPin,HIGH);
  digitalWrite(RCKPin,LOW);
  delay(1000);
}

その他

全然関係ないけどハマったこと

入力ビット列をいちいち設定するのがめんどくさくてfor文で済ませようとしたところ、以下のエラーにはまった。

invalid conversion from 'char' to 'const char*' -fpermissive arduino

Stringの特定の文字列にアクセスする場合は、一度別のStringクラスお変数に渡す必要がありそう。

当初
    if(inputArray[i].equals("1")){
現状
    tmp=inputArray[i];
    if(tmp.equals("1")){