LoginSignup
1
1

More than 5 years have passed since last update.

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

Posted at

前書き

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

75hc595_in.jpg

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

目的

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

やったこと

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

75hc595_in.jpg

わかったこと

  • 出力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")){
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1