アナログタコメータをつくる(5) スケッチ、そして完成
- カテゴリ: HA36Sアルト
- 投稿日時: 2018/02/12(月) 12:32:07
さて肝心のスケッチです。前に書いた通りライブラリがふたつ必要です。
Arduino-OBD2-Async
https://github.com/vova-ivanyshyn/Arduino-OBD2-Async
Switec X25 library
https://github.com/clearwater/SwitecX25
ライブラリは適当な場所に入れておきます。
スケッチを簡単に説明すると、ステッピングモータの目標値は0.1秒ごとに更新し、モータの動作自体は毎ループごとに行います。文字盤のバックライトは5秒毎に更新。
たぶんもっといいやりかたがあるんでしょうね。シロウトのヘナチョコプログラムだと思って温かい目で見てやってください。何かあったらコメント欄からお知らせいただけると嬉しいです。
#include “SwitecX25.h”
#include “OBD.h”
SwitecX25 motor(315*3, 4, 5, 6, 7);
COBD obd;
// ステップモーター定数
const int PULSE_PER_REV = 315*3; // ステップモータ全体のパルス数
const int MAX_DISP_REV = 8000; // 表示最大回転数(rpm)
const int VIEW_ANGLE = 315; // 使用範囲(deg)
const float CONV = (1 / (float)MAX_DISP_REV) * ((float)VIEW_ANGLE / 315.0) * (float)PULSE_PER_REV;
// 回転数*CONV=ステップ数 : CONV = (1/8000)*(315/315)*315*3 = 0.118125 ->0.12
// エンジン回転数変数
int CurrentRpm = 0; //現在のエンジン回転数
int PreviousRpm = 0; //前回のエンジン回転数
// 更新頻度変数
const int UpdateInterval1 = 100; // 更新間隔(高頻度) ミリ秒
const int UpdateInterval2 = 5000; // 更新間隔(低頻度) ミリ秒
unsigned long PreviousUpdate1 = 0; // 前回の更新時(高頻度)
unsigned long PreviousUpdate2 = 0; // 前回の更新時(低頻度)
// 照明変数
const int LedPin = 9;
const int CdsPin = 0;
int CdsValue = 0;
void setup()
{
for ( int i = 30; i < LedValue(); i += 1 ) {
analogWrite( LedPin, i );
delay( 10 );
}
motor.zero();
delay(200);
motor.setPosition(MAX_DISP_REV * CONV);
motor.updateBlocking();
delay(200);
motor.setPosition(0);
motor.updateBlocking();
delay(200);
obd.begin();
while (!obd.init(PROTO_AUTO));
}
void loop()
{
unsigned long CurrentTime = millis(); // 現在時
motor.update(); //メータを駆動 (1step/Loop)
if (!obd.asyncInProgress()) {
obd.asyncRequest(PID_RPM); //リクエスト送信
}
if (CurrentTime - PreviousUpdate1 >= UpdateInterval1) { //更新(高頻度)
int val = 0;
if (obd.asyncGet(val)) {
CurrentRpm = val % 10000;
if (abs(PreviousRpm - CurrentRpm) > 9){ //前回との差が一桁なら更新しない
motor.setPosition((float)CurrentRpm * (float)CONV); //目標位置設定
PreviousRpm = CurrentRpm;
}
}
PreviousUpdate1 = CurrentTime;
}
if (CurrentTime - PreviousUpdate2 >= UpdateInterval2) { //更新(低頻度)
analogWrite( LedPin, LedValue() );
PreviousUpdate2 = CurrentTime;
}
if (obd.errors >= 2) {
reconnect();
setup();
}
}
void reconnect()
{
for (uint16_t i = 0; !obd.init(PROTO_AUTO); i++) {
delay(3000);
}
}
int LedValue()
{
int result;
CdsValue = analogRead(CdsPin); // だいたい 500-1000
result = -0.3*(float)CdsValue+350;
if (result > 255){
result = 255;
}
return result;
}
さあ一気に仕上げていきますよ。
パテ盛りとペーパー掛けを繰り返して納得できたら洗浄しサーフェイサーを吹いて確認。そこで見つけたアラをまたパテとペーパーで修正。ってなループをしばらく繰り返します。
タミヤ研磨スポンジシートの400番から始めて、クレオスのサフ500番、タミヤのペーパー600番、800番、サフ1000番、ペーパー1000番まで。写真はサフ1000番の直後ですね。
面出しは苦手です。平面ならまだしも円筒は難しい。だんだん嫌になってきたのでほどほどのところでやめておきます。
ハンドピースで塗装。クレオスのラッカー黒。だいたいいつもは半ツヤ程度でごまかすんですが今回はツヤ有りブラックで。
ツヤ有り塗装はエア圧強め塗料多めで近めから吹くと良いです。希釈は通常通り薄めで、数回重ねたら最後は垂れる寸前くらいまで吹くとしっとりしたツヤが得られます。
って初めてやったので偉そうなことは言えませんハイwww
持ち手はトイレットペーパーの芯です。このくらいの大きさの対象物のときはこれが最高に使いやすいです。
この後塗膜保護と見栄えのためクリアを重ねて水研ぎしピアノブラック調の予定でしたが、面倒くさくなったのでこのままで。
文字盤はとあるプロ向けの 2D プリンタを使用。ボルティーのタコメータ盤面をつくったときに使ったのと同系統のプリンタです。家電量販店には売ってません。紫外線硬化タイプのインクを使います。
0.3mm プラバンにダイレクト印刷しました。濃度を数パターン試して、最終的には 400% としました。
写真だと表面がザラザラな感じですが実物では気になりません。前はつや消しコートしましたが、直射日光を浴びることはまずないはずなのでこれもやめ。
部品が揃いました。組み立てです。基本的には全てはめ込みです。
黒い本体部分、表面がうねっているのがバレバレですね。あらためてプラモデルのひとは凄いなと思います。
メータ正面のガラス押さえ用の輪っかは、これまたクレオスラッカーのシルバー。仕上げも製面もちゃんとしていなかったので筆塗りです。もうちょっとアルミっぽいシルバーのほうが良かったかも。まあいいや。
正面にガラスというか透明な保護板を入れる予定でしたが、単車と違って防水にする必要もないし、透明プラバンをきれいに丸く切り出す自信もなかったのでとりあえずなしで。
裏側には大穴が空いてます。設置すれば見えないので問題なし。自作モノの場合は特に、手抜きというか割り切りが大事ですよ。ははっ。
机上で発光テスト。針の光が漏れててガラス押さえが赤くなっちゃってますね。LED の周囲に遮光板をつけることにします。
ちょっと文字盤が小さかったなぁ。周りからバックライトがモレモレです。あまりに気になるようなら作り直しますか。
クルマに取り付けました。おー、いいですね。なかなカッコイイです。
夜になるのを待って照明の確認。
視認性はばっちりです。文字盤のゼロが暗いですね。モータがあるのでうまく光が回り込まなかった模様。まあいいや。
ちょっと荒いですが昼間撮影した動画です。オープニングセレモニーが意外とタイミングよいです。
1200円程度でつくった割にはよくできたと思います。Arduino についてもいい勉強ができました。
これにて完成。
コメント
4件のコメントがあります
初めまして。
私はkeiと申します。
趣味でバイクに乗っているのですが、この記事を偶然拝見して、どうしても自作のメーターが作りたくなり、目下、c言語の勉強中です。
まず、ど素人なので失礼な質問や基礎を理解せずの質問に失礼があればご容赦ください。
今はc言語のレファレンスを見ながらスケッチの構成を勉強させていただいているのですが、まず、私はバイクのメーターの自作にチャレンジしているので、obdなるものがどういうものかわかりません。
構文をみるとライブラリを使って、obdから
回転数を入手してるのは理解できました。
ここは他の事例を参考にパルス信号を取り出し回転数に変換するのは、私の今後の課題においておくとして、どうしてもわからないのが、
if (obd.errors >= 2)という部分です。
これは何を入手し、どういう判断をしているのかがわかりません。
エラーが出たらもう一度通信して初めからって感じかなって思うのですが、これをバイクに置き換えるとどうすればいいのかご教示いただけると幸いです。
長文になりましたが、どうか50の手習いにお付き合いください。
早速失礼しました。
コメントを見当違いのところに書き込んでしまいました
私が見ていたのは、アナログメーターの自作のところでした。
ボルティーに乗られているのですね。
私は、カタナの750に乗っていて、先日、針が折れてしまってメーターをどうしようって見ていたらたどり着いていきさつです。
keiさんこんばんは。ご丁寧にありがとうございます。
(コメントの場所をアナログタコメータの記事に移動しました)
まず OBD2 についての説明は別記事 http://kyu.php.xdomain.jp/?... を御覧ください。
残念ですが単車には車の OBD2 に相当するインターフェイスがありません。もしかしたら近年の単車にはあるかもしれませんが、KATANA750 にはないと思います。
この記事のタコメータは、車の自己診断コネクタに市販の読み取り機器を改造して取り付け、その機器と通信し Arduino でステッピングモータを制御するというものです。ですのでこの仕組みでは単車のタコメータは作れないでしょう。
もしやるとしたら、どうにかして点火信号を取り出してカウントする方法が考えられます。サードパーティ製の外付けタコメータと同様ですね。よくあるのはプラグコードにコードをぐるぐる巻にしてピックアップの代わりにするというやり方でしょうか。ちなみにわたしのボルティは点火コイルの一次側からとりました。
ただしピックアップがうまく行っても、それをどうやって回転数に変換するかというところは、結構難しかったと思います。たとえば4発で 1500rpm とすると、一気筒あたり一分間に 187.5 回点火するわけですが、ただ数えていても一分経たないと187.5回点火したかどうかはわからないですよね。一秒だと3.125回。いずれにしてもしばらく待たないとその時の回転数がわからないんです。
ちなみに if (obd.errors >= 2) の部分ですが、obd からエラーが返ってきたら、というような意味です。このライブラリの決り文句ですね。メインループ内でエラーが返ってきたら再接続するというような処理に使っています。
KATANA750 のタコメータは確か機械式だったと思います。これを自作の電気式に変えるのはかなりハードルが高いと思います。頑張ってください。
Kyu様
早速のご返信感謝いたします。また急な質問に関わりませず、ご丁寧にお答えいただき、重ねてお礼申し上げます。
まず、エラーコードについてですが、私が考えていますバイクへのコンバートでは、そもそもエラー信号がありませんので、このコードは削除とすれば良いですね。
次にピックアップの件ですが、これはおっしゃる通りの方式(確かゲート方式)ですと低回転でタコメーターとして機能できないと思うので、レシプロカル方式で、1サイクルの周期間の時間を測って時間あたりのパルス数を計算させる方式ではどうかと考えます。とはいえ、両方式を知ったのは昨日のことですので、これからどうすれば実現できるかを考えなくてはなりません。
すでにarduinoとステッピングモーターは調達済なのであとには引けないですし。
Kyu様のように丁寧にご説明いただけると少し頑張ろうという気になれます。
これからもド素人の天然質問にお付き合いいただけるとありがたいです。