ガルパン 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 件のコメント:
コメントを投稿