長かったなぁ。あれこれ寄り道した気がする。その挙句に逃亡なんかしてやっと終わりそうな予感がする。あれから5年くらいか、遠い目。
仕様もハードウェアもほぼ固まったし行けそうな感じがする。
マイコンを下手に多機能モデルにせずに8ピンPIC(12F1822)に拘ったところで応用力が広がったような気もします。早くサブディスププレイ化も進めたいし基板化して3Dモデルと合体させれば完成・・・だ。
新プロジェクト12F1822+VID6608+X27.168
バイク用ステッピングタコメータの作成
マイコン 12F1822
ステッピングモータ X27.168
モータドライバー VID6608
RA0~RA2:X27.168専用のVID6608制御※(CLK / DIR / RESET)
RA5:回転数入力
RA3:設定変更用ボタン(MODE-SW)
RA4:表示LED
1クランク1パルスとして設計
漏れ漏れインタフェースV2から回転信号を入力(基板同梱)
※VID6608はX27.168専用で使われることが多い、2ch仕様の古いモータドライバー
MODEスイッチの機能
29K 52Y 4UO の各仕様のタコメータとして切替可能
シフトアップインジケータ(7,000~12,000rpm/500prmステップで任意設定)
デフォルトの初期設定52Y 10,500RPM
現在の問題点は電源消失後の再起動時にVID6608のリセット制御がスカる時があり、位置決めであるオープニングセレモニー動作をすっ飛ばす時がある。再現性がないので困ってる。
VID6608のデーターシート通りに作ってるにもかかわらず今のところ謎。
いつも通りのバグである可能性が非常に高い。
もう一つは決め打ち項目でずっと悩んでいるのは入力信号のことである。
入力処理基準の1クランク1パルスは変わらないが皆が知ってる通りRZ系は1クランク2パルスだ
今は漏れ漏れインタフェースのHW側で処理しているが12F1822のマイコン処理でも可能。
ず~~~と、この部分の仕様がコロコロ変わっていて当方では決めきれない。
あとで総監督と助監督にでも聞いてみよう。
現在の回路図 (非接触型の漏れ漏れインターフェースのみ省略)

設定モードのソース、相変わらずバグ付きがお好きです
プッシュボタンのチャタリングを恐れてくどい様に強固にしたが結局オーソドックスな入力スイッチモデルを採用。
#define HOLD_TIME_MS 1500 // 長押しの判定時間 (1.5秒)
#define SHORT_TIME_MS 50 // 短押しの判定時間 (チャタリング防止)
void check_settings(void) {
uint8_t phase = 1;
uint8_t temp_spec = g_tach_spec;
uint16_t temp_ind_rpm = g_ind_rpm;
// ---------------------------------------------------
// フェーズ1:仕様の初期位置へ針を移動(1000rpm)52Y
// ---------------------------------------------------
update_phase1_needle(temp_spec);
while (phase <= 2) {
uint16_t press_time = 0;
// ボタンが押されるのを待機
while (BTN_SET == 1) {
__delay_ms(10); // 割り込みで針は勝手に動くので待つだけでOK
}
// ボタンが押されている時間をカウント
while (BTN_SET == 0) {
__delay_ms(10);
press_time += 10;
if (press_time >= HOLD_TIME_MS) {
break; // 長押し時間に到達したらループを抜ける
}
}
// --- 長押し判定 ---
if (press_time >= HOLD_TIME_MS) {
if (phase == 1) {
// フェーズ1 決定処理
g_tach_spec = temp_spec; // 仕様を本決定
// LEDを2回点滅して合図
LED_STATUS = 1; __delay_ms(200); LED_STATUS = 0; __delay_ms(200);
LED_STATUS = 1; __delay_ms(200); LED_STATUS = 0; __delay_ms(200);
phase = 2; // フェーズ2へ移行
// フェーズ2の初期位置(現在のインジケータ設定値)へ移動
// ここでは確定した仕様を使って正しいステップ数を計算する
g_motor_target_step = rpm_to_step((uint8_t)(temp_ind_rpm / 100));
}
else if (phase == 2) {
// フェーズ2 決定処理
g_ind_rpm = temp_ind_rpm;
// EEPROMへ保存
write_eeprom(0x00, g_tach_spec);
write_eeprom(0x01, (uint8_t)(g_ind_rpm >> 8));
write_eeprom(0x02, (uint8_t)(g_ind_rpm & 0xFF));
// LEDを3回点滅して合図
for(uint8_t i=0; i<3; i++){
LED_STATUS = 1; __delay_ms(200); LED_STATUS = 0; __delay_ms(200);
}
phase = 3; // 設定終了
}
// ボタンが離されるまで待機(連続入力を防ぐ)
while (BTN_SET == 0) {
__delay_ms(10);
}
}
// --- 短押し判定 ---
else if (press_time >= SHORT_TIME_MS) {
if (phase == 1) {
// 仕様切り替え (52Y -> 29K -> 4UO -> 52Y)
temp_spec++;
if (temp_spec > SPEC_4UO) temp_spec = SPEC_52Y;
update_phase1_needle(temp_spec);
}
else if (phase == 2) {
// 回転数切り替え (+500rpm)
temp_ind_rpm += 500;
if (temp_ind_rpm > 12000) {
temp_ind_rpm = 7000; // 12000を超えたら7000に戻る
}
g_motor_target_step = rpm_to_step((uint8_t)(temp_ind_rpm / 100));
}
// ボタンが離されるまで待機
while (BTN_SET == 0) {
__delay_ms(10);
}
}
}
// 設定完了後、針を0rpmに戻して通常動作へ
g_motor_target_step = 0;
}
// ---------------------------------------------------
// フェーズ1用の針位置移動ヘルパー関数
// ---------------------------------------------------
void update_phase1_needle(uint8_t spec) {
uint8_t backup_spec = g_tach_spec;
g_tach_spec = spec; // 一時的に計算用ロジックを切り替える
if (spec == SPEC_52Y) {
g_motor_target_step = rpm_to_step(10); // 1000 rpm
} else if (spec == SPEC_29K) {
g_motor_target_step = rpm_to_step(50); // 5000 rpm
} else if (spec == SPEC_4UO) {
g_motor_target_step = rpm_to_step(95); // 9500 rpm
}
g_tach_spec = backup_spec; // 元の設定に戻す
}この進捗はプログラミングが楽しくてしょうがない、当方の気まぐれ的一時的な盛り上がりだろうから、個人的要望として年度内の完成を目指している。まあ、今まで通り気長に待っていてください。

コメント