2017年9月7日木曜日

リレーで100V制御(その3)

構成図





●動作概要
・90cm以内に物体を検知したらライトを点灯
・検知されなくなったら5秒後に消灯


●プログラムコード
/* HC-SR04モジュール設定 */
#define SONIC_TRIG 7
#define SONIC_ECHO 6

/* リレースイッチピン */
#define SWITCH_PIN 4

/* 消灯用タイマー */
unsigned long gElapsedTime;

/* 照明ステータス */
int gLightStatus = LOW;

/* 消灯までの時間 */
int gLightOffWaitSec = 5;

/* 検出境界値(cm) */
int gBorder = 20;

/*
 * 初期処理:超音波距離測定
 */
void initUltraSonic() {
  pinMode(SONIC_TRIG, OUTPUT);
  pinMode(SONIC_ECHO, INPUT);
}

/*
 * 超音波距離測定
 * 音速331.5 + 0.6 * 温度:1cm当たりの音波の時間(マイクロ秒)
 *  343.5:29.11@室温20度
 *         30.40@調整後
 * 測定可能距離:2cm〜400cm
 * 失敗時:0
 */
double measureUltraSonic() {

  // Trigに10マイクロ秒 HIGH出力
  digitalWrite(SONIC_TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(SONIC_TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(SONIC_TRIG, LOW);

  // EchoがHIGHからLOWになる時間(マイクロ秒)を取得
  // TIMEOUT  : 測定距離 × 往復 × 1cm当たりの音波の時間(マイクロ秒) + Trigの時間
  //  24720μ : 400cm * 2 * 30.4 + 400
  double duration = pulseIn(SONIC_ECHO, HIGH, 24720);

  // 往復時間と音速から距離算出
  // 距離 = 時間 / 2 * 30.4
  return duration / 60.8;
}

/* 
 * 距離測定
 */
double measureRange() {
  
  double wk_range = 0, wk;
  int count = 0;
  
  for(int i = 0; i < 10; i++) {
    if (i > 0) delay(60); // MaxRepeat 60ms
    wk = measureUltraSonic();
    if (wk) {
      wk_range += wk;
      count++;
      if (count > 1) break;
    }
  }
  if (count == 0) {
    return 0;
  }
  return wk_range / count;
}

/* 
 *  範囲内に物体があるか判定する
 *  -1:測定失敗
 *   0:物体なし
 *   1:物体あり
 */
int checkDetect() {
  double wk_range = measureRange();
  if (!wk_range) {
    // 測定失敗
    Serial.println(F(" 測定失敗"));
    return -1;
  }

  Serial.print(wk_range);
  Serial.println(F(" cm"));
  if (wk_range > gBorder) {
    // 範囲外
    return 0;
  } else {
    // 範囲内あり
    return 1;
  }
}

/*
 * ステータス更新
 * 点灯、消灯の制御を行う
 */
void updateStatus(int nowStatus) {

  if (nowStatus == HIGH) {
    // HIGHの場合、タイマー更新
    gElapsedTime = millis();
  } else {
    // LOWの場合、消灯までの時間が経過するまで待つ
    if (millis() - gElapsedTime < gLightOffWaitSec * 1000) {
      return;
    }
  }
  if (gLightStatus == nowStatus) {
    return;
  } else {
    gLightStatus = nowStatus;
  }

  digitalWrite(SWITCH_PIN, gLightStatus);
  Serial.print("LIGHT --> ");
  Serial.println(gLightStatus ? "ON" : "OFF");
}

// =======================================================
// メイン処理
// =======================================================
void setup() {

  // リレースイッチピン設定
  pinMode(SWITCH_PIN, OUTPUT);
  
  // 距離測定初期化
  initUltraSonic();

  // タイマー初期化
  gElapsedTime = millis();
  
  Serial.begin(115200);
}

void loop() {

  int checkStatus = LOW;
  switch(checkDetect()) {
    case 1: // 検知あり
      checkStatus = HIGH;
      break;
    case 0: // 検知なし
      checkStatus = LOW;
      break;
    default: // 測定失敗
      delay(100);
      return;
  }
  // ステータス更新
  updateStatus(checkStatus);

  delay(100);

}

●今後の予定
・消灯までの時間と検出の境界値を実行時に変えれるようにする
・省電力化

0 件のコメント:

コメントを投稿