倅と一緒にArduino_ATCプラレール_02(仮スケッチ)
目次
本件は、以前書かせていただきました「倅と一緒にArduino_ATCプラレール_01(前準備)」の続きです。
なにやらやりたいことを聞き出して、メモしたのですが、あまり、ごちゃごちゃ書いてもこのページが読み辛くなるだけですので(下記をご覧になるとお分かりになると思いますが手遅れです。すみません)抜粋した機能メモだけ、書きます。
倅には、頭の体操をしてもらうために、質問を受け付けつつ自作してもらい、成功体験を得てもらいましょう。
詰まったとこでは、適切なタイミングでヘルプします。つまらなくなっちゃったら、逆効果ですしね。
Arduino Nanoの D6,D7 にモーター制御を担当させて、D9を接近センサーかのらデータ入力に使うと仮定して作ってゆきます。
各々の端子(D6,D7,D9)がすでに何かに使われてているか、知識がなくてわからないので、探りながらやってゆきます。
端子を変えられるように スケッチ上では前半に#define で定義して後で変えやすくしようと思います。
とりあえず、下記機能を実現します。(めもめも)
機能要件メモ
こういうのを書くのは職業病ですね。実は細かいテキストも書いていたのですが(職業病で「試験項目作れないと正しいものができてるかわからなくなる」なんて思いながら)ここでは書きません。評価基準を「楽しかったか?」に絞ることにします。
が、まぁ大体の機能メモは必要ですので、一応書きます(理屈が多くてすみません)。
要件1「前方、障害物走検出を契機とした停止」 機能概要(ア)、「停止」 (1)”急停止”:走行電源断による急停止実施での”停止状態への遷移” 緩停止は実現を見送りとする。緩停止は衝突につながりやすい旨伝達したこともあり 合意形成しやすかったことが理由に含まれます(誘導しています悪い業者です)。 要件2、停止後の自動運転再開 機能概要(ア)、障害物が検出されていない場合には走行状態に自動遷移する。 機能概要(イ)、「走行」 (1)”(緩)加速”:供給電圧順次制御による加速を経由しての指定電圧により期待される走行速度への状態遷移制御 ”(緩)加速”をプラレールで実現したら格好いいからというクライアント(倅殿)の強い要望の為。 (インバーターチックな動きをさせたい)
接続は、前回書かせていただきましたこのページ(接続図)を参照ください。
機能に関して
部品1:接近センサーモジュール[KKHMF LM393 IR赤外線障害物回避センサモジュール]
・VCC(電源5v)/GND(マイナス極)/OUT(信号線) それぞれをArduinoに接続します。ここでは、D7とOUTを接続したと仮定します。
setup()では
void setup()
{
pinMode( 7 , INPUT ); // 接近センサポート使用宣言
}
loop()では
void loop()
{
// 接近状態検出 LOW = 非接近 , HIGH = 接近
l_tmp_pin = digitalRead(7); // 接近センサーからの情報を取得
if(l_tmp_pin == LOW)
{ // 接近検知状態
// 停止措置等の処理をここに書く
} else { // 接近未検出状態
// 前進等の処理をここに書く
}
}
部品2:DCモーター制御のモータードライブモジュール[L9110S Hブリッジ ステッパ モータドライブ モジュール デュアル DC ステップ モータ ドライバ コントローラボード]
setup()では
void setup()
{
pinMode( 8 , OUTPUT ); // IAポート使用宣言
pinMode( 9 , OUTPUT ); // IBポート使用宣言
digitalWrite( 8 , LOW ); // StopOperation
digitalWrite( 9 , LOW ); // StopOperation
}
loop()では
void loop()
{
digitalWrite(8, LOW); // PWM speed = slow
analogWrite(9, 200); // 2個目の引数は 255-加減値、この例では200固定
}
スケッチ
とりあえず、動作確認していませんが、こんな形で進めようとおもいます。
/*
[Pin3,4に対してのOperation]
IA IB
L L Off
H L Forward
L H Reverse
H H Off
つまり
3[LOW] ,4[LOW] OFF
3[HIGH] ,4[LOW] 正転
3[LOW] ,4[HIGH] 逆転
3[HIGH] ,4[HIGH] OFF
analogWrite( XD_MTSW_IB, 255-xa_cur_speed ); //前進
*/
#define XD_DEBUG 1
/////////////////////
// Pin配置について宣言
#define XD_MTSW_IA 8 // IAとつなぐPIN番号宣言
#define XD_MTSW_IB 9 // IBとつなぐPIN番号宣言
#define XD_PIN_IR 7 // 赤外線接近センサとつなぐPIN番号宣言
/////////////////////
//進行方向の状態フラグ
#define XF_DIRC_STOP 0 // 直近の進行方向(停止[起動直後扱]:0)
#define XF_DIRC_FORW 1 // 直近の進行方向(前進:1)
#define XF_DIRC_BACK -1 // 直近の進行方向(後退:-1)
//モーターの速度指示(固定値)
#define XD_PWM_SLOW 50 // 動き始め最低速度数値 (Default 50) 下げられるだけ下げるチューニングをする 暫定値
#define XD_PWM_FAST 255 // 最高速度
//#define XD_PWM_FAST 200 // arbitrary fast speed PWM duty cycle
//進行速度の加算値
#define XD_SPEED_STEP 20 //ゆっくり加速時の速度加算にかける秒数
#define XD_SPEED_ADD 4 //ゆっくり加速時の速度加算値
//10秒ぐらいで全速になるとかっこいいかもね = 200/10 = 40
//#define XD_SPEED_ADD ((XD_PWM_FAST-XD_PWM_SLOW)/XD_SPEED_STEP) //ゆっくり加速時の速度加算値
/////////////////////
// グローバル変数
//int xa_stop_alert; // 接近警報状態フラグ
int xa_cur_speed; // 現在の前方進行速度パラメータ
int xa_prev_direc; // 直近の進行方向(0:停止、XF_DIRC_FORW:前進、XF_DIRC_BACK:後退)
unsigned long xa_stopping_timer_cnt; // 停止時に入った時の時間情報 xa_stopping_timer_cnt = millis();
unsigned long xa_adding_timer_cnt; // インバーターっぽい加速実現のための時間情報 xa_adding_timer_cnt = millis();
/////////////////////
// セットグローバル変数
void setup()
{
pinMode( XD_MTSW_IA , OUTPUT ); // IAポート使用宣言
pinMode( XD_MTSW_IB , OUTPUT ); // IBポート使用宣言
digitalWrite( XD_MTSW_IA , LOW ); // StopOperation
digitalWrite( XD_MTSW_IB , LOW ); // StopOperation
pinMode( XD_PIN_IR , INPUT ); // 接近センサポート使用宣言
xa_cur_speed = 0; // 進行指示の速度は0とする(初期化)
xa_prev_direc = XF_DIRC_FORW; // 初期的には進行の指示は出さないで0=ニュートラル(停止中)
xa_stopping_timer_cnt = 0; // 停止状態に至った時間を仮に設定 millis() の値は停止したら入る
xa_adding_timer_cnt = 0; // インバーター加速関連評価タイマー値初期化
}
/////////////////////
// in_speed MAXSpeedを指定してそこまで加速する
void xf_go_ahead(int in_speed)
{
unsigned long l_tmp_mills;
l_tmp_mills = millis(); // 起動からの経過時間=現在時間 を取得
xa_stopping_timer_cnt = 0; // 停止状態に至った時間を仮に設定 millis() の値は停止したら入る
if(xa_prev_direc != XF_DIRC_FORW)
{ //直前までバックしていたか、停止していた
xa_adding_timer_cnt = l_tmp_mills;
xa_cur_speed = 0;
}
xa_prev_direc = XF_DIRC_FORW; // 直近に前進した記録 方向フラグ
if((xa_adding_timer_cnt + 100) < l_tmp_mills) // 100ミリ以上経過していれば再評価
{
xa_adding_timer_cnt = l_tmp_mills; //現在時間をを記録
// 速度上限に抑えつつ、増速
xa_cur_speed += XD_SPEED_ADD;
if(xa_cur_speed >= in_speed)
{
xa_cur_speed = in_speed;
}
}
xf_ff(xa_cur_speed);
}
void xf_ff(int in_cur_speed)
{
digitalWrite(XD_MTSW_IA, LOW); // PWM speed = slow
analogWrite(XD_MTSW_IB, in_cur_speed); // PWM speed = slow
}
/////////////////////
void xf_stop(int in_mode)
{
xa_prev_direc = XF_DIRC_STOP;
xa_adding_timer_cnt = 0;
if(xa_stopping_timer_cnt == 0)
{
xa_stopping_timer_cnt = millis(); // 停止状態に至った時間を設定
}
if(in_mode == 0)
{
// なんとなく止める(走行中緩停止実験実装)
if(xa_cur_speed > 0)
{
xf_ff(xa_cur_speed);
} else {
xa_cur_speed -= (XD_SPEED_ADD + 0); //ぶつかってしまうようであれば ここの加算値を大きくすると間に合くかも
if(xa_cur_speed < 0)
{
xa_cur_speed = 0;
}
digitalWrite( XD_MTSW_IA, LOW );
digitalWrite( XD_MTSW_IB, LOW );
}
}
}
/////////////////////
//メインループ
void loop()
{
int l_tmp_pin; // Pin状態データ受信
unsigned long l_tmp_mills;
l_tmp_mills = millis(); // 起動からの経過時間=現在時間 を取得
// 接近状態検出 LOW = 非接近 , HIGH = 接近
l_tmp_pin = digitalRead(XD_PIN_IR); // 接近センサーからの情報を取得して、警報状態フラグを立てる
if(l_tmp_pin == LOW)
{ // 接近検知状態
//停止措置
xf_stop(0); //緊急停止
} else { // 接近未検出状態
// 前進[速度加算&上限値丸め処理]]
xf_go_ahead(XD_PWM_FAST);
}
}
//おわり
とりあえず今回は、スケッチを仮に書いてみました。