2026/03/29(Sun) [長年日記] この日を編集
[mini] ステッパーモーターをMaxxEcuのPWMで駆動する
これまで、ミニのアイドリングをArduinoで水温をチェックしてステッパーモーターを制御する方法でやっていたのだけど、なんか安定しない。なのでAIに協力してもらい、MaxxECUのIdle PWM solenoid出力を使って制御する方法に変更した。PWMは、50Hzの初期状態のまま使用。それほど更新頻度は高くないが、アイドリング制御には問題ないというAIの判断。
以下は、PWMの信号をブロッキングで取得する方法を使っている。非ブロッキングの方法でもやってみたのだが、ノイズの影響なのか安定しないのでそちらはやめてしまった。
これに加え、MaxxxECU側でIdle controlをとりあえずOpen loopで設定した。まだ温度域による微調整が必要そうだが、いい感じの手応え。
#include#include #include #include #include #include "MCP_ADC.h" #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 32 #define OLED_RESET -1 #define SCREEN_ADDRESS 0x3C Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); float Vref = 3.82; int THERM_B = 3395; int THERM_R0 = 9290; float THERM_T0 = 273.15 + 27.0; const int DIR = 8; const int STEP = 9; MCP3004 mcp1; const int inputPin = 7; AccelStepper stepper(AccelStepper::DRIVER, STEP, DIR); // 状態管理 int stepperPos = 0; int pwm_target = 0; // 温度取得 float getTemperature() { uint16_t val = mcp1.read(0); float volts0 = val * Vref / 1023; float rr1 = 9320 / volts0 - 2000; float t = 1.0 / (log(rr1 / (float)THERM_R0) / (float)THERM_B + 1.0 / (float)THERM_T0); return t - 273.15; } void move_stepper_pwm() { unsigned long pw = pulseIn(inputPin, LOW, 40000); // μs //Serial.println(pw); static float filt_pw = 10000; // 初期値(適当でOK) if (pw > 1000 && pw < 30000) { float alpha = 0.2; filt_pw = filt_pw * (1 - alpha) + pw * alpha; } // PWM → ステップ位置に変換 // 例:1000~2000us → 0~50ステップ pwm_target = map((int)filt_pw, 0, 20000, 5, 85); pwm_target = constrain(pwm_target, 5, 85); // ステッパー移動 if (stepper.distanceToGo() == 0 && pwm_target != stepperPos) { pwm_target = pwm_target - 4; // 補正 stepper.moveTo(pwm_target); stepperPos = pwm_target; } } void setup() { Wire.begin(); Wire.setClock(100000); Serial.begin(9600); if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { for(;;); } display.clearDisplay(); display.setTextSize(2); display.setTextColor(SSD1306_WHITE); display.setCursor(0,0); display.println("INIT OK"); display.display(); delay(10); SPI.begin(); mcp1.begin(10); // AccelStepper 設定 stepper.setMaxSpeed(2000); stepper.setAcceleration(3000); // 初期位置調整 stepper.moveTo(-85); while (stepper.distanceToGo() != 0) { stepper.run(); } stepperPos = -85; pinMode(inputPin, INPUT_PULLUP); move_stepper_pwm(); disp_header(); } unsigned long lastUpdate = 0; void loop() { // --- AccelStepper の run() は常に高速で回す --- stepper.run(); unsigned long now = millis(); if (now - lastUpdate >= 600) { lastUpdate = now; move_stepper_pwm(); float temp = getTemperature(); update_temp_and_level(temp, stepperPos); } } void disp_header() { display.clearDisplay(); display.setTextSize(1); display.setCursor(0,0); display.println("Water Temp"); display.setTextSize(1); display.setCursor(67,10); display.cp437(true); display.write(167); display.print("C"); display.setCursor(77,0); display.println("Accel Lv"); display.display(); } void update_temp_and_level(float temp, int lv){ int i_temp = (int)temp; float f_dot = temp - i_temp; int i_dot = (int)(f_dot * 10); display.setTextSize(3); char buf[10], buf2[10]; sprintf(buf, "%03d", i_temp); sprintf(buf2, ".%d", i_dot); display.fillRect(0, 10, 72, 24, SSD1306_BLACK); display.setCursor(0,10); display.setTextSize(3); display.print(buf); // 値表示部分だけ消す display.fillRect(48, 16, 40, 16, SSD1306_BLACK); display.setCursor(48,16); display.setTextSize(2); display.print(buf2); // 値表示部分だけ消す display.fillRect(90, 10, 38, 22, SSD1306_BLACK); // 再描画 display.setCursor(90, 10); display.setTextSize(3); display.println(lv); display.display(); }
2026/03/22(Sun) [長年日記] この日を編集
[ND] 夏タイヤへ交換
暫く先まで氷点下になることもないようなので、夏タイヤへ交換した。ジャッキアップしたついでに、ブレーキフルードの交換も行っておいた。
空気圧を調整するためにコンプレッサーを駆動したので、ついでにへたりきっていた耕運機と草刈り機のタイヤへもエアーを入れておいた。草刈り機は14.0kmらしいのでその圧で、耕運機は不明だったので同じにした。
走行距離:174,999 km
2026/03/21(Sat) [長年日記] この日を編集
[mini] ライトおわん交換
ライトを固定するビスの土台のプラスチックがだめになって空回りするようになってしまったので、おわんごと交換します。
元々は96年式以前用の鉄のおわんがついていたのですが、97年式移行用のプラスチックのものに交換です。なんかパーツが足らないような??
おわんはボディにリベットで固定されているので、8mmのドリルで揉んでリベットを壊して外しました。
そして、新しいおわんをこのリベットで取り付けました。かれこれ10年前に何かのために買っておいたものですが、何だったのかは不明。やっと日の目を見たわけ。実は、今回これ用に同じ太さで短いものを買っておいたのですが、結局のところ長さが足りず、画像のものが適切だったという…。
おわんを取り付けたところ。リレーを取り付けたときに配線が汚くなっていたのを綺麗にしたいというのもあって、ギボシ端子などすべて取り去って配線をやり直します。
青白がハイビーム、青赤がロービーム、赤がポジションで、黒がアースでした。その他に、リレー用のバッ直が引いてあります。
配線をやり直して、きれいになりました。でも、新しいおわんの方がちょっと狭いのでリレーが収まるか?
リレーをライトの裏に収めて、ライトを固定しました。うまくリレーも入った。ライトの固定は、ライトリム側に行います。これが96以前用と異なってパーツが足りないんではと思った点。ライトリムは、光軸調整用のボルト2本と固定用のビス1本で行う仕組み。固定はやはりプラスチックにタッピングビスなので、何度も雑にやったら駄目になる…。
ライトリングをはめてビスで止めたら完成。このビスもプラスチックにタッピングビス。ここはなんとかしてほしいところ。
2026/03/06(Fri) [長年日記] この日を編集
[mini] arduino復活
arduino壊れたので代替機をポチった。USB-C対応のnano互換機。それにプログラムを書いて…あれ?ログが出ない。ハズレを引いたかな、と思って別のに書いて…やっぱりログが出ない。おかしいなぁと思ってバージョンの古い動いていたものに変えたらログが出た。問題ないようだ。
これって新しい方のプログラムがバグで動かないのか?ということになって、壊れたと思ったnano everyに古いものを書き込んだら、問題なく動くじゃん。なんてこった。
バグはどこかと思って探って見たがよくわからない。もう一度書き込んだりしていると、動くときと動かない時があることが判明。仕方ないのでGeminiに投げてみたら、ステッパーモーター制御とLCD制御に時間がかかるので、動かなことがあるとのこと。改善案を示してくれた。更に、LCDに文字を出すところで、writeコマンドを使っていたのだが、これだとコマンドを送ることもできるようでバグの原因にもなっていた。代わりに、printを使ってこれも直った。その他、ステッパーモーター制御のバグが含まれていたので、これは自分で修正。AIを信じちゃいけないところとAIに頼ったほうがいいところとあるなぁ。
そんな訳で埋め込みLCDとステッパーモーター制御が無事復活したのだった。
2026/03/01(Sun) [長年日記] この日を編集
[mini] ドアチェックリンク交換
ミニのドアが半分開いた状態で止まらないので、チェックリンクがダメなのかなぁと思って、購入。交換してみた。今回買ったのは、2種類あるうちのちょっと高いやつ。
クレビスピン?を抜いて、ドアを締めたら外れた。逆の手順で、チェックリンクをドアが半分だけ開いた状態でつけて、ピンを挿入して完成。
あれ?ドアが半分空いた状態では止まらないじゃん。これって正常だったのか…。
[mini] ArduinoのLCDをメータ埋め込みにした
今度は、メーターパネルを取り外してメーター自体も取り外し。
写真を全然撮っていなかったのだが、メーターの電球をLEDタイプにすべて交換した。
そして、LCDをこの前やっていたメーター埋め込みにしたものをやっと取り付けた。LCDとArduinoの間のケーブルは、1mくらいの長さにした。
しかしこれが悪さをしたのかどうか不明なのだが、Arduinoが半死になってしまった。PCからは見えるのだが、ステッパーモーターもLEDも制御できない。しかも、開発機もだめになったし、本番機もだめになってしまったのだ。
本番機は、調子よく動いてると思って、プログラムを書き換えた後で死んでしまったようだ。電源のノイズを拾ったのかなぁ?















