2016-01-09

ガルパン KV-2 その7

ガルパン KV-2 その7です。
マスキングしてサフ噴きました。
忘れない様に回路図を載っけときます。

 Arduinoのスケッチも載せときます。

/// KV-2
/// JOYSTIK_crawler_PWM_04
/// 4ch JOYSTIK receiver Crawler
#include
#define IR_IN   2  // IR Receiver
#define NEC    1
#define BUF_SIZE  (512)
#define DATA 0
int ND0 = 0;  //反転コード
int ND1 = 0;  //データコード
int ND2 = 0;  //カスタムコード
int ND3 = 0;  //カスタムコード
int PWML = 0; //左速度
int PWMR = 0; //右速度
int ROT = 90; //砲塔センター
Servo servo09;  //サーボの名称を設定
//Servo servo10;  //サーボの名称を設定

void setup()  {
  pinMode( IR_IN , INPUT );//IR input
  pinMode(3, OUTPUT);//L正転
  pinMode(5, OUTPUT);//L反転
  pinMode(6, OUTPUT);//R正転
  pinMode(11, OUTPUT);//R反転
  pinMode(12, OUTPUT);//砲火
  servo09.attach( 9);//砲塔旋回
  servo09.write(90);//砲塔初期位置
  //servo10.attach(10);//サーボ割り当て
  Serial.begin(115200);//シリアルスピードセット(実装時は削除)
}

void loop() {
  //ここからブラックボックス
  unsigned long usec, nec_data = 0;
  unsigned int i, n, irOffTime, minTime, aveCnt = 0, aveAdd = 0;
  unsigned int irdata[ BUF_SIZE ], timeunit, leaderH, leaderL, datalen;
  unsigned int format = 0, hex = 0, sony_data = 0, sony_adrs = 0, sony_adrs_bit = 0;
  boolean isvalid = true;
  // ● 赤外線を感知するまで待つ
  while ( digitalRead( IR_IN ) == HIGH );
  // ● 生データの取得
  for ( i = 0; i < BUF_SIZE; ) {
    usec = micros();
    while ( digitalRead( IR_IN ) == LOW );          // IR信号がONの時間を測定
    irdata[  i] = micros() - usec;
    irdata[++i] = 0;
    usec = micros();
    while ( digitalRead( IR_IN ) == HIGH ) {        // IR信号がOFFの時間を測定
      irOffTime = micros() - usec;
      if ( irOffTime > 65000 ) goto ir_exit;        // 信号途絶なら終了
    }
    irdata[i++] = irOffTime;
  }
ir_exit:
  // ● 時間単位を調べる
  minTime = irdata[0];                    // まず最小値を確認
  for ( i = 0; irdata[i]; i++) minTime = min( minTime, irdata[i]);
  for ( i = 0; irdata[i]; i++) {          // 最小値の+50%までを時間単位とする
    if ( minTime * 3 / 2 > irdata[i] ) {
      aveAdd += irdata[i] - minTime;
      aveCnt++;
    }
  }
  timeunit = aveAdd / aveCnt + minTime;
  if ( timeunit < 300 ) return;           // 時間単位が短すぎるときは異常と判断
  // ● 時間単位でのデータに変換
  for ( i = 0; irdata[i]; i++) irdata[i] = ( irdata[i] + timeunit / 2 ) / timeunit;
  // ● 解析しやすくするためにデータの整理
  leaderH = irdata[0];                // リーダ部Highの長さ
  leaderL = irdata[1];                // リーダ部Low の長さ
  for ( i = 0;; i += 2) {             // データ解析用にリーダ部とリピートを除去・整理
    irdata[i] = irdata[i + 2];
    irdata[i + 1] = irdata[i + 3];
    if ( irdata[i + 1] > 10 || irdata[i + 1] == 0 ) {
      irdata[i + 1] = 0;
      datalen = i / 2 + 1;
      break;
    }
  }
  if ((leaderH > 14 || leaderH < 18) && leaderL == 8 ) {
    format = NEC;
  }
  // ● フォーマット毎に結果を表示
  switch ( format ) {
    case NEC:      // ■ NECフォーマット
      for ( n = 0; n < datalen - 1; n++) { // ストップビット手前まで繰り返し
        nec_data |= ( (irdata[n * 2 + 1] == 1) ? 0UL : 1UL ) << n;
      }
      if ( !isvalid ) break;   // データに不具合があれば以降は表示しない
      //ここまでブラックボックス

      //ドライバ制御ここから
      ND0 = (nec_data      ) % 256 ;//L_PWM
      ND1 = (nec_data >>  8) % 256 ;//R_PWM
      ND2 = (nec_data >> 16) % 256 ;//Action A
      ND3 = (nec_data >> 24) % 256 ;//Action B

      Serial.print(ND3, HEX);   // コードを表示  実装時は削除
      Serial.print(" ");        //               実装時は削除
      Serial.print(ND2, HEX);   // コードを表示  実装時は削除
      Serial.print(" ");        //               実装時は削除
      Serial.print(ND1, HEX);   // コードを表示  実装時は削除
      Serial.print(" ");        //               実装時は削除
      Serial.print(ND0, HEX);   // コードを表示  実装時は削除
      Serial.print(" ");        //               実装時は削除
      Serial.println(ROT);      // コードを表示  実装時は削除

      // ND0をL, ND1をRに割り当て
      // NDxのセンターを90度としてPWM出力
      // 116〜140を不感帯とする。

      // 3:L正転、5:L反転
      if (ND0 > 140 ) {
        PWML = (ND0 - 128) * 2 ; //128以上はマイナス128して倍に
        analogWrite(3, PWML)   ; //L正転
        analogWrite(5, 0   )   ;
      }
      else if  (ND0 < 116 ) {
        PWML = (127 - ND0) * 2 ; //128未満は反転して倍に
        analogWrite(3, 0   )   ;
        analogWrite(5, PWML)   ; //L反転
      }
      else {
        PWML = 0;
        analogWrite(3, 0)      ; //L stop
        analogWrite(5, 0)      ; //L stop
      }

      // 6:R正転、11:R反転
      if (ND1 > 140 ) {
        PWMR = (ND1 - 128) * 2 ; //128以上はマイナス128して倍に
        analogWrite(6, PWMR)   ; //R正転
        analogWrite(11, 0  )   ;
      }
      else if  (ND1 < 116 ) {
        PWMR = (127 - ND1) * 2 ; //128未満は反転して倍に
        analogWrite(6, 0      );
        analogWrite(11, PWMR)  ; //R反転
      }
      else {
        PWMR = 0;
        analogWrite(6, 0)    ; //R stop
        analogWrite(11, 0)   ; //R stop
      }

      // 0V(000)判定  JOYSTIK_button 砲火
      if (            ND3 <  20 ) {  //0V検出
        digitalWrite(12, HIGH); //砲火点灯
        analogWrite ( 3,   0 ); //
        analogWrite ( 5, 255 ); //L反転
        analogWrite ( 6,   0 ); //
        analogWrite (11, 255 ); //R反転
        delay       (    
          80 ); //後退

        digitalWrite(12, LOW ); //砲火消灯
        analogWrite ( 3, 255 ); //L正転
        analogWrite ( 5,   0 ); //
        analogWrite ( 6, 255 ); //正反転
        analogWrite (11,   0 ); //
        delay       (     50 ); //前進

        analogWrite ( 3,   0 ); //stop
        analogWrite ( 5,   0 ); //stop
        analogWrite ( 6,   0 ); //stop
        analogWrite (11,   0 ); //stop
      }

      // 1V(051)判定:砲塔右旋回
      if (ND3 >  31 && ND3 <  71 ) {  //1V検出
        ROT = ROT + 4;
        if ( ROT > 170 ) {
          ROT = 170;
        }
        servo09.write(ROT);
        //} else {
        //digitalWrite(8, LOW);
      }

      // 1V(051)判定:砲塔左旋回
      if (ND2 >  31 && ND2 <  71 ) {  //1V検出
        ROT = ROT - 4;
        if ( ROT < 10 ) {
          ROT = 10;
        }
        servo09.write(ROT);
      }
      //ドライバ制御ここまで
      break;
  }
}

0 件のコメント: