スポンサーサイト


上記の広告は1ヶ月以上記事の更新がないブログに表示されます。
新しい記事を書くことで、こちらの広告の表示を消すことができます。  
Posted by ミリタリーブログ at

2019年06月14日

ARES SOC SLR 分解

ARES SOC SLRを分解します。


後部のネジを2つ外しバットプレートを取り外します。



チークパッド後ろのネジを緩めて、ストック後部を取り外します。




本体側面のネジを4つ取り外し、アッパーレシーバーを取り外します。




スプリングと、ネジを1つ外し、ダミーボルトを取り外します。



ピンを2本抜き取り、メカボックスを取り出します。


メカボックスにARESとキンワの封印シールが張ってありました。




メカボックス後部のマイナスネジを外し、六角レンチを差込み、押し込みながら回すと
スプリングガイドが外れます。


側面のネジを外してメカボックスを開けました。
グリスが大量に塗られていました。
タペットプレート、シリンダーヘッドは専用品のようです。
セクターギアにカットオフ検知用の磁石が取り付けられています。


ノズル長は21.2mm。



メカボックスを取り外したあとにそのままインナーバレルが取り外せます。


インナーバレル長はなんと670mm。



ホップ構造は普通ですが、プラスチックのパーツで直接押すようになっています。



この銃は電子トリガーが標準装備されており、
ロアレシーバーに電子回路、メカボックスに磁気センサーが取り付けられています。




本体後方のネジ2つを外すと電子回路を取り外せます。





マイコン:STM 8S003F3P6
レギュレーター:HT7133
駆動FET:83S3G ×2
ブレーキFET:65P03


動作はトリガーが押された後に磁気センサーが磁石を検知するとブレーキが掛かりモーターが停止します。


磁気センサーが一定時間磁石を検知しないとモーターが停止します。
5回連続で感知しないとトリガーを押しても動かなくなります。  
タグ :ARESSOC SLR

Posted by 名無しのナナシ at 23:54Comments(0)エアガン整備エアガン

2019年06月11日

ARES SOC SLR(中古品)

ARESのSOCSLRを買いました。





この銃はARESオリジナルのセミオートスナイパーライフルです。
本体のほかにマガジン1つとバイポッド、クリーニングロッド、説明書が付属しています。




説明書は英語で書かれていますが、詳細なイラストがあるので大体分かると思います。




バイポッドは本体左右の専用レールに取り付けられるものですが、首振りができません。

グリップ下のモノポッドと合わせて銃を固定して定点狙撃するためのもので、
移動しながら使うには不向きです。


マガジンはオリジナルのプラスチック外装のものです。



M14マガジンとの比較。
幅は大体同じで,長さは約2/3です。


この銃はブルパップなのでグリップ後ろに取り付けます。



マガジンキャッチはマガジン後ろにあり、ボタンを押し上げて取り外します。
マガジンは自重で落下します。



銃口のフラッシュハイダーはM14正ネジで取り付けられています。
取り外すとインナーバレルがはみ出します。



ホップ調整はチャージングハンドルを引いて、ダミーボルトを開いて行います。
ダミーボルトはボルトストップで開いたまま固定されます。


ボルトストップの解除は本体左にあるボルトリリースレバーを押し下げます。
結構硬いです。



セーフティーはアンビで人差し指で操作します。



この銃にはレーザーサイトが装備されているようですが、
点かないようにされているようです。



トリガー前にレーザー用のスイッチが付いています。
下側のボタンを押してオンオフをするようです。
左右にあるダイヤルは回すことができますが、ただの飾りのようです。



本体上前方のネジを外し、トップレールを前に引き出し、上に外して、バッテリーの脱着を行います。
バッテリーは11.1V推奨ですが、7.4Vでも駆動できました。


レーザーサイト用の配線は切り取られているようです。



初速はホップを切った状態では67m/s前後ですが、ホップを掛けるほど初速が上がり、
91m/sまで上がりました。


重量は本体のみで5.4kg、バイポッドが814gで、合計6.2kgです。
スコープをつけると、7kg前後になり、とても重たいです。
次回は分解を行います。  
タグ :ARESSOC SLR

Posted by 名無しのナナシ at 22:26Comments(0)エアガンエアガン中古

2019年06月03日

動画投稿、2月17日分その2

2月17日、福岡サバゲーランドの動画を
投稿しました。


  

Posted by 名無しのナナシ at 17:56Comments(0)サバゲー動画福岡

2019年05月08日

電子トリガーを作る その4

その3の続き。
ヒューズが飛ぶ問題への対処を行います。
どんな感じに飛ぶというと、撃っていると突然ショートしたようになってヒューズが飛びます。
色々と調べてみるとこういったページを見つけました。
ページに書いてあることによるとアンダーシュートが原因と思われます。


アンダーシュートによって2つのFETが同時にオンになりショートしてしまい、ヒューズが飛んでしまうようです。

そこで対策として、
1.ブートストラップコンデンサの容量を再計算、470μF→47μFへ変更。
2.Vcc端子とCOM端子の間に470μFの電解コンデンサを追加。
3.ゲート抵抗を33Ω→47Ωへ変更。
その他に、バッテリー電圧を測定する分圧抵抗を追加したり
センサー用の電源をマイコンと別にしました。
最終的な回路はこちらです。



マガジンに磁石を仕込んで、これを磁気センサーで検出してボルトストップするようにしました。


ボルトストップはチャージングハンドルを引くことで解除できるようにしています。


プログラムは以下の通り。

//F2000用FCUプログラムVer.1.03
//改訂記録============================================================================
//Ver.1.01 モーターロック保護処理の追加
//Ver.1.02 ボルトストップ時にピストンを前進位置で停止するよう変更
//Ver.1.03 ボルトストップ解除時に発射されてしまう不具合を修正
//入出力ピンの名称変更=================================================================
#define SEMI_SW A0 //セミオートスイッチ
#define VAL_IN A1 //電圧測定入力
#define FULL_SW 4 //フルオートスイッチ
#define SAFETY_SW 2 //セーフティスイッチ
#define CUTOFF_SW 3 //カットオフスイッチ
#define NO_AMMO_SW 6 //残弾無し検知スイッチ
#define COCKING_FOWARD_SW 7 //コッキングハンドル前進検知スイッチ
#define COCKING_BACK_SW 8 //コッキングハンドル後退検知スイッチ
#define MOTOR 9 //モーター制御出力
#define INDICATOR 10 //インジケーターLED
#define LED 13 //マイコンLED
//定数の宣言===========================================================================
const byte PWM = 254; //フルオートサイクル調整用定数、254まで
const unsigned int PRECOCK = 30;//プリコック時間(ミリ秒)
const unsigned int DECOCK = 0; //デコック時間(ミリ秒)
const unsigned int SW_ON = 280; //セミオートスイッチオン閾値
const unsigned int SW_OFF = 90; //セミオートスイッチオフ閾値
const unsigned int CHATA_SEMI = 0; //セミオートスイッチチャタリング防止(マイクロ秒、1/1000ミリ秒)
const unsigned int CHATA_FULL = 5000; //フルオートスイッチチャタリング防止(マイクロ秒、1/1000ミリ秒)
const unsigned int CHATA_CUTOFF = 0; //カットオフスイッチチャタリング防止(マイクロ秒、1/1000ミリ秒)
const bool ON = LOW, OFF = HIGH; //スイッチ用定数、混乱防止のため
const bool SEMI = false, FULL = true; //フル・セミ切り替え用定数
const unsigned int V_R1 = 1000;     //電圧検知VIN側抵抗値(Ω)
const unsigned int V_R2 = 1000;     //電圧検知GND側抵抗値(Ω)
const unsigned int LIMIT_VAL_S = 740; //待機時電圧下限値(V×100)
const unsigned int LIMIT_VAL_M = 610; //稼働時電圧下限値(V×100)
const unsigned int VF = 70; //ダイオード順方向降下電圧値(V×100)
//変数の宣言===========================================================================
volatile int Fire = 0; //発射制御用変数
volatile unsigned int Semi_Sw = 0; //セミオートスイッチ用変数
volatile bool Cutoff = LOW, Old_Cutoff = LOW; //カットオフセンサー用変数
volatile bool SemiTrg = OFF, Old_SemiTrg = OFF; //セミオート処理用変数
volatile bool FullTrg = OFF, Old_FullTrg = OFF; //フルオート処理用変数
volatile bool Shot_Mode = SEMI;//フル/セミ切り替え用変数
volatile bool No_Ammo = LOW;//残弾無し検知用変数
volatile bool Bolt_Stop = false;//ボルトストップ処理用変数
volatile bool Cocking_Fowad = LOW;//コッキングハンドル前進検知用変数
volatile bool Cocking_Back = LOW;//コッキングハンドル後退検知用変数
volatile bool Fast_Shot = true;//ファストショット処理用変数
bool Battery_Low = false;//バッテリー低下処理用変数
float Vcc = 0; //基準電圧(V)
unsigned int Val = 0;//測定電圧(V×100)
unsigned long Time = 0, Old_Time = 0; //電圧測定時間記録(ミリ秒)
unsigned long M_Time = 0 ,Old_M_Time = 0; //モーター駆動時間記録(ミリ秒)
//セットアップ=========================================================================
void setup() {
//入出力ピンの設定=====================================================================
  pinMode(FULL_SW,INPUT);
  pinMode(CUTOFF_SW,INPUT);
  pinMode(NO_AMMO_SW,INPUT);
  pinMode(COCKING_FOWARD_SW,INPUT);
  pinMode(COCKING_BACK_SW,INPUT);
  pinMode(SAFETY_SW,INPUT);
  attachInterrupt(digitalPinToInterrupt(SAFETY_SW),SAFETY_MODE,LOW);
  pinMode(LED,OUTPUT);
  pinMode(INDICATOR,OUTPUT);
//起動処理============================================================================
  digitalWrite(INDICATOR,HIGH);
  analogWrite(MOTOR,0);
  delay(1000);             //1秒待つ
}
//メインプログラム====================================================================
void loop() {
  digitalWrite(INDICATOR,LOW);
  Time = millis();        //現在の時間を取得(バッテリー電圧測定用)
  M_Time = millis();      //現在の時間を取得(モーターロック保護処理用)
//現在の各スイッチの状態を検知========================================================
  Cutoff = digitalRead(CUTOFF_SW);
  Semi_Sw = analogRead(SEMI_SW);
  /*セミオートスイッチに光センサーを使うため
   *オン・オフの処理を追加
   */
  if(Semi_Sw >= SW_ON){
    SemiTrg = ON;
    /*光センサーの数値が定数SW_ONの閾値以上の場合
     *セミオートスイッチをオンとする
     */
  }
  if(Semi_Sw <= SW_OFF){
    SemiTrg = OFF;
    /*光センサーの数値が定数SW_OFFの閾値以下の場合
     *セミオートスイッチをオフとする
     */
  }
  FullTrg = digitalRead(FULL_SW);
  No_Ammo = digitalRead(NO_AMMO_SW); 
  Cocking_Back = digitalRead(COCKING_BACK_SW);
   
  //カットオフスイッチの状態をLEDで表示
  if(Cutoff == HIGH){
    digitalWrite(LED,HIGH);
  }
  if(Cutoff == LOW){
    digitalWrite(LED,LOW);
  }
//モーター動作処理==================================================================== 
  if(Fire >= 1){
    //変数Fireが1以上のときモーター作動
    switch (Shot_Mode == FULL){
    //モーターの出力変更
      case FULL:
        if(Fast_Shot == true){
          analogWrite(MOTOR,254);
        }
        else{
          analogWrite(MOTOR,PWM);
        }
        break;
        /*フルオート時、最初の1発は最大出力
         *それ以降、変数PWMの値の出力
         */
        default:
        analogWrite(MOTOR,254);
        //セミオート時、最大出力
      }
//モーターロック保護処理================================================================
      while(M_Time - Old_M_Time >= 200){
        analogWrite(MOTOR,0);
        digitalWrite(INDICATOR,HIGH);
        delay(100);
        digitalWrite(INDICATOR,LOW);
        delay(100);
        /*トリガーが押されてから、または
         *カットオフスイッチを検出してから200ミリ秒以上
         *新たなカットオフスイッチを検出しなかった場合
         *モーターを停止し、インジケーターLEDを点滅する
        */
      }
//残弾無し処理=========================================================================
      if(No_Ammo == HIGH){
         Fire = 1;
        /*残弾無し検知スイッチがオンの時、
         *変数Fireの値を1にする
         */
      }
  }
//カットオフ処理=======================================================================
  if(Fire > 1){
    if(Cutoff == HIGH && Old_Cutoff == LOW){
        Fire = Fire - 1;
        Fast_Shot = false;
        Old_M_Time = M_Time;                          //カットオフ検出の時間を記録(モーターロック保護処理用)
        Val = GetVal(analogRead(VAL_IN));             //電圧を取得
        if(Val < LIMIT_VAL_M){                        //稼働時下限値を下回ったとき
          Battery_Low = true;                         //変数Battery_Lowをtrueにし、
          Fire = 1;                                   //変数Fireの値を1にする
        }
        /*カットオフスイッチがLOWからHIGHなったときに
         *変数Fireの数字を1引き、変数Fast_Shotをfalseにする
         */
    }
    Old_Cutoff = Cutoff;
  }
  if(Fire == 1){
    if(Cutoff == HIGH && Old_Cutoff == LOW){
      analogWrite(MOTOR,254);
      Val = GetVal(analogRead(VAL_IN));               //電圧を取得
        if(Val < LIMIT_VAL_M){                        //稼働時下限値を下回ったとき
          Battery_Low = true;                         //変数Battery_Lowをtrueにする
        }
      if(Cocking_Back == ON || No_Ammo == HIGH){
        delay(DECOCK);
      }else{
        delay(PRECOCK);
      }
      analogWrite(MOTOR,0);
      Fire = 0;
      Shot_Mode = SEMI;
      Fast_Shot = true;
      Time = millis();
      Old_Time = Time;                               //モーターが停止した時間を記録(バッテリー電圧測定用)
      /*変数Fireが1に等しい場合、
       *カットオフスイッチがLOWからHIGHになった時に
       *コッキングハンドル検知スイッチがオフの時
       *定数PRECOCKミリ秒後、モーターを停止し、
       *コッキングハンドル検知スイッチがオンの時、
       *あるいは残弾無し検知スイッチがオンの時、
       *定数DECOCKミリ秒後、モーターを停止する
       */
       
      if(No_Ammo == HIGH){
        //残弾無し処理
        Bolt_Stop = true;
        /*残弾無し検知スイッチがオンの時、
         *ボルトストップを行う
         */
      }
    }
    Old_Cutoff = Cutoff;
  }
  if(Cutoff == LOW && Old_Cutoff == HIGH ){
    delayMicroseconds(CHATA_CUTOFF);
    /*カットオフスイッチがONからOFFになったとき
     *チャタリング防止のため
     *定数CHATA_CUTOFFマイクロ秒停止する
     */  
  }
    
//トリガー処理=========================================================================
  /* 変数Bolt_Stopがfalseの時
   * かつ、変数Battery_Lowがfalseの時のみ
   * トリガー入力を受け付ける
   */
  if(Bolt_Stop == false && Battery_Low == false){
//セミオート処理=======================================================================
    if(Fire == 0 ){
      analogWrite(MOTOR,0);
      Shot_Mode = SEMI;
      /*変数Fireの値が0の時
       *セミオート入力を受け付ける
       */
      if(SemiTrg == ON && Old_SemiTrg == OFF){
        Fire = 1;
        Shot_Mode = SEMI;
        /*セミオートスイッチがOFFからONになったとき
         *変数Fireに1を代入する
         */
        Old_M_Time = M_Time;          //セミオートトリガーが押された時間を記録(モーターロック保護処理用)
      }
  
      if(SemiTrg == OFF && Old_SemiTrg == ON){
        delayMicroseconds(CHATA_SEMI);
        /*セミオートスイッチがONからOFFになったとき
         *チャタリング防止のため
         *定数CHATA_SEMIマイクロ秒停止する
         */
      }
    }   
//フルオート処理=======================================================================
    if(SemiTrg == ON && No_Ammo == LOW){
      if(FullTrg == ON){
        Fire = 2;
        Shot_Mode = FULL;
        /*セミオートスイッチがONのままの場合フルオートスイッチを受け付け
         *フルオートスイッチがONになっている間
         *変数Fireに2を代入し続ける
         */
        if(Old_FullTrg == OFF){
          Old_M_Time = M_Time;         //フルオートトリガーが押された時間を記録(モーターロック保護処理用)
         }
      }
      if(FullTrg == OFF && Old_FullTrg == ON){
        Fire = 1;
        delayMicroseconds(CHATA_FULL);
        /*フルオートスイッチがONからOFFになったとき
         *変数Fireに1を代入し、 
         *チャタリング防止のため
         *定数CHATA_FULLマイクロ秒停止する
         */
      }  
    }
  }
//フル・セミオートスイッチの状態を記録する=============================================
  Old_SemiTrg = SemiTrg;
  Old_FullTrg = FullTrg;
//待機時電圧測定処理===================================================================
  if(Fire == 0 && Time - Old_Time >= 500){        //Fireが0かつ、発射後500msおきに
    Val = GetVal(analogRead(VAL_IN));             //電圧を取得
    if(Val < LIMIT_VAL_S){                        //待機時下限値を下回ったとき
      Battery_Low = true;                         //変数Battery_Lowをtrueにする
    }
    Old_Time = Time;                              //測定した時間を記録
  }
//オートカット処理===================================================================== 
  while(Fire == 0 && Battery_Low == true){        //バッテリー電圧の低下を検出した場合、動作を停止し、
    analogWrite(MOTOR,0);                         //インジケーターLEDを点滅する
    digitalWrite(INDICATOR,HIGH);
    delay(100);
    digitalWrite(INDICATOR,LOW);
    delay(1000);
  }
  noInterrupts();
//ボルトストップ処理===================================================================
  while(Bolt_Stop == true){
    Fire = 0;
    SemiTrg = OFF, Old_SemiTrg = OFF;
    FullTrg = OFF, Old_FullTrg = OFF;
    analogWrite(MOTOR,0);
    digitalWrite(INDICATOR,HIGH);
    while(Cocking_Back == OFF){
      Cocking_Back = digitalRead(COCKING_BACK_SW);
    }
    Cocking_Fowad = digitalRead(COCKING_FOWARD_SW);
    if(Cocking_Fowad == ON){
      No_Ammo = digitalRead(NO_AMMO_SW);
      switch(No_Ammo == LOW){
        case true:
          Bolt_Stop = false;
          digitalWrite(INDICATOR,LOW);
          break;
        default:
          Cocking_Back = OFF;
      }
      
    }
    /*コッキングハンドル後退検知スイッチがオンになった後、
     *残弾無し検知スイッチがオフかつ、
     *コッキングハンドル前進検知スイッチがオンになった時、
     *ボルトストップを解除する
     *コッキングハンドル前進検知スイッチがオンになった時、
     *残弾無し検知スイッチがオンの場合はやり直し
     */
  }
  interrupts();
  if(Fire < 0){
    Fire = 0;
  }
}
//セーフティモード=====================================================================
void SAFETY_MODE() {
  analogWrite(MOTOR,0);
  Fire = 0;
  Semi_Sw = 0;
  Cutoff = LOW, Old_Cutoff = LOW;
  SemiTrg = OFF, Old_SemiTrg = OFF;
  FullTrg = OFF, Old_FullTrg = OFF;
  Shot_Mode = SEMI;
  Fast_Shot = true;
  Cocking_Fowad = LOW;
  Cocking_Back = LOW;
  /*セーフティスイッチがオンの時、
   *モーターを停止し、変数の初期化を行う
   */
}
//センサーの値から電圧を計算===========================================================
unsigned int GetVal(unsigned int A){
  float V,Vcc;
  Vcc = cpuVcc(); //基準電圧の取得
  V = A * Vcc / 1024.0 /V_R2 * (V_R1 + V_R2); 
  return(unsigned int)(V * 100.0+ VF);//100倍して整数にする
}
// 電源電圧(AVCC)測定関数==============================================================
float cpuVcc(){
  unsigned long sum=0;
  adcSetup(0x4E);                    // Vref=AVcc, input=internal1.1V
  for(int n=0; n < 10; n++){
    sum = sum + adc();               // adcの値を読んで積分
  }
  return (1.1 * 10240.0)/ sum;       // 電圧を計算して戻り値にする
}
// ADコンバーターの設定================================================================
void adcSetup(byte data){
  ADMUX = data;                      // ADC Multiplexer Select Reg.
  ADCSRA |= ( 1 << ADEN);            // ADC イネーブル
  ADCSRA |= 0x07;                    // AD変換クロック CK/128
  delayMicroseconds(500);            // 安定するまで待つ
}
// ADCの値を読む=======================================================================
unsigned int adc(){                  
  unsigned int dL, dH;
  ADCSRA |= ( 1 << ADSC);            // AD変換開始
  while(ADCSRA & ( 1 << ADSC) ){     // 変換完了待ち
  }
  dL = ADCL;                         // LSB側読み出し 
  dH = ADCH;                         // MSB側
  return dL | (dH << 8);             // 10ビットに合成した値を返す
}
  

Posted by 名無しのナナシ at 22:24Comments(0)エアガンカスタムエアガンマイコン

2019年05月04日

電子トリガーを作る その3

その2の続き。
電動ガンへの実装を行います。

今回取り付けるのは、G&GのF2000。
ETUが搭載されていない旧式です。


テスト基板を少し変更した実装基板を作りました。



この基板はメカボックスのスイッチが付いていた所に取り付けました。


マイコン基板はバッテリースペース下に入れました。


トリガースイッチは、元の仕様通りフルセミの選択をトリガーストロークで行い、
セミをフォトリフレクタ、フルをマイクロスイッチで検出するようにしました。



そのほか、セーフティスイッチなどを取り付け。


これで実装完了ですが、テストしたところヒューズが飛ぶ問題が起こったので、
次回はその対処とプログラムの改良を行います。  

Posted by 名無しのナナシ at 22:22Comments(0)エアガンカスタムエアガンマイコン

2019年04月09日

電子トリガーを作る その2

その1の続き。
今回はセミオート射撃をできるようにします。

セミオート射撃のために、カットオフを検出できるようにします。
セクターギアに開いている穴に直径5mmの磁石を埋め込み、これをホールICで検出します。



メカボックス越しでは磁力を検出できなかったので、穴を開けます。


ユニバーサル基板にホールICを半田付けし、取り付けのためにメカボックスにネジを切りました。



プログラムは以下の通り。
//カットオフテスト用
//入出力ピンの名称変更
#define SEMI_SW 4 //セミオートスイッチ
#define CUTOFF_SW 3 //カットオフセンサー
#define MOTOR 9 //モーター制御出力
#define LED 13 //マイコンLED
//定数の宣言
const int Chata = 0; //チャタリング防止(マイクロ秒)
const bool ON = LOW; //スイッチ用定数、混乱防止のため
const bool OFF = HIGH;
//変数の宣言
int Fire = 0; //発射制御用変数
bool Coff = LOW; //カットオフセンサー用変数
bool Old_Coff = LOW;
bool SemiTrg = HIGH; //セミオートスイッチ用変数
bool Old_SemiTrg = HIGH;

void setup() {
   //入出力ピンの設定
   pinMode(SEMI_SW,INPUT);
   pinMode(CUTOFF_SW,INPUT);
   pinMode(LED,OUTPUT);
}
void loop() {

   //現在の各スイッチの状態を検知
   Coff = digitalRead(CUTOFF_SW);
   SemiTrg = digitalRead(SEMI_SW);
   
   //カットオフスイッチの状態をLEDで表示
   if(Coff == HIGH){
      digitalWrite(LED,HIGH);
   }
   if(Coff == LOW){
      digitalWrite(LED,LOW);
   }

   if(Fire >= 1){
      analogWrite(MOTOR,254); //変数Fireが1以上のときモーター作動
   }
   if(Fire > 1){
      //カットオフ処理
      if(Coff == HIGH && Old_Coff == LOW){
         Fire = Fire - 1;
         /*カットオフスイッチがLOWからHIGHなったときに
          *変数Fireの数字を1引く
          */
     }
     if(Coff == LOW && Old_Coff == HIGH){
        /*物理スイッチを使用する際のチャタリング防止用      
         */
     }
     Old_Coff = Coff;
   }
   if(Fire == 1){
      if(Coff == HIGH && Old_Coff == LOW){
         analogWrite(MOTOR,0);
         Fire = 0;
         /*変数Fireが1に等しい場合、
          *カットオフスイッチがLOWからHIGHになったとき
          *モーターを停止する
          */
      }
      if(Coff == LOW && Old_Coff == HIGH ){
        /*物理スイッチを使用する際のチャタリング防止用      
         */
      }
      Old_Coff = Coff;
   }
    
   if(Fire == 0){
      /*トリガー処理、変数Fireの値が0の時のみ
       *トリガー入力を受け付ける
       */
      analogWrite(MOTOR,0);
      if(SemiTrg == ON && Old_SemiTrg == OFF){
         Fire = 1;
         /*トリガーがOFFからONになったとき
         *変数Fireに1を代入する
         */
      }
      
      if(SemiTrg == OFF && Old_SemiTrg == ON){
         delayMicroseconds(Chata);
         /*トリガーがONからOFFになったとき
          *チャタリング防止のため
          *変数chataマイクロ秒停止する
          */
      }
      Old_SemiTrg = SemiTrg;
   }
    
   if(Fire < 0){
      Fire = 0;
   }
}
動かすとこんな感じ。
  

Posted by 名無しのナナシ at 22:11Comments(0)エアガンカスタムエアガンマイコン

2019年04月08日

電子トリガーを作る その1

電子トリガーに興味を持ち、色々と調べてみたら
こんなものを見つけて、自分でも作れそうだったので
作ってみることにしました。

以前、ガスガン内蔵ヒーター制御装置を作る際、テストに使ったArduino Nano互換機。
これを使います。
プログラム用のソフト他はこちらを参照してください。


まずはモーターを動かすモータードライバを作ります。
見つけた回路図をほぼそのまま流用して作りました。
詳細についてはこちらを参照してください。


回路図のマイコンVINと出力PINの所をスイッチで繋ぐとそのまま動かせます。


次はマイコンを繋いでテストします。
プログラムは以下の通り。

//モータードライバーテスト用
void setup() {
  pinMode(2,INPUT);
  pinMode(3,INPUT);
  pinMode(4,INPUT);
}

void loop() {
 if(digitalRead(2)==HIGH){
    analogWrite(5,255);   //出力100%、しばらくすると動かなくなる
 }
 else if(digitalRead(3)==HIGH){
    analogWrite(5,123);   //出力50%
 }
 else if(digitalRead(4)==HIGH){
    analogWrite(5,254);   //出力99%、連続使用できる限界
 }
 else{
 analogWrite(5,0);
 }
}
このプログラムをマイコンに書き込み、マイコンのD2,D3,D4にスイッチ、D5に出力PINの所を繋ぎ
動かすとこんな感じです。
このモータードライバーは連続して動かすことができないので、
PWM出力でブートストラップコンデンサを充電する時間を作る必要があります。


次回から電動ガンへの実装を行います。  

Posted by 名無しのナナシ at 23:26Comments(0)エアガンカスタムエアガンマイコン

2019年04月02日

NcStar ADO 3 – 9 x 42mmスコープ&レッドドットサイト

新しく買ったエアガン用にアマゾンに売っていた
NcStarというメーカーのスコープを買いました。




箱の中に専用ケースとスコープがありました。



スコープ本体の見た目。
近未来的なデザインが気に入っています。


スコープを覗くとこんな感じ。


付属している説明書等。
すべて英語で書かれています。



スコープのエレベーションとウィンデージダイヤル。
エレベーションは下に付いています。


ドットサイトのエレベーションとウィンデージダイヤル。
マイナスネジを回して調整します。


本体上部のコントロールパネル。
手前の四角ボタンがスコープ側、奥の丸ボタンがドットサイト側の光量調整です。
中央のボタンでスコープイルミネーションの色を変更できます。
スコープのイルミネーションをオンにするには+ボタンを長押し、 オフにするには+と-ボタンを同時押しします。




ドットサイトは可倒式で左側にロック解除レバーがあります。
ロックを解除すれば自動で立ち上がり、ドットサイトがオンになります。
手で倒せばオフになります。




スコープとドットサイト共通の電源としてCR123A電池を1つ使います。



新しく買ったエアガンに取り付けてみました。
  
タグ :NcStar

Posted by 名無しのナナシ at 00:06Comments(0)装備

2019年03月31日

動画投稿、2月17日分その1

2月17日、福岡サバゲーランドの動画を
投稿しました。




  

Posted by 名無しのナナシ at 21:21Comments(0)サバゲー動画福岡

2019年03月20日

A&K SVDにダブルイーグルM905用マガジンを流用する方法

A&KのSVDを実戦投入するためにマガジンを確保しようとしましたが、
マガジンがどこにも売っていません。
流用できそうなマガジンを探していたら、ダブルイーグルM905用マガジンを見つけました。

右がA&K、左がダブルイーグル。
ぱっと見、よく似ています。



早速マガジンを装着しようとしましたが、案の定入りません。


よく見てみると、前側の出っ張りが少し大きいようなのでヤスリで削りました。
(右がダブルイーグル、左がA&K)



マガジンが入るようになりましたが、今度は給弾されません。
マガジンが小さいようで後ろ側に隙間ができていて、ストッパーを押し切れていないようです。


マガジンの後ろ側にプラ板を接着してストッパーを押せるようにしました。
メカボックスを外した状態で試したら、給弾されるようになりました。



しかし、メカボックスを取り付けた状態で試したら、マガジンキャッチが掛からなくなりました。
メカボックスを避ける凹みの深さが足りていないようです。


へこみの深さはA&Kが15mm、ダブルイーグルは12mm。
3mm削る必要があります。



マガジンの中身を出して、凹みの上側を切除、ヤスリで削ります。



外側もヤスリで削ります。
鉄製で、少し厚みがあるので苦労しました。


装着して給弾することを確認して完了です。   

Posted by 名無しのナナシ at 22:00Comments(0)エアガンカスタムエアガン

2019年03月20日

PSO-1スコープ(レプリカ)

A&KのSVD用にPSO-1レプリカスコープを買いました。



これはアマゾンに売ってあった3-9倍率のモデルです。


重量は722g。


説明書も付属していますが、
すまねぇ、ロシア語はさっぱりだ。



エレベーションとウィンデージダイヤルです。



ゼロインは上についているプラスネジを外して、黒いダイヤルを回して行います。
(実物は上のネジを外さず緩めるだけです。)



マウント取り付けの調整に使うレンチです。

使い方はラジオペンチなどで押さえながらナットを回して調整します。



イルミネーション用の電池は単三電池です。
中国語で書かれた電池が付属しています。


点灯させるとこんな感じです。


A&KのSVDへ取り付けました。
特に加工なしで取り付けられました。
  

Posted by 名無しのナナシ at 19:58Comments(0)装備

2019年03月19日

はじめての流速カスタム(A&K電動SVD)

大分前に購入していた、A&K電動SVD。


一応撃てるようにいじっていますが、M14との差別化ができずに放置していました。
そこで流速カスタムの実験台に使うことにしました。
流速カスタムで0.28g弾を飛ばせるようにし、遠距離特化にします。
まず、分解してメカボックスを取り出します。

本体右側の六角ネジを外します。


マガジンキャッチ付近のピンを左側から抜き出します。


トリガーガードを取り外し、レシーバー下の部品を取り外します。



チャンバーブロック両脇の芋ネジを緩めて取り外します。
チャンバーは同社製ミニミと同様の構造で、同じような改良をしてあります。
ついでに長掛けホップにしてあります。


メカボックスを後ろに引きながら、前側を下から押し上げて取り外します。




メカボックス後ろからスプリングを取り外せます。


タペットスプリングは外に露出しているので取り外します。


メカボックスのプラスネジを外して分割します。


流速カスタムの原理などは検索すればいっぱい出てくるので省略。
ピストンに重りをつけて重くして、強めのスプリングを入れます。

ピストンに鉛シートで作った重りを入れて、35g程にします。
スプリングはKM企画の0.9Jスプリングを入れます。



このままでは法定初速をオーバーするので、インナーバレルを切断して調整します。
588mm→200mmに切断しました。




ついでにモーターを交換し、FETを取り付けます。
モーターはSHSのハイトルクモーターに交換します。


モータ軸が少し長いので切断して調整しました。



FETはXCORTECHのデュアルFETをグリップ内の空洞に入るように取り付けました。


レスポンスを向上させるため、11.1Vリポバッテリーを使います。


コネクターはXT60コネクターに交換しました。



これでカスタム完了です。
初速をマルイ0.20、0.25、0.28gの弾を使い、ホップ最弱時の初速と初速最大値を測ります。

0.20gホップ最弱 81.1m/s


0.20g初速最大 93.2m/s


0.25gホップ最弱 76.8m/s


0.25g初速最大 83.4m/s


0.28gホップ最弱 75.7m/s


0.28g初速最大 79.6m/s


どの弾でも0.9J以下でちょうどいいぐらいです。  

Posted by 名無しのナナシ at 23:35Comments(0)エアガンカスタムエアガン

2019年02月11日

M1918の修理その2

前回のM1918の修理のつづき。
出来たロウ原型から石膏型を作ります。


使うのはアマゾンで売っていたノリタケ 鋳造用石膏 (G-2)。
これに水を加えて攪拌し、型に流し込みます。
水の量は、石膏の量(g)×混水量(%)で、この石膏の混水量は46~50%なので
1kgに対して水を460~500ml入れます。



水を加えた石膏にロウ原型を沈めます。
ロウが石膏より比重が軽いので浮いてこなくなるまで上から押さえておきます。
1日ほど置いて固まったら枠を外し、湯口を広げます。



鋳造をする前に石膏を250℃で乾燥させる必要があるので、コンベクションオーブンを用意しました。


オーブンを予熱してから、温度を250℃に設定し、完全に乾燥するまで加熱します。
このときロウ原型も揮発して無くなります。
注意 とても臭いがきついので十分に換気してください。



いよいよ鋳造を行います。
アマゾンで買ってきた亜鉛合金に、ルツボとして100均に売ってあったステンレスのカップを使います。



七輪に木炭を入れて火を起こします。



亜鉛合金を入れたカップを火に掛けて中が溶けるまで加熱します。
この亜鉛合金の融点は500℃程度なので割りと簡単に溶けました。



溶けた亜鉛合金を石膏型に流し込み、冷えてから型を破壊して取り出します。


余分な部分を削って元のパーツと見比べてみました。
表面が粗いですがちゃんと出来ているようです。



重量は元のパーツが109g、作ったものが105g。


本体に取り付けられるようにタップを立てます。
タップはM3×0.5ピッチのものです。



肉盛りした部分が邪魔してアウターバレルが奥まで入らなかったので
アウターバレル側を削りました。



アウターバレルを取り付けるためのタップを立てて完成。
何とか元通りにできました。  

Posted by 名無しのナナシ at 20:14Comments(1)エアガン整備エアガン

2019年02月11日

M1918の修理その1

M1918を壊してしまいました。



うっかり落としたときにチャンバーブロックが真っ二つ。
普通ならパーツ交換すれば良いのですが、
この銃はパーツが売っていません。


エポキシ接着剤でくっつけてみましたが、重いアウターバレルを支えるには強度が不足しています。
つまり修理不可能、この銃は廃棄処分になってしまいます。
それでは困るのでなんとかします。

どうするかというと、壊れたパーツを元に複製します。
具体的には、
壊れたパーツをシリコンで型取り

シリコン型でロウ原型を作成

ロストワックス法で石膏型を作成

亜鉛合金で鋳造

仕上げ、タップ立て

完成

今回はロウ原型を作るところまでいきます。



紙コップを枠に使ってシリコンを流し込みます。
シリコン型は上下で分割するので、半分は粘土で埋めておきます。


シリコンを流し込む前に剥離剤を塗ります。


今回使ったシリコンはA材とB材を同量混ぜるタイプです。


剥離剤が乾いた後、シリコンを流し込みます。



シリコンが固まったら裏返して、粘土を取り除きます。


ロウを流し込む湯口を付けてみましたが、この形では型からそのまま抜き取ることが出来ませんでした。
剥離剤を塗って枠を取り付け、再びシリコンを流し込みます。



シリコンが固まったら枠から外し、型を割り、原型を取り外します。


流し込むロウは100均に売ってあった仏壇用のものです。



湯煎で溶かして型に流し込みます。
流し込んだらすぐに揺すって空気を抜きます。


型から取り外し、バリを取り、別に作った湯口を取り付けてロウ原型は完成です。
次回は鋳造をします。  

Posted by 名無しのナナシ at 01:27Comments(0)エアガン整備エアガン

2019年02月11日

動画投稿、8月12日分

2018年8月12日、大分CAMP御戦フィールドの動画を投稿しました。





  

Posted by 名無しのナナシ at 00:20Comments(0)サバゲー動画大分

2019年01月30日

エマージェンシーショットシェルキャリア(ESC)

エマージェンシーショットシェルキャリア(ESC)を買ってみました。




本体のほかに専用ハードケースとホルスター、説明書が入っています。
セーフティピンはホルスターに付いています。




本体上のチャンバーロックを後ろに引きながらバレルを持ち上げるとシェルが取り出せます。



シェルのリム部分を回すと分解できます。
中身はモスカートを小さくした感じです。
バレル部分の取り外しは、ケース部を持ってペンチなどで回して外します。
ただし、取り外す前にケース部に取り付けられているバルブを先に外す必要があります。
取り付けはバレルから先に取り付けます。  

Posted by 名無しのナナシ at 23:53Comments(0)エアガン

2019年01月16日

スプリング式グレネード

スプリング式のグレネードを買いました。



SP製というオレンジのものと、GBR製というグレーのものです。






見た目はグレーの方がかっこいいですが、オレンジの方が丈夫そうです。



弾は両方とも下の蓋を開けて入れます。
グレーの方は飛び出していて、下から落とすと破損しそうです。




信管部分は上の六角を回すと感度を調整できるそうです。
締めると感度が鋭くなり、緩めると鈍くなります。
あまり締めすぎると安全ピンを付けていても起爆してしまいます。



オレンジの方は上のネジを外すと分解できます。
グレーの方はピンで結合してあり分解が困難です。




信管部分の構造は外羽のツメに上から乗った状態で引っかかるように止まっており、
上に持ち上げると開きます。  

Posted by 名無しのナナシ at 22:44Comments(0)エアガン

2018年11月25日

ガスガン内蔵ヒーター制御装置を作る その4

ヒーター制御装置の実装をします。




マイコンボードは更に小型のものを使います。

Digisparkというマイコンボードの互換機で
マイコンの仕様についてはこちら

このマイコンを使うときは、こちらの手順にしたがって開発環境を インストールする必要があります。
ただ、不具合があるようなのでインストールパッケージ定義をこちらのものに変更してください。

プログラムは入出力関係を少し変更する必要があります。

//ヒーター制御プログラムテスト(Digispark用)
//入出力ピンの名称変更
#define HEATER 0          //ヒーター制御出力
#define Temp_Input A1    //サーミスタ入力
#define Val_Input A2     //電圧測定入力
#define LED 1            //マイコンLED

//定数の宣言
const int V_R1 = 1000;     //電圧測定VIN側抵抗値(Ω)
const int V_R2 = 1000;     //電圧測定GND側抵抗値(Ω)
const int B = 4100;       //サーミスタB定数
const long T_R1 = 10000;   //サーミスタ基準抵抗値[Ω]
const long T_R2 = 10000;    //サーミスタバランス抵抗[Ω]
const int T0 = 298;       //サーミスタ基準温度[K]
const int Limit_Val = 740;    //測定電圧下限値[V×100]
const int Limit_L_Temp = -200,Limit_H_Temp = 400;  //正常温度閾値[℃×10]
const int L_Temp = 280;  //温度下限値[℃×10]
const int H_Temp = 300;  //温度上限値[℃×10]
//変数の宣言
float Vcc = 0;            //基準電圧[V]
int Val = 0;              //測定電圧[V×100]
int Temp = 0;             //測定温度[℃×10]

void setup () {
  //入出力ピンの設定
  pinMode(HEATER, OUTPUT);
  pinMode(LED, OUTPUT);
}

void loop () {
  Vcc = cpuVcc();                                //基準電圧の取得
  Temp = GetTemp(analogRead(Temp_Input));        //温度の取得
  Val = GetVal(analogRead(Val_Input));           //電圧を取得

  while (Temp > Limit_H_Temp || Temp < Limit_L_Temp){   //測定温度が正常な範囲内から外れると
    digitalWrite(HEATER, LOW);                          //ヒーターをオフにし、マイコンLEDが短い間隔で点滅する
    digitalWrite(LED, HIGH);
    delay(100);
    digitalWrite(LED, LOW);
    delay(100);
  }
  while (Val < Limit_Val) {                      //測定電圧が下限値を下回るとヒーターをオフにし、
    digitalWrite(HEATER, LOW);                   //マイコンLEDが長い間隔で点滅する
    digitalWrite(LED, HIGH);
    delay(100);
    digitalWrite(LED, LOW);
    delay(1000);
  }
  
  if (Temp <= L_Temp) {                         //測定温度が下限値以下になると
    digitalWrite(HEATER, HIGH);                 //ヒーターをオンにする
  }
  
  if (Temp >= H_Temp) {                         //測定温度が上限値以上になると
    digitalWrite(HEATER, LOW);                  //ヒーターをオフにする
  }
  delay(100);                                    //0.1s待つ
}
//センサーの値から温度を計算
float GetTemp (int raw) {
  float V_R2 ;
  float R ;
  float t;

  V_R2 = raw * Vcc / 1.024;                                         //バランス抵抗の消費電圧を算出
  R = Vcc * 1000.0 / V_R2 * T_R2 - T_R2;                            //サーミスタの抵抗値を算出
  t = (1000 / (1 / (0.001 * T0) + log(R / T_R1) * 1000 / B) - 273); //温度の計算
  return (int)(t * 10.0);                                           //10倍にして整数にする
}
//センサーの値から電圧を計算
int GetVal(int A) {
  float V;
  V = A * Vcc / 1024.0 / V_R2 * (V_R1 + V_R2);                      //電圧の計算
  return (int)(V * 100.0);                                //100倍して整数にする
}

float cpuVcc() {                     // 電源電圧(AVCC)測定関数
  long sum = 0;
  adcSetup(0x0C);                    // Vref=Vcc, input=internal1.1V
  for (int n = 0; n < 10; n++) {
    sum = sum + adc();               // adcの値を読んで積分
  }
  return (1.1 * 10240.0) / sum;      // 電圧を計算して戻り値にする
}

void adcSetup(byte data) {           // ADコンバーターの設定
  ADMUX = data;                      // ADC Multiplexer Select Reg.
  ADCSRA |= ( 1 << ADEN);            // ADC イネーブル
  ADCSRA |= 0x07;                    // AD変換クロック CK/128
  delayMicroseconds (500);             // 安定するまで待つ
}

unsigned int adc() {                 // ADCの値を読む
  unsigned int dL, dH;
  ADCSRA |= ( 1 << ADSC);            // AD変換開始
  while (ADCSRA & ( 1 << ADSC) ) {   // 変換完了待ち
  }
  dL = ADCL;                         // LSB側読み出し
  dH = ADCH;                         // MSB側
  return dL | (dH << 8);             // 10ビットに合成した値を返す
}




アナログ入力に干渉するため、
マイコンボードについているツェナーダイオードを取り外しています。



前回試した回路に取り付けて問題ないか確認しました。



実装する回路図はこちら。
ヒューズと電源スイッチ、プログラムを書き込むときに回路を切り離すスイッチを追加しました。





これをケースの中に入れて完成です。

最終的なプログラムはこちら。

//ヒーター制御プログラムVer.1.00(Digispark用)
//入出力ピンの名称変更=================================================================
#define HEATER 0          //ヒーター制御出力
#define Temp_Input A1    //サーミスタ入力
#define Val_Input A2     //電圧測定入力
#define LED 1            //マイコンLED
//定数の宣言===========================================================================
const int V_R1 = 1000;     //電圧測定VIN側抵抗値(Ω)
const int V_R2 = 1000;     //電圧測定GND側抵抗値(Ω)
const int B = 4100;       //サーミスタB定数
const long T_R1 = 10000;   //サーミスタ基準抵抗値[Ω]
const long T_R2 = 10000;    //サーミスタバランス抵抗[Ω]
const int T0 = 298;       //サーミスタ基準温度[K]
const int Limit_Val_S = 740;    //待機時電圧下限値[V×100]
const int Limit_Val_M = 730;    //稼働時電圧下限値[V×100]
const int Limit_L_Temp = -200,Limit_H_Temp = 400;  //正常温度閾値[℃×10]
const int L_Temp = 280;  //温度下限値[℃×10]
const int H_Temp = 300;  //温度上限値[℃×10]
//変数の宣言===========================================================================
float Vcc = 0;            //基準電圧[V]
int Val = 0;              //測定電圧[V×100]
int Temp = 0;             //測定温度[℃×10]
bool Battry_Low = false;  //オートカット用変数
bool Heater_sw = LOW;     //ヒータースイッチ
//セットアップ=========================================================================
void setup () {
//入出力ピンの設定=====================================================================
  pinMode(HEATER, OUTPUT);
  pinMode(LED, OUTPUT);
//起動処理============================================================================
  digitalWrite(HEATER, LOW);
  digitalWrite(LED, LOW);
}
//メインプログラム=====================================================================
void loop () {
//各センサーの数値を取得===============================================================
  Vcc = cpuVcc();                            //基準電圧の取得
  Temp = GetTemp(analogRead(Temp_Input));    //温度の取得
  Val = GetVal(analogRead(Val_Input));       //電圧を取得
//温度異常セーフティ処理===============================================================
  while (Temp > Limit_H_Temp || Temp < Limit_L_Temp){   //測定温度が正常な範囲内から外れると
    digitalWrite(HEATER, LOW);                          //ヒーターをオフにし、マイコンLEDが短い間隔で点滅する
    digitalWrite(LED, HIGH);
    delay(100);
    digitalWrite(LED, LOW);
    delay(100);
  }
//オートカット判定=====================================================================
  switch(Heater_sw == HIGH){
    case true:
      if (Val < Limit_Val_M){          //ヒーターがオンの時、稼働時下限値以下の時、
        Battry_Low = true;             //変数Battry_Lowをtrueにする
      }
      break;
    default:
      if (Val < Limit_Val_S){            //ヒーターがオフの時、待機時下限値以下の時、
        Battry_Low = true;             //変数Battry_Lowをtrueにする
      }
  }
//オートカット処理=====================================================================
  while (Battry_Low == true){         //変数Battry_Lowをtrueの時、ヒーターをオフにし、
    digitalWrite(HEATER, LOW);         //マイコンLEDが長い間隔で点滅する
    digitalWrite(LED, HIGH);
    delay(100);
    digitalWrite(LED, LOW);
    delay(1000);
  }
//ヒーター制御処理=====================================================================
  if (Temp <= L_Temp) {               //測定温度が下限値以下になると
    Heater_sw = HIGH;                 //ヒーターをオンにする
  }
  
  if (Temp >= H_Temp) {               //測定温度が上限値以上になると
    Heater_sw = LOW;                  //ヒーターをオフにする
  }
  digitalWrite(HEATER,Heater_sw);
  delay(100);                         //0.1s待つ
}
//センサーの値から温度を計算===========================================================
float GetTemp (int raw) {
  float V_R2 ;
  float R ;
  float t;

  V_R2 = raw * Vcc / 1.024;                                         //バランス抵抗の消費電圧を算出
  R = Vcc * 1000.0 / V_R2 * T_R2 - T_R2;                            //サーミスタの抵抗値を算出
  t = (1000 / (1 / (0.001 * T0) + log(R / T_R1) * 1000 / B) - 273); //温度の計算
  return (int)(t * 10.0);                                           //10倍にして整数にする
}
//センサーの値から電圧を計算===========================================================
int GetVal(int A) {
  float V;
  V = A * Vcc / 1024.00 / V_R2 * (V_R1 + V_R2);            //電圧の計算
  return (int)(V * 100.0);                                //100倍して整数にする
}
//電源電圧(AVCC)測定関数===============================================================
float cpuVcc() {
  long sum = 0;
  adcSetup(0x0C);                    // Vref=Vcc, input=internal1.1V
  for (int n = 0; n < 10; n++) {
    sum = sum + adc();               // adcの値を読んで積分
  }
  return (1.1 * 10240.0) / sum;      // 電圧を計算して戻り値にする
}
//ADコンバーターの設定===================================================
void adcSetup(byte data) {           
  ADMUX = data;                      // ADC Multiplexer Select Reg.
  ADCSRA |= ( 1 << ADEN);            // ADC イネーブル
  ADCSRA |= 0x07;                    // AD変換クロック CK/128
  delayMicroseconds (500);          // 安定するまで待つ
}
//ADCの値を読む==========================================================
unsigned int adc() {
  unsigned int dL, dH;
  ADCSRA |= ( 1 << ADSC);            // AD変換開始
  while (ADCSRA & ( 1 << ADSC) ) {   // 変換完了待ち
  }
  dL = ADCL;                         // LSB側読み出し
  dH = ADCH;                         // MSB側
  return dL | (dH << 8);             // 10ビットに合成した値を返す
}

稼働時間を少しでも延ばすため、
ヒーター稼動時と待機時で電圧下限値を変えてあります。



使うときはベルトに取り付けたラジオポーチに入れて使います。  

Posted by 名無しのナナシ at 23:50Comments(0)エアガンカスタムエアガンマイコン

2018年11月11日

ガスガン内蔵ヒーター制御装置を作る その3

前回テストした回路を実装していきます。
まずはガスガン側から。



ガスガン~制御回路の配線は4芯カールコードを使います。



ガスガンと制御回路を切り離せるようにコネクターを取り付けます。



サーミスタはフィルムヒーターに直接接着します。
これはマガジンが装着されていない状態でも温度が上がり過ぎないようにするためです。




万が一の保険に72℃の温度ヒューズを取り付けました。



テストして問題ないか確認。
次回は制御回路の実装を行います。  

Posted by 名無しのナナシ at 23:35Comments(0)エアガンカスタムエアガンマイコン

2018年11月10日

ガスガン内蔵ヒーター制御装置を作る その2

ヒーター制御装置の回路とプログラムを作っていきます。

まずテスト用の回路図を作成しました。



NTCサーミスタを使った分圧回路で温度を検知し、FETでヒーターのオン・オフを行います。
バッテリーの電圧は固定抵抗を使った分圧回路を用いて検知します。



これをブレッドボード上で組み立て、テストを行います。

プログラムの方は、まず温度と電圧を読み取り、シリアルモニタに表示するプログラムを作成しました。

//ヒーター制御入力テスト用
//定数の宣言
const int V_R1 = 1000;     //電圧測定VIN側抵抗値[Ω]
const int V_R2 = 1000;     //電圧測定GND側抵抗値[Ω]
const int B = 4100     //サーミスタB定数
const int T_R0 = 10000;     //サーミスタ基準抵抗値[Ω]
const int T_R1 = 10000;     //バランス抵抗[Ω]
const int T0 = 298;     //サーミスタ基準温度[K]
//変数の宣言
float Vcc = 0;     //基準電圧[V]
int Val = 0;     //測定電圧[V×100]
int Temp = 0;     //測定温度[℃×10]

void setup () {
  Serial.begin(9600);     // 9600 bpsで接続
  Serial.println("READ_START");     // 最初に1度だけ Start を表示

void loop () {
  Vcc = cpuVcc();      //基準電圧の取得
  Temp = GetTemp(analogRead(A0));     //温度の取得
  Val = GetVal(analogRead(A1));      //電圧を取得
  Serial.print("Vcc=");     //基準電圧の表示
  Serial.print(Vcc);
  Serial.print(" TEMP=");     //温度の表示
  Serial.print(Temp);
  Serial.print(" V=");     //電圧の表示
  Serial.println(Val);
  delay(50);     // 0.05s 待つ
}
//センサーの値から温度を計算
float GetTemp (int raw){
  float V_R0 ;
  float R ;
  float t;
   
  V_R0 = raw * Vcc / 1.024;     //回路内抵抗の消費電圧を算出
  R = Vcc * 1000.0 / V_R0 * T_R1 - T_R1;     //サーミスタの抵抗値を算出
  t = (1000 / (1 / (0.001 * T0)+log(R / T_R0)*1000 / B) - 273);     //温度の計算
  return(int)(t * 10.0);     //10倍にして整数にする
}
//センサーの値から電圧を計算
int GetVal(int A){
  float V;
  V = A * Vcc / 1024.0 /V_R2 * (V_R1 + V_R2);     //電圧の計算
  return(int)(V * 100.0);     //100倍して整数にする
}

float cpuVcc(){     // 電源電圧(AVCC)測定関数
  long sum=0;
  adcSetup(0x4E);     // Vref=AVcc, input=internal1.1V
  for(int n=0; n < 10; n++){
    sum = sum + adc();     // adcの値を読んで積分
  }
  return (1.1 * 10240.0)/ sum;     // 電圧を計算して戻り値にする
}
 
void adcSetup(byte data){     // ADコンバーターの設定
  ADMUX = data;     // ADC Multiplexer Select Reg.
  ADCSRA |= ( 1 << ADEN);     // ADC イネーブル
  ADCSRA |= 0x07;     // AD変換クロック CK/128
  delayMicroseconds (500);     // 安定するまで待つ
}
 
unsigned int adc(){     // ADCの値を読む
  unsigned int dL, dH;
  ADCSRA |= ( 1 << ADSC);     // AD変換開始
  while(ADCSRA & ( 1 << ADSC) ){     // 変換完了待ち
  }
  dL = ADCL;     // LSB側読み出し 
  dH = ADCH;      // MSB側
  return dL | (dH << 8);     // 10ビットに合成した値を返す
}

以上のプログラムを書き込み、バッテリーを接続後、シリアルモニタを表示すると下のように表示します。
(このプログラムを使う際、マイコンVINの接続を切っておかないと、バッテリー電圧が高く表示されてしまいます。)


うまく表示できたら、今度はヒーターを動かしてみます。



プログラムは以下の通り。

//ヒーター制御プログラムテスト
//入出力ピンの名称変更
#define HEATER 2     //ヒーター制御出力
#define Temp_Input A0     //サーミスタ入力
#define Val_Input A1     //電圧測定入力
#define LED 13     //マイコンLED

//定数の宣言
const int V_R1 = 1000;     //電圧測定VIN側抵抗値(Ω)
const int V_R2 = 1000;     //電圧測定GND側抵抗値(Ω)
const int B = 4100;     //サーミスタB定数
const int T_R0 = 10000;     //サーミスタ基準抵抗値[Ω]
const int T_R1 = 10000;     //サーミスタバランス抵抗値[Ω]
const int T0 = 298;     //サーミスタ基準温度[K]
const int Limit_Val = 740;     //測定電圧下限値[V×100]
const int Limit_L_Temp = -200,Limit_H_Temp = 400;     //正常温度閾値[℃×10]
const int L_Temp = 280;     //温度下限値[℃×10]
const int H_Temp = 300;     //温度上限値[℃×10]
//変数の宣言
float Vcc = 0;     //マイコン電源電圧[V]
int Val = 0;     //測定電圧[V×100]
int Temp = 0;     //測定温度[℃×10]

void setup () {
  //入出力ピンの設定
  pinMode(HEATER, OUTPUT);
  pinMode(LED, OUTPUT);
  delay(1000);     //電源投入時1s待つ
}

void loop () {
  Vcc = cpuVcc();     //マイコン電源電圧の取得
  Temp = GetTemp(analogRead(Temp_Input));     //温度の取得
  Val = GetVal(analogRead(Val_Input));      //電圧を取得

  while (Val < Limit_Val) {     //測定電圧が下限値を下回るとヒーターをオフにし、
    digitalWrite(HEATER, LOW);     //マイコンLEDが長い間隔で点滅する
    digitalWrite(LED, HIGH);
    delay(100);
    digitalWrite(LED, LOW);
    delay(1000);
  }

  while (Temp > Limit_H_Temp || Temp < Limit_L_Temp){     //測定温度が正常な範囲内から外れると
    digitalWrite(HEATER, LOW);     //ヒーターをオフにし、マイコンLEDが短い間隔で点滅する
    digitalWrite(LED, HIGH);
    delay(100);
    digitalWrite(LED, LOW);
    delay(100);
  }

  digitalWrite(13, LOW);
  
  if (Temp <= L_Temp) {     //測定温度が下限値以下になると
    digitalWrite(HEATER, HIGH);     //ヒーターをオンにする
  }
  
  if (Temp >= H_Temp) {     //測定温度が上限値以上になると
    digitalWrite(HEATER, LOW);     //ヒーターをオフにする
  }
  delay(100);     //0.1s待つ
}
//センサーの値から温度を計算
float GetTemp (int raw) {
  float V_R0 ;
  float R ;
  float t;

  V_R0 = raw * Vcc / 1.024;     //バランス抵抗の消費電圧を算出
  R = Vcc * 1000.0 / V_R0 * T_R1 - T_R1;     //サーミスタの抵抗値を算出
  t = (1000 / (1 / (0.001 * T0) + log(R / T_R0) * 1000 / B) - 273);     //温度の計算
  return (int)(t * 10.0);     //10倍にして整数にする
}
//センサーの値から電圧を計算
int GetVal(int A) {
  float V;
  V = A * Vcc / 1024.0 / V_R2 * (V_R1 + V_R2);     //電圧の計算
  return (int)(V * 100.0);     //100倍して整数にする
}

float cpuVcc() {     // 電源電圧(AVCC)測定関数
  long sum = 0;
  adcSetup(0x4E);     // Vref=AVcc, input=internal1.1V
  for (int n = 0; n < 10; n++) {
    sum = sum + adc();     // adcの値を読んで積分
  }
  return (1.1 * 10240.0) / sum;     // 電圧を計算して戻り値にする
}

void adcSetup(byte data) {     // ADコンバーターの設定
  ADMUX = data;     // ADC Multiplexer Select Reg.
  ADCSRA |= ( 1 << ADEN);     // ADC イネーブル
  ADCSRA |= 0x07;     // AD変換クロック CK/128
  delayMicroseconds (500);     // 安定するまで待つ
}

unsigned int adc() {     // ADCの値を読む
  unsigned int dL, dH;
  ADCSRA |= ( 1 << ADSC);     // AD変換開始
  while (ADCSRA & ( 1 << ADSC) ) {     // 変換完了待ち
  }
  dL = ADCL;     // LSB側読み出し
  dH = ADCH;     // MSB側
  return dL | (dH << 8);     // 10ビットに合成した値を返す
}

プログラムの動きとしては、
電源接続後、1秒待ってから動作開始。

温度、電圧の取得。

電圧が下限値(7.4V)を下回ると無限ループで停止、LEDを1秒間隔、0.1秒点灯させる。

温度が異常な値(40℃を超え、-20℃を下回る)を示すと無限ループで停止、LEDを0.1秒間隔、0.1秒点灯させる。

温度が下限値(28℃)以下になるとヒーターをオンにする。

温度が上限値(30℃)以上になるとヒーターをオフにする。

以下繰り返し。

テストの結果うまくいったので、次からは実装を行います。  

Posted by 名無しのナナシ at 21:13Comments(0)エアガンカスタムエアガンマイコン