日輪刀を作ってみる　その2

その1からの続きです。
少しパワーアップ。

https://qiita.com/ichihey/items/23998f8e38e1b89ee3db


#目次
[1. はじめに](#1-はじめに)
[2. 構成検討](#2-構成検討)
[3. 設計](#3-設計)
[4. おわりに](#4-おわりに)

# 1. はじめに
その1では音声を出せる光る刀をダイソー品改造で作りました。
その2では
・音声を複数キャラ出せるようにする
・発光色をキャラごとに変えられるようにする
という点を追加しました。
なお今回も音声は私的利用の範囲内で使用しています。


# 2. 構成検討
前回の構成は下記のような感じでした。
これだとｽｲｯﾁでﾄﾗｯｸを1つ送ることしかできないので、音声のキャラ変えには
ボタンを押しまくったりするというイケてない状態になってしまいます。
また、LEDは既存のもので単色なので固定色しか出せません。
音声が別キャラになっても、刀身が同じ色だとなんだかイマイチです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112433/54e1f6de-9052-4fbc-9d29-e65e36f9f5d7.png)

ということで、下記の様な動作イメージを考えました。
SWでモード切替（キャラ変）とトラック送りをします。
SWを増やすのは嫌なので、ダブルクリックとシングルクリックで使い分けるようにします。
モードごとに3色LEDのPWM制御で色味パターンも変えるようにします。
このようにある程度の制御が必要なので、Arduinoを使うことにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112433/d3446450-e44e-4115-ec26-00210dd704a6.png)

ハード構成です。
筐体は前回同様、ダイソーの忍者刀を使います。
制御マイコンとしては、Arduino pro miniを使います。
3色LEDはアマゾンかAliexpressで買ったと思います。よくあるカソードコモンタイプです。
mp3出力は前回同様SDカード経由でDFPlayerにします。
スピーカーは忍者刀のものだと少しサイズ大きく入らなくなってしまうので、ちょい小さいものを用意。
なにかのオモチャから分解してゲットしたものを使ってた気がします。
あと電池を1つはずしてスペースを確保したので、電圧を上げるための5V昇圧コンバータを入れました。
こちら秋月電子のものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112433/bf04a012-de6f-5ab7-4303-fc18e33c71a6.png)

Arduino pro miniは書込にシリアルポートが必要なので、下記のようなセットで購入しました。
もれなく5個ついてきますが、なにかに使うでしょう！

https://www.amazon.co.jp/gp/product/B01CX2AQEW/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

他購入物
大体アマゾンですが、Aliexpressとかのほうが安いかも。

https://akizukidenshi.com/catalog/g/gK-13065/

https://www.amazon.co.jp/Aideepen-MP3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%A4%E3%83%BCDFPlayer%E3%82%AA%E3%83%BC%E3%83%87%E3%82%A3%E3%82%AA%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%80%81MP3-WMA%E3%81%AE%E3%82%92%E7%B5%B1%E5%90%88%E3%83%87%E3%82%B3%E3%83%BC%E3%83%80%E3%83%BC%E3%80%81TF-U%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF%E3%82%92%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88-%E9%9F%B3%E5%A3%B0%E3%83%9C%E3%82%A4%E3%82%B9%E9%9F%B3%E6%A5%BD%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB/dp/B07M8TJ24Q/ref=sr_1_1_sspa?keywords=dfplayer+mini&qid=1654203695&s=musical-instruments&sprefix=df%2Cmi%2C185&sr=1-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUEzN1JPUE5DOVg2UkQ5JmVuY3J5cHRlZElkPUEwOTE1OTgzMjFVSVpXWElJWkoyNiZlbmNyeXB0ZWRBZElkPUFCRFBMR1BZV0NEWUwmd2lkZ2V0TmFtZT1zcF9hdGYmYWN0aW9uPWNsaWNrUmVkaXJlY3QmZG9Ob3RMb2dDbGljaz10cnVl

https://www.amazon.co.jp/%E3%80%90100%E5%80%8B%E5%85%A5%E3%82%8A%E3%80%91-LED-%E7%A0%B2%E5%BC%BE%E5%9E%8B-%E3%82%AB%E3%82%BD%E3%83%BC%E3%83%89%E3%82%B3%E3%83%A2%E3%83%B3-4leg/dp/B083LCCVVW/ref=sr_1_10?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=10R2VMBVHUTPW&keywords=%E3%83%95%E3%83%AB%E3%82%AB%E3%83%A9%E3%83%BCLED&qid=1654207360&sprefix=%E3%83%95%E3%83%AB%E3%82%AB%E3%83%A9%E3%83%BCled%2Caps%2C216&sr=8-10

# 3. 設計
ブレッドボードで動作テスト時の配線図です。
LEDの抵抗は220Ωです。
そこまで強く光らせるわけではないので、Arduinoからの直接出力で対応。
DFPlayerはシリアル通信での制御にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112433/9fdb53d3-2001-0072-9f23-d4590c63f79f.png)

実際の配線図。
LED1個しか書いてませんが、実際は4個並列でつなげてます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112433/5c58fc09-0873-47e9-5024-de4fa764f11e.png)


実際に組み込んだ写真です。
相当せまい中に組み込んだので、かなり作業性悪いです。
フタするとどっかが断線したり、を2-3回繰り返してなんとか動作まで持っていく感じ。
書いといてなんですがあまりおすすめしない構造です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112433/02d9bfe6-6e51-c9cb-8e9a-044149e148ea.png)


Arduinoのソースコードです。
とりあえず動かす目的なのであまり精査はしてません。
タクトスイッチを入力ボタンとして、
シングルクリックでトラック送り、ダブルクリックでモード切替です。
モードは炭治郎、善逸、煉獄さん、主題歌の4つ。
それぞれのモードで青、黄色、赤、色切替として特色を表現していることにしました。

その1と同じく音声はマイクロSDに入れてDFplayerに読み込ませてます。
音声の準備はいい感じに。


```php
//DEFPLAYER設定
  #include "Arduino.h"
  #include "SoftwareSerial.h"
  #include "DFRobotDFPlayerMini.h"
  SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
  DFRobotDFPlayerMini myDFPlayer;
  void printDetail(uint8_t type, int value);
//pin設定
  int LED_R=2;
  int LED_G=3;
  int LED_B=4;
  int switch_pin=5;
  int led =13;
//変数設定
  int click_flag_1 = 1 , click_flag_2 = 1;
  int channel = 1;
  int track =0;
  int track_num_tanjiro =12;
  int track_num_zenitsu =4;
  int track_num_rengoku =3;
  int track_num_music =2;
  unsigned long timer=0;
  unsigned long curr=0;
  
  
void setup()
{
  //DEFPLAYER初期化
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);
  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true);
  }
  Serial.println(F("DFPlayer Mini online."));
  //----Set volume----
  myDFPlayer.setTimeOut(500); //Set serial communictaion time out 500ms
  myDFPlayer.volume(10);  //Set volume value (0~30).
  myDFPlayer.volumeUp(); //Volume Up
  myDFPlayer.volumeDown(); //Volume Down

  myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
  myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD); 

  
  
  pinMode(LED_R, OUTPUT);
  pinMode(LED_G, OUTPUT);
  pinMode(LED_B, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(switch_pin, INPUT_PULLUP);
  digitalWrite(LED_R,LOW);
  digitalWrite(LED_G,LOW);
  digitalWrite(LED_B,LOW);

}

void click_check(){
  //SW ONで開始する関数。SWOFFだと動かない
  
  click_flag_1=0;//クリックフラグをゼロリセット
  for(int i=0; i<10; i++){
    if(digitalRead(switch_pin) == 1){ //GND接続なのでpin=0でON, 1でOFF
      click_flag_1=1;
      break;  //200msec以内にSW　ON⇒OFFでﾌﾗｸﾞ1を立てる
    }
  delay(20);//20msec×10で200msec繰り返す
}

  if(click_flag_1 == 1){ //ﾌﾗｸﾞ１がたってた場合

   for(int i=0; i<10; i++){
    click_flag_2 = digitalRead(switch_pin);
    if(click_flag_2==0)
      break; //もう一度SWがONになったらﾌﾗｸﾞ2をゼロに
      delay(20); //20msたつまでループ
    }

    if(click_flag_2 == 0){ //ﾌﾗｸﾞ2が立ってたらダブルクリック
    Serial.println("Double");
      if(channel==5){
       channel=1;
      }
      else{
     channel=channel+1; //チャネルを1送る
     }
    track = 1; //トラック1を指定
    click_flag_2 = 1; //ﾌﾗｸﾞ2をリセット
    delay(50);
    }
    else{
    Serial.println("Single");
    track = track +1;//トラックを1進める
    
    }
  }
  return 0;  
}



void loop(){
if(digitalRead(switch_pin) == 0){ //スイッチ検出
  Serial.println("switch check");
  timer =0;
  click_check();
  delay(100); //ここの数値を小さくすると上手く動かなくなるので注意

  if(channel==1){
    Serial.println("竈門炭次郎モード");
    if(track>=track_num_tanjiro+1){
      track=1;//トラック数が曲数より大きくなってたら1に戻す
      myDFPlayer.playFolder(channel, track);//チャネル、トラックを指定再生
    }
    myDFPlayer.volume(30);
    delay(100);//Vol変更後再生まですこしディレイないとエラーになる
    Serial.print("channel:");
    Serial.print(channel);
    Serial.print(", track:");
    Serial.println(track);            
    myDFPlayer.playFolder(channel, track);//チャネル、トラックを指定再生
    timer=millis();
    LED_tanjiro();
    Serial.print("timer:");
    Serial.println(timer);     
  }
  
  else if(channel==2){ //善一の動作
  Serial.println("我妻善一");
    if(track>=track_num_zenitsu+1){
      track=1;//トラック数が曲数より大きくなってたら1に戻す
      myDFPlayer.playFolder(channel, track);//チャネル、トラックを指定再生
    }
    myDFPlayer.volume(30);
    delay(100);//Vol変更後再生まですこしディレイないとエラーになる
    Serial.print("channel:");
    Serial.print(channel);
    Serial.print(", track:");
    Serial.println(track);     
    myDFPlayer.playFolder(channel, track);//チャネル、トラックを指定再生
    timer=millis();
    LED_zenitsu();
  }

  else if(channel==3){ //煉獄さんの動作
    Serial.println("煉獄杏寿郎");
    if(track>=track_num_rengoku+1){
      track=1;//トラック数が曲数より大きくなってたら1に戻す
      myDFPlayer.playFolder(channel, track);//チャネル、トラックを指定再生
    } 
    myDFPlayer.volume(30); 
    delay(100);//Vol変更後再生まですこしディレイないとエラーになる
    Serial.print("channel:");
    Serial.print(channel);
    Serial.print(", track:");
    Serial.println(track);     
    myDFPlayer.playFolder(channel, track);//チャネル、トラックを指定再生
    timer=millis();
    LED_rengoku();
  }
  else if(channel==4){
    Serial.println("Music");
    if(track>=track_num_music+1){
      track=1;//トラック数が曲数より大きくなってたら1に戻す
    }
    myDFPlayer.volume(30);
    delay(100);//Vol変更後再生まですこしディレイないとエラーになる
    Serial.print("channel:");
    Serial.print(channel);
    Serial.print(", track:");
    Serial.println(track);     
    myDFPlayer.playFolder(channel, track);//チャネル、トラックを指定再生
    timer=millis();
    LED_music();
    Serial.print("timer:");
    Serial.println(timer); 
    
  }
}
curr=millis();
    Serial.println(curr-timer); 
if(curr-timer>30000){
  LED_off();
}


}

void LED_off(){
  digitalWrite(LED_R,LOW);
  digitalWrite(LED_G,LOW);
  digitalWrite(LED_B,LOW);
  digitalWrite(led,LOW);
  
}
void LED_tanjiro(){
  Serial.println("tanjiro LED start");
  analogWrite(LED_R,0);
  analogWrite(LED_G,0);
  analogWrite(LED_B,128);
}

void LED_zenitsu(){
  Serial.println("zenitsu LED start");
  analogWrite(LED_R,128);
  analogWrite(LED_G,32);
  analogWrite(LED_B,0);
}
void LED_rengoku(){
  Serial.println("rengoku LED start");
  analogWrite(LED_R,128);
  analogWrite(LED_G,0);
  analogWrite(LED_B,0);
  
}

void LED_music(){
  Serial.println("music LED start"); 

  timer=millis();
  curr=timer+10;
  while(curr-timer<90000){
      analogWrite(LED_R,128);
      analogWrite(LED_G,0);
      analogWrite(LED_B,0);
      delay(500);
      if(digitalRead(switch_pin) == 0){
        break;
      }
      analogWrite(LED_R,0);
      analogWrite(LED_G,128);
      analogWrite(LED_B,0);
      delay(500);
      if(digitalRead(switch_pin) == 0){
        break;
      }
      analogWrite(LED_R,0);
      analogWrite(LED_G,0);
      analogWrite(LED_B,128);
      delay(500);
      if(digitalRead(switch_pin) == 0){
        break;
      }
      analogWrite(LED_R,128);
      analogWrite(LED_G,64);
      analogWrite(LED_B,0);
      delay(500);
      if(digitalRead(switch_pin) == 0){
        break;
      }
      analogWrite(LED_R,128);
      analogWrite(LED_G,0);
      analogWrite(LED_B,128);
      delay(500);
      if(digitalRead(switch_pin) == 0){
        break;
      }                      
    curr=millis();
    Serial.println(curr-timer); 

    }
  channel=1;
  track=1;
  LED_off(); 
  }
```

# 4. おわりに
なんとか複数モードをもたせた日輪刀動作を確認できました。
ただし作業性がとても悪く、電池交換もいちいち柄を開けないといけません。
柄を開けて閉めるだけで断線のリスクもあり、どうにもオモチャとして使いづらい…
既存品に別部品を詰め込むのも限界なので、3Dプリンタで筐体設計が必要ですがそれは次回にて。