まずは、LEDだけを1秒ごと交互点滅させるプログラム
起動後の時間を監視し10秒ごとにフェーズを0..と遷移し、フェーズ1,2の場合のみ交互点滅する。
久しぶりにマジで書いてみた。
=========================
/*
踏切模型の並行動作テスト
LEDを1秒おきに左右交互に点滅させる
getPhase()関数内で経過時間から現在のフェーズを0..2値で取得し、
フェーズに従ってLEDLEDを交互点灯させる
フェーズ2を超えるとフェーズ0になり、交互点灯動作は終了する
2023/9/7
*/
#define wl_R 4 // 警告灯 右
#define wl_L 5 // 警告灯 左
#define ss_R 12 // 列車センサー 右
#define servoPin 9 // サーボpin
const int intervalLED = 1000; // LED点滅間隔
#include "Servo.h"
Servo servo; // MyServo生成
unsigned long startT = millis(); // 開始時間記録
int phase = 0; // 現在のフェーズを与える 0:待機 1:LED点滅期 2:LED点灯期
//unsigned long ms = 0; // SW押下からの時間 MS
bool warnLedOn = false; // 警告灯点滅期間フラグ
bool servoDwOn = false; // サーボ下降フラグ
int wlCnt = 0; // 警告LEDが点灯した回数
// SW押されるの待つ
void waitSwitch(){
while (digitalRead(ss_R) == HIGH){ //スイッチが押されるまで待つ
digitalWrite(wl_R, HIGH);
delay(200);
digitalWrite(wl_R, LOW);
delay(200);
}
}
void setup() {
pinMode(wl_R,OUTPUT);
pinMode(wl_L,OUTPUT);
pinMode(ss_R,INPUT_PULLUP); // スイッチをPullUPで使用
servo.attach(servoPin);
servo.write(90); // バー直立
//waitSwitch(); // SW押されるの待つ
digitalWrite(wl_R, LOW);
digitalWrite(wl_L, LOW);
Serial.begin(9600);
Serial.print('start at ');
Serial.println(startT);
}
void getPhase(){ // 現在のフェーズを判定する
unsigned long pastT = millis() - startT; // 開始からの時刻を得る
if (pastT <= 10*1000){
phase = 0;
warnLedOn = false;
servoDwOn = false;
return;
}
if (pastT <= 20*1000){
phase = 1;
warnLedOn = true;
servoDwOn = false;
return;
}
if (pastT <= 30*1000){
phase = 2;
warnLedOn = true;
servoDwOn = true;
return;
}
phase = 0;
warnLedOn = false;
servoDwOn = false;
}
void dbg(){
Serial.print(millis());
Serial.print(" Phase:");
Serial.print(phase);
Serial.print(" LEd:");
Serial.print(warnLedOn);
Serial.print(" Servo:");
Serial.print(servoDwOn);
Serial.print(" wlCnt:");
Serial.print(wlCnt);
Serial.println("");
}
// warnLedOn=trueの間 警告LEDを交互点滅させる
void do_LED(){
static unsigned long lastT = 0; // 最後の点滅交代時刻をstaticで記録
unsigned long nowT = millis(); // 現在時刻取得
if (!warnLedOn){ // warnLedOn=True時のみLEDを点灯させる
digitalWrite(wl_R, LOW);
digitalWrite(wl_L, LOW);
wlCnt = 0; // 消灯時は点滅回数を0にしておかないと交互表示ができない
return;
}
if (nowT - lastT >= intervalLED){ // 1秒ごとに値を反転させる
lastT = nowT;
digitalWrite(wl_R, ! digitalRead(wl_R));
digitalWrite(wl_L, ! digitalRead(wl_L));
}
wlCnt = wlCnt + 1;
}
// 点滅開始時に交互表示状態を作っておく
void start_LED(){
digitalWrite(wl_R, HIGH);
digitalWrite(wl_L, LOW);
wlCnt = 1;
}
void loop() {
getPhase();
if ((wlCnt == 0) && (phase == 1)){
Serial.println("start_LED()");
start_LED(); // 点滅開始時に一回だけ交互表示状態を作っておく
}
dbg();
do_LED();
delay(1000);
}