waiasu’s diary

バーグマン200のカスタムをメインに。

ウインカーポジション ディミングターン統合

希望するようなパーツが無いので別々に作っていましたが一つにまとめました。シールドっぽい感じでの自作なので後から照度センサーによるポジション輝度の変更とか機能追加できます。現状「電源」「ウインカー出力」「オーディオ出力+ウインカー入力」の3階建てです。

ウインカーリレーとしては問題無かったのですが、せっかくのディミングなのにウインカーをキャンセルしたり左右に切れなく入れ替えたりすると途中で終わってしまったり、途中から始まったりと美しくない事が気になった為。

ポジションもドライブ回路の都合で減光下限まで使い切れていない事やオンまでの時間がウインカー周期以上に設定できないとか、ウインカーが点滅する前に切ることが出来ないのが気になって。

別々での対策でも問題点はクリアできるのですがシンプルにまとめました。取り付けもウインカーリレーを抜いて直結してスイッチからウインカーへ向かうラインをカットして割り込むだけの配線に。調整もユニットにアクセスするならUSBで焼くのも手間は変わらないのでボリューム関係とA/D変換に関するスケッチは削除。気になってどうせシリアルモニタで点灯回数等も数字で確認するんで。

そもそも言われなければ分からないレベルですし言われても目視で確認出来ないレベルの話かもしれません。


キーオンでアクションがあり、しっかり減光出来て、オンスタートで、ディミングは必ず先頭から始まり、途中で切り替えてもキレイに繋がって、鼓動っぽいオーディオ出力もでき、各タイミングや時間に減光ピッチもスケッチ書き換えで即対応な仕様となりました。

とりあえず満足ですが電源をウインカーリレーを抜いてショートした部分からとっているのでどうするか迷っています。配線がスッキリしたので出先でも応急処置可能で問題ないのですがシグナルのヒューズに絡むのが嫌です。かと言っておもちゃの後付ACCと一緒にするのもどうかと…。

int WIN_IL=14; //ウインカー入力(L)
int WIN_IR=15; //ウインカー入力(R)
int WIN_OL=10; //ウインカー出力(L)
int WIN_OR=9;  //ウインカー出力(R)
int AUD_OX=6;  //オーディオ出力

int STP=5000;  //ステップ時間

int CHA=100;   //入力確認時間(ms)
int NUM=75;    //点滅回数(毎分)
int ONT=200;   //オンキープ時間(ms)
int OFT=200;   //オフキープ時間(ms)

/////オープニング

void setup() {
  pinMode(WIN_IL,INPUT);
  pinMode(WIN_IR,INPUT);
  pinMode(WIN_OL,OUTPUT);
  pinMode(WIN_OR,OUTPUT);
  pinMode(AUD_OX,OUTPUT);
  Serial.begin(9600);

  unsigned long TIM=millis();

  for (int C=0; C<=500; C++) { //起動待ち(500ms)
    delay(1);
    if (input(WIN_IL) || input(WIN_IR)) { //入力確認
      winker();
      goto setup_end;
    }
  }

  analogWrite(WIN_OL,1); //点灯時ゆらぎ対策
  analogWrite(WIN_OR,1);
  digitalWrite(WIN_OL,LOW);
  digitalWrite(WIN_OR,LOW);

  for (int V=0; V<=255; V++) { //ゆっくり点灯
    analogWrite(WIN_OL,V);
    analogWrite(WIN_OR,V);
    delayMicroseconds(STP);
    if (input(WIN_IL) || input(WIN_IR)) { //入力確認
      winker();
      goto setup_end;
    }
  }

  for (int C=0; C<=80000/STP; C++) { //消灯(80ms)
    digitalWrite(WIN_OL,LOW);
    digitalWrite(WIN_OR,LOW);
    delayMicroseconds(STP);
    if (input(WIN_IL) || input(WIN_IR)) { //入力確認
      winker();
      goto setup_end;
    }
  }

  for (int C=0; C<=80000/STP; C++) { //点灯(80ms)
    digitalWrite(WIN_OL,HIGH);
    digitalWrite(WIN_OR,HIGH);
    delayMicroseconds(STP);
    if (input(WIN_IL) || input(WIN_IR)) { //入力確認
      winker();
      goto setup_end;
    }
  }

  for (int C=0; C<=80000/STP; C++) { //消灯(80ms)
    digitalWrite(WIN_OL,LOW);
    digitalWrite(WIN_OR,LOW);
    delayMicroseconds(STP);
    if (input(WIN_IL) || input(WIN_IR)) { //入力確認
      winker();
      goto setup_end;
    }
  }

  for (int V=255; V>=0; V--) { //ゆっくり消灯
    analogWrite(WIN_OL,V);
    analogWrite(WIN_OR,V);
    delayMicroseconds(STP);
    if (input(WIN_IL) || input(WIN_IR)) { //入力確認
      winker();
      goto setup_end;
    }
  }

  Serial.println((millis()-TIM)*0.001);

  for (int C=0; C<=1000; C++) { //始動待ち(1000ms)
    delay(1);
    if (input(WIN_IL) || input(WIN_IR)) { //入力確認
      winker();
      goto setup_end;
    }
  }
  setup_end:;
}

///// ポジション点灯

void loop() {
  for (int C=0; C<=200; C++) { //点灯待ち(200ms)
    delay(1);
    if (input(WIN_IL) || input(WIN_IR)) { //入力確認
      winker();
      goto loop_end;
    }
  }
 
  analogWrite(WIN_OL,1); //点灯時ゆらぎ対策
  analogWrite(WIN_OR,1);
  digitalWrite(WIN_OL,LOW);
  digitalWrite(WIN_OR,LOW);

  for (int V=0; V<=20; V++) { //ゆっくり点灯(20/255)
    analogWrite(WIN_OL,V);
    analogWrite(WIN_OR,V);
    delayMicroseconds(STP);
    if (input(WIN_IL) || input(WIN_IR)) { //入力確認
      winker();
      goto loop_end;
    }
  }

  while(true) {  //入力待ち(ポジション点灯中)
    delay(1);
    if (input(WIN_IL) || input(WIN_IR)) { //入力確認
      winker();
      goto loop_end;
    }
  }
  loop_end:;
}

///// 入力確認

int input(int PIN_NO) {
  int ADD=0;

  if (PIN_NO!=99) { //オン安定待ち
    while (digitalRead(PIN_NO)) {
      if(ADD>CHA) { break; }
      ADD++;
      delay(1);
    }
  } else { //オフ安定待ち
    while (!digitalRead(14) && !digitalRead(15)) {
      if(ADD>CHA) { break; }
      ADD++;
      delay(1);
    }    
  }
  if(ADD>CHA) { return true;
  } else { return false; }
}

///// ディミングウインカー

void winker() {
  float FRQ=60.0/NUM*1000.0;
  float GRT=((FRQ-ONT-OFT)*1000.0/256.0)*0.96;
  float AOP=FRQ/3.0; //オーディオオフポイント
  float GRP=3.0;     //1.0-5.0 減光ピッチ
  float SGR=GRT/GRP; 
  float LGR=GRT*GRP;
  float GRH=255-(GRP*42.5);

  digitalWrite(WIN_OL,LOW); //ポジションオフ
  digitalWrite(WIN_OR,LOW);

  while(true) {
    unsigned long TIM=millis();
    int LOF=0;
    int LOR=0;
    int LOA=0;
    if (digitalRead(WIN_IL)) { LOF=1; }
    if (digitalRead(WIN_IR)) { LOR=1; }

    if (LOF) { digitalWrite(WIN_OL,HIGH); }
    if (LOR) { digitalWrite(WIN_OR,HIGH); }
    digitalWrite(AUD_OX,HIGH); //オーディオオン
   
    delay(ONT); //オンキープ

    for (int V=255; V>=0; V--) { //ゆっくり消灯
      if (LOF) { analogWrite(WIN_OL,V); }
      if (LOR) { analogWrite(WIN_OR,V); }

      if (TIM+AOP<millis() && LOA==0) { LOA=1;
        digitalWrite(AUD_OX,LOW); //オーディオオフ
//        Serial.println(60000.0/(millis()-TIM));
      }

      if (V>GRH){ delayMicroseconds(SGR);
      } else if (V>42){ delayMicroseconds(GRT);
      } else{ delayMicroseconds(LGR); }
    }

    for (int C=0; C<=OFT; C++) { //オフキープ
      delayMicroseconds(1000);
      if (!digitalRead(WIN_IL) && !digitalRead(WIN_IR)) { //両側オフ時のみ
        if (input(99)) { goto winker_end; } //反転入力確認
      }
    }
    Serial.println(60000.0/(millis()-TIM));
  }
  winker_end:;
}

オーバーフローの処理はしていないので各数値は常識的な範囲内で。片側入力オフ時の確認が甘いような気もしますが問題があれば対策します。