masayasanのアイコン画像

【玩具】「色変わりの刀」制作

masayasan 2021年02月19日に作成  (2021年02月19日に更新)

1.製作内容

某漫画に登場する持ち主によって色が変わる刀をモデルにした「色変わりの刀」を製作した。
筐体としてダイソーで販売している「光る忍者刀」を使用している。
マイコン部分はArduino互換機であるSeeeduino Xiaoを使用。

2.使用部品

・光る忍者刀(ダイソー)
・Seeeduino Xiao(Arduino互換機)
・DFplayer
・RGBフルカラーLED 5mm OSTA5131A カソードコモン(秋月電子)
・抵抗入トランジスタ RT1P137P 40V1A
・抵抗器10M、300、220Ω
・ビニル配線
・百均で販売されていた防犯ブザー内にあったトランス?(型式不明)
・5mm角プラ棒

3.電気回路図

キャプションを入力できます

4. 製作過程

①黒と銀のマスキングタープを刀身に貼付け
刀身部に黒と銀のマスキングテープを張付けました。
刀の刃部分はLEDの光が見える様に少し隙間を空けています。

②5mm角プラ棒にLED6個を巻き付け
LED(RGB)は5mm角棒にマスキングテープで巻きつけて刀身部分に入れます。
電池ホルダーは既存の柄部分を流用します。

③DFplayer
簡単な配線、コマンドで好きな音を再生できるDFplayer。
SDカードに音源を保存しておくのですが、音源を探す or 作成するのが一番苦労したかも。
ネット上にあるフリーの音源も沢山あるのですが、イメージしているものとピッタリの音は中々入手が難しいです。

④左側は圧電ブザー右側はトランス?
写真左側は圧電ブザーで右側は防犯ブザーに入っていたトランスらしきもの。
圧電ブザーの音量を大きくするために設置してあります。

⑤3.3Vでも動作可能なSeeduino Xiao
低電圧(3.3V)動作可能かつPWM対応ピンを多く持つArduino互換機のSeeeduino Xiaを選定。
トランジスタを仲介して1つのピンでLED6個制御する。

⑥皮膚抵抗を検知する為のリード線
2本のリード線を触るとマイコンに入力されている電圧が分圧されて、入力値が変化します。
皮膚の抵抗値はおよそ2~5M?
その値を元に色が決定されLEDが発色します。

⑦柄の部分
柄の部分にリード線を這わせて、握った時に皮膚抵抗を検知する様にした。

⑧傾斜スイッチ
傾斜スイッチが金属製なので、ビニルテープで巻いて絶縁しました。

5. コード

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"


SoftwareSerial mySoftwareSerial(9, 10); // RX, TX
DFRobotDFPlayerMini myDFPlayer;

int val1 = 0; //常時 抵抗値観測
int val2 = 0; //設定抵抗値 手を離すまで値保持
int TiltSWval = 0;//傾斜回数観測
boolean TiltSWon;//TiltSWvalが一定回数ONでON
int RGB[3] = {0, 0, 0};
int SoundOn = 1;
int Soundname[4] = {1, 2, 3, 4}; //[0]:色変わり、[1]:構え、[2]:攻撃、[3]:無音

unsigned long Posingtime1 = 0;
unsigned long Posingtime2 = 0;
unsigned long Posingtime3 = 0;
#define TiltSW 0
#define redLED 1
#define greenLED 2
#define blueLED 3

//pin7 analogread pin9,10 Sirial

int color = 0;
#define white 1//kasumi
#define olive 2
#define yellow 3//kaminari
#define fuchsia 4
#define silver 5//iwa
#define apua 6
#define lime 7
#define red 8//honoo
#define gray 9//keadamono
#define blue 10//mizu
#define green 11//kaze
#define purple 12
#define maroon 13
#define navy 14
#define teal 15
#define black 16


void setup() {
  Serial.begin(9600);
  mySoftwareSerial.begin(9600);
  if (!myDFPlayer.begin(mySoftwareSerial, false)) {  //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) {
      delay(0); // Code to compatible with ESP8266 watch dog.
    }
  }
  myDFPlayer.volume(30);  //Set volume value. From 0 to 30
  myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);
  pinMode(TiltSW, INPUT_PULLDOWN);
}

void loop() {
  readval();
  if (val1 <= 600 && val2 == 0) {
    val2 = val1;
  }
  Posingtime1 = millis();
  while (val2 != 0) {
    readval();
    color = map(val2, 200, 600, 1, 16);
    colorPG();
    analogWrite(redLED, RGB[0]);
    analogWrite(greenLED, RGB[1]);
    analogWrite(blueLED, RGB[2]);
    Posingtime1 = millis();
    Posingtime2 = 0;
    if (SoundOn == 1) {
      myDFPlayer.play(2);
      SoundOn = 2;
      Serial.print("s1");
    }
    Action();
    if (val1 > 600) {
      initialize();
      Serial.print("val1 ");
      Serial.print(val1);
      Serial.println("reflesh");
    }
  }
}

void readval() {
  for (int i = 0; i < 30 ; i ++) {
    val1 = val1 + analogRead(8);
    TiltSWval += digitalRead(TiltSW);
    delay(5);
  }
  val1 = val1 / 30;
  if (TiltSWval < 10) {
    TiltSWon = 0;
  }
  else if (TiltSWval > 20) {
    TiltSWon = 1;
  }
  TiltSWval = 0;
}

void Action() {
  while (val1 < 600 && TiltSWon == 1) {
    SoundOn = 2;
    readval();
    if (millis() - Posingtime1 > 2000) {
      Posingtime2 = millis() - Posingtime1;
    }
    analogWrite(redLED, RGB[0]);
    analogWrite(greenLED, RGB[1]);
    analogWrite(blueLED, RGB[2]);
    delay(200);
    Serial.println("");
    Serial.print("TiltOn");
    while (val1 < 600 && Posingtime2 > 5000) {
      Posingtime2 = millis() - Posingtime1;
      readval();
      analogWrite(redLED, 0);
      analogWrite(greenLED, 0);
      analogWrite(blueLED, 0);
      //delay(200);
      Serial.print("kamae");
      Serial.print("time2");
      Serial.print(Posingtime2);
      Posingtime3 = millis() - Posingtime2;
      if (TiltSWon == 1) {
        if (SoundOn == 2) {
          myDFPlayer.playFolder(1, Soundname[1]);
          SoundOn = 0;
          Serial.print(",SoundOn,");
          Serial.print(SoundOn);
        }
      }
      else if (TiltSWon == 0) {
        SoundOn = 2;
        analogWrite(redLED, RGB[0]);
        analogWrite(greenLED, RGB[1]);
        analogWrite(blueLED, RGB[2]);
        delay(200);
        Posingtime1 = millis();
        Posingtime2 = 0;
        Serial.println("atack");
        myDFPlayer.playFolder(1, Soundname[2]);
        SoundOn = 2;
        delay(3000);
      }
      if (Posingtime2 > 10000) { //5secで構えキャンセル
        Posingtime1 = millis();
        Posingtime2 = 0;
        Serial.println("cancel");
        myDFPlayer.playFolder(1, Soundname[3]);
        SoundOn = 2;
      }
    }
  }
}

void initialize() {
  val2 = 0;
  Posingtime2 = 0;
  analogWrite(redLED, 0);
  analogWrite(greenLED, 0);
  analogWrite(blueLED, 0);
  SoundOn = 1;
  myDFPlayer.pause();
}

void colorPG() {

  switch (color) {
    case olive:
      RGB[0] = 128;
      RGB[1] = 128;
      RGB[2] = 0;
      break;
    case yellow://yellow 3//kaminari
      RGB[0] = 255;
      RGB[1] = 255;
      RGB[2] = 0;
      Soundname[2] = random(9, 10);
      break;
    case fuchsia:
      RGB[0] = 255;
      RGB[1] = 0;
      RGB[2] = 255;
      break;
    case silver://silver 5//iwa
      RGB[0] = 192;
      RGB[1] = 192;
      RGB[2] = 192;
      Soundname[2] = 11;
      break;
    case apua:
      RGB[0] = 0;
      RGB[1] = 255;
      RGB[2] = 255;
      break;
    case lime:
      RGB[0] = 0;
      RGB[1] = 255;
      RGB[2] = 0;
      break;
    case red://red 8//honoo
      RGB[0] = 255;
      RGB[1] = 0;
      RGB[2] = 0;
      Soundname[2] = random(5, 6);
      break;
    case gray:
      RGB[0] = 128;
      RGB[1] = 128;
      RGB[2] = 128;
      break;
    case blue://blue 10//mizu
      RGB[0] = 0;
      RGB[1] = 0;
      RGB[2] = 255;
      Soundname[2] = 14;
      break;
    case green://green 11//kaze
      RGB[0] = 0;
      RGB[1] = 128;
      RGB[2] = 0;
      Soundname[1] = 7;
      Soundname[2] = 8;
      break;
    case purple:
      RGB[0] = 128;
      RGB[1] = 0;
      RGB[2] = 128;
      break;
    case maroon:
      RGB[0] = 128;
      RGB[1] = 0;
      RGB[2] = 0;
      break;
    case navy:
      RGB[0] = 0;
      RGB[1] = 0;
      RGB[2] = 128;
      break;
    case white:
      RGB[0] = 255;
      RGB[1] = 255;
      RGB[2] = 255;
      break;
    case teal://white 1//kasumi
      RGB[0] = 0;
      RGB[1] = 128;
      RGB[2] = 128;
      Soundname[2] = 13;
      break;
    case black:
      RGB[0] = 0;
      RGB[1] = 0;
      RGB[2] = 0;
      break;
  }
}

6.まとめ

握る人が同じでも、握り方で色が変わる

刀を握るたびに色が変わるので、子供たちはそれぞれの色に対応したごっこ遊びをしてました。
音に関しては苦労した割に地味な音ばかりだったので、無い方が良かったかも。。。

おもちゃは単純明快な方が遊びやすいし、故障も少なくて良い。
今後の制作作品に反映させていきます。

ログインしてコメントを投稿する