秋月電子PIC18F8720モジュールキットの20MHZクリスタルを取り外します。ハンダコテを2丁使用して外しますが、60W程度でハンダを溶かして横にスライドさせる感じで外します。写真右側にスライドさせないと、ICの足にハンダがついてしまい失敗します。解けにくい場合はクリスタルのパッドにハンダ新たにを流し込んでおくと解けやすくなります。
※標準状態では最大速度20MHzの動作となってしまいます。40MHz動作でプログラムを作成していますので、10MHzに換装してください。交換後は4逓倍で40MHzで動作可能となります。
クリスタルを取り外したパッドはハンダ吸い取り処理を行います。銅線にコテをあてて、熱を加えれば、銅線に余分なハンダがすいとられます。
10MHZクリスタルをハンダあげします。
(RSオンラインで手に入ります)
右の写真が接続ピンです。
画像をクリックすると、拡大します。
接続略図
あなたのシステムから データを送信するだけで@MicroDriverがPicaso MD-1へグラフィカル表示を制御します。
接続は上の図に示すように接続します。
@MicroDriverの使用するピンは
あなたのシステムとの接続ピン
SDI:
SDO:
SCK
BUSY/READY:
INTRUPTS
4D Systems μVGA Picaso MD-1と@MicroDriverの接続は
RS232C TX:
RS232C RX:
となっています。
@MicroDriver側の送信信号は5vのためPicaso MD1入力レベルに変換するため1KΩの抵抗をTX側に接続します。(5V−>3Vへレベル変換)
簡単に略図で表すと下のように接続します。(画像をクリックすると拡大します)

1.初期化
メインルーティンにて必ずINTRUPTS LINEの初期化を最初に行って下さい。
でないと、spi通信がうまくいかない場合があります
この画面表示が完了後に各データの最大値設定をします。
サンプルCソース(CCS−C)
ユーザー側初期化処理
main()
{
unsigned int data_from_Master = 0,data_from_Slave;
//spiマスター側初期設定 パルスエッジはlow->highで通信 クロックは40MHzの1/4
//SS端子は使用しない
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4 | SPI_SS_DISABLED
);
output_high(PIN_C0);//INTRUPTS LINE 初期化
}
2.最大値と警報値の設定
MODE-1のバーグラフと設定数値の関係は右の写真のようになります。(画像クリックで拡大します)
0x42(hex number string:M )は最大値をセットするためのコマンドです
spi通信にて0x42+表示するbarの位置+最大値+0を15回書き込みます
例はbar1(数値1)の最大値を3000とする場合です
データ配列は
0x42 01 0B B8 00 00 00 00 00 00 00 00 00 00 00 00 00と送信します。
注意しなければならないのは16進数で送信することで、0B B8は10進数で3000となります。
またSPI通信で書き込めるのは整数のみです!!
void bar1_max_set()
{
//@MicroDriverのready信号が0Vになるまで待機します
//あなたのシステムの電圧入力ピンがG1ピンとして記載してます。
//READ Ready&busy Line (@MicroDriver)が送信データ受け入れ準備が可能か調べます
//0ならデータ送信が可能で、1なら準備中です。準備中(描画中)なら待機します。
while(input(pin_G1)!=0)
{
};
//@MicroDriveに、これから設定データを送ることを通知します。
//INTERRUPTS LINEを 5Vにします
//
ext_int_pulse();
//MAX ARART SET COMMAND
//0x42(hex number)は最大値をセットするためのコマンドです
//spi通信にて0x42+表示するbarの位置+最大値+0を15回書き込みます
//例:bar1の最大値を3000とする場合は
//0x42 01 0B B8 00 00 00 00 00 00 00 00 00 00 00 00 00
//0B B8は10進数で3000です
//SPI通信で書き込めるのは整数です!!
//注意:
//データ送信することを通知して、データを送信しない場合はタイムアウトにより送信データは
//キャンセルされます。
spi_write(0x42);
delay_us(800);
spi_write(1);//BAR1(数値1)の設定
delay_us(100);
//bar1(数値1)に最大値3000を設定
xmsb=make8((long)3000,1);//3000を16進数の2バイトに分解 上位バイトとして0Bになる
xlsb=make8((long)3000,0);//3000を16進数の2バイトに分解 下位バイトとしてB8になる
spi_write(xmsb);
delay_us(100);
spi_write(xlsb);
delay_us(100);
//bar1(数値1)に警報値2500を設定
xmsb=make8((long)2500,1);
xlsb=make8((long)2500,0);
spi_write(xmsb);
delay_us(100);
spi_write(xlsb);
delay_us(100);
delay_us(800);
damy();
}
※この処理をBAR2(数値2)にも同様に行って下さい。
void damy()//ここは絶対に変更しないで下さい。パケットのデータ数調整とタイミングです。
{
p_damy=0;
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
delay_ms(1000);
}
@MicroDriverへの割り込みパルスの送信
void ext_int_pulse()//外部割込みパルス生成
{
output_low(PIN_C0); // Slave(@MicroDrive)のINT1に割込みを発生させるべくパルスを出力する
delay_us(300); //パルス幅:100μsec
output_high(PIN_C0);//あなたのシステムがピンC0よりINTRUPTS LINEに 5V を出力するとして記載
delay_us(300);
output_low(PIN_C0);
}
簡単な処理フローは
(1)準備中かどうかREAD Ready&busy Lineの電圧を調べる
(2)0VならINTRUPTS LINEに 5V外部割込みパルスを送信する。
(3)最大値、警報値を送信する
と言う流れになります。
※ネゴシエーション処理を行うと、遅くなるため、INTRUPTS LINEに 5Vを検知したら直ぐに受信処理を行うようになっています。
表示画面をプリセットパターンMODE-1〜MODE-5に変更します。
1.MODE-1
(1)バーグラフ
バーグラフは2データ表示が可能です。
予め警告値設定データを送信することによって、バーグラフ左に警告ランプをそれぞれ表示できます(青ー>赤)。また表示するデータによって文字列(単位)を数値の右脇に設定出来ます(速度ならKM)。文字列はプリセットされていますので、ユーザが文字列を送信する必要はありません。
(2)OBDii
画面左下はOBDiiの情報を表示するエリアです。単位、OBDiiの種類(エンジンクーラント温度、インテーク温度など)を文字列で表示出来ます。(文字列はプリセットされています)
(3)ATシフト位置
・シフト位置
ユーザが送信したシフト位置を画面右下に表示します。シフト位置表示可能数値は1〜5速です。
・ロックアップ
パーキングはP、ロックアップはL、ハンクラッチ状態は―で表示できます。
・シフトアップ警告
あらかじめ設定されたエンジンシフトアップ指令をあなたのシステムより送信することによって↑が緑から赤に表示することが可能です。
(4)その他
画面右上にその他の数値データを表示出来ます。
2.MODE-2
(1)数値
画面左上の数値が速度(固定)、右が馬力(固定)
画面左下が回転数(固定)、その隣が最大トルク(固定)です。
このモードは常に速度、回転数、ギアポジション、最大トルク回転数 を送信しなければなりません。
シフトタイミング表示は停止するたびに、シフト可能範囲を計算して更新します。
赤の横線がギア位置によって出せるスピードの範囲を表し、緑が最大トルク回転数〜エンジン最大回転数の範囲を表します。白の点線はシフトの軌跡を表します。赤のカーソルが現在の回転数とギア位置により移動します。この表示によって、燃費運転の場合は緑のバーグラフ前で変速、加速運転は緑のバーグラフ内に赤カーソルが入る様に運転すると気持ち良い加速運転が体感できます。
注意:現在のバージョンは1、2速はロックアップなしで想定して速度範囲を計算します。また3−5速はロックアップしないと計算されません。
(2)ATシフト位置
・シフト位置
ユーザが送信したシフト位置を画面右下に表示します。シフト位置表示可能数値は1〜5速です。
・ロックアップ
パーキングはP、ロックアップはL、ハンクラッチ状態は―で表示できます。
・シフトアップ警告
あらかじめ設定されたエンジンシフトアップ指令をあなたのシステムより送信することによって↑が緑から赤にすることが可能です。
トルク計算は40KM以上でトルクが大きくなるほど、最大トルク回転数を更新するようにします。サンプルCソースは
if(maxtorqu<jiku_torqu&&_speed>=40&&maxtorqu_rpm<(long)mid_rpm)
{
maxtorqu=jiku_torqu;
maxtorqu_rpm=(long)mid_rpm;
}
とします。mid_rpmは浮動小数点データとして記載しています。送信データは常に整数です。
3.MODE-3
パワーカーブを表示します。
パワーカーブは
数値1:速度
数値2:回転数
数値3:馬力
経過時間
をユーザが@MicroDriver側へ常に送信します。
画面モード変更のサンプルCソース
void VGA_SET()
{
p_damy=0;
while(input(pin_G1)!=0)
{
}
delay_us(800);
ext_int_pulse();
delay_us(800);
IN=0;
spi_write(0x43);//change modeコマンド
delay_us(800);
if(vew_mode==0)
spi_write(1);
else if(vew_mode==1)//通常バーグラフモード
spi_write(1);
else if(vew_mode==2)//シフトインジケータモード
spi_write(2);
else if(vew_mode==3)//パワーカーブモード
spi_write(3);
else if(vew_mode==4)//リザーブ
spi_write(4);
else if(vew_mode==5)//オシロモード
spi_write(5);
delay_us(800);
//数値の単位を表示する文字列の設定
//0:R P M
//1:Km/h
//2:PS
//3:Km/L
//4:%
//5:L
//6: km
//7:x10ms
//8:kPa
//9: oC
if(vew_mode==4)//MODE-4におけるbar1の文字列設定
{
//7は文字列でX10msと表示
spi_write(7);
delay_us(10);
}
else//その他モードの文字列
//bar1グラフに単位を設定
spi_write(6);//速度を設定する例
delay_us(10);
//bar2グラフに単位を設定
spi_write(0);//回転数を設定する例
delay_us(10);
//数値データ3に単位を設定
spi_write(1);//燃費を設定する例
delay_us(10);
//ここは絶対に変更しないで下さい。パケットのデータ数調整とタイミングです。
spi_write(obdm);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
spi_write(p_damy);
delay_us(800);
}
サンプルCソース
//BUSY/ REDY LINEの信号が0Vになるまで待つと、処理が止まるため、@MicroDriverが描画処
//理中ならスキップすることが必要です
if (input(pin_G1)==0)
{
crc=0;
ext_int_pulse();//割込み信号送信
delay_us(10);
spi_write(0x44);//数値データ送信command
crc=crc+0x44;//送信データのサムを計算
delay_us(10);
spi_write(vga_gearpos);//ギアポジションを送信
crc=crc+vga_gearpos;//送信データのサムを計算
delay_us(10);
spi_write(vga_lockup);//ロックアップ状態 0:ロックアップなし 1:ロックアップ
crc=crc+vga_lockup;//送信データのサムを計算
delay_us(10);
//バーグラフ1(数値1)のデータ
if(vew_mode==2)//MODE-2の数値の場合はスピードを送信する
{
xmsb=make8((long)speed,1);
xlsb=make8((long)speed,0);
}
else//mode2以外はユーザーが選択したデータを送信する例は回転数
{
xmsb=make8((long)mid_rpmd,1);
xlsb=make8((long)mid_rpmd,0);
}
spi_write(xmsb);
crc=crc+xmsb;
delay_us(10);
spi_write(xlsb);
crc=crc+xlsb;
delay_us(10);
//バーグラフ2(数値2)のデータ
//回転数変数は小数点として記載。
//sampleの送信データは1桁を切り捨ててます。
//回転数を1桁目まで表示すると見にくくなりますので
//MODE-2の数値の場合は回転数を送信する
//回転数の変数は浮動小数点
if(vew_mode==2)//MODE-2の数値の場合は必ず回転数を送信する
{
xmsb=make8(((long)(gear_rpm/10))*10,1);
xlsb=make8(((long)(gear_rpm/10))*10,0);
}
else//mode2以外はユーザーが選択したデータを送信する。例は速度
{
xmsb=make8((long)speed,1);
xlsb=make8((long)speed,0);
}
spi_write(xmsb);
crc=crc+xmsb;
delay_us(10);
spi_write(xlsb);
crc=crc+xlsb;
delay_us(10);
//数値3のデータ送信
if(vew_mode==2)//MODE-2では馬力データを必ず送信します
{
if( s_start_speed>=30)//30km以上なら馬力データ送信
{
xmsb=make8((long)jiku_power,1);
xlsb=make8((long)jiku_power,0);
}
else//30KM以下なら0を送信
{
xmsb=make8(zero,1);
xlsb=make8(zero,0);
}
}
else//mode2以外はユーザーが選択したデータを送信する例は燃費
{
xmsb=make8((long)nenpi,1);//例は燃費データの送信
xlsb=make8((long)nenpi,0);
}
spi_write(xmsb);
crc=crc+xmsb;
delay_us(10);
spi_write(xlsb);
crc=crc+xlsb;
delay_us(10);
//単位時間の送信。オシログラフ等を描画するため
if(vga_time4>=old_vga_time4)
vga_spantime=vga_time4-old_vga_time4;
else
vga_spantime= 6600-old_vga_time4+vga_time4;
old_vga_time4=vga_time4;
if(vew_mode==1||vew_mode==2)
{
xmsb=make8(rpm_time1,1);
xlsb=make8(rpm_time1,0);
}
else if(vew_mode==3)
{
xmsb=make8(vga_time4,1);
xlsb=make8(vga_time4,0);
}
else if(vew_mode==4)
{
xmsb=make8(vga_time4,1);
xlsb=make8(vga_time4,0);
}
else if(vew_mode==5)
{
xmsb=make8(vga_spantime,1);
xlsb=make8(vga_spantime,0);
}
//time
spi_write(xmsb);
crc=crc+xmsb;
delay_us(10);
spi_write(xlsb);
crc=crc+xlsb;
delay_us(10);
//shift arart
spi_write(vga_shftupon);//ユーザ側よりシフトポイントアラートを操作 0:NonArart 1:Arart ON
crc=crc+vga_shftupon;
delay_us(10);
//vtec
spi_write(vga_vtecon);//ユーザ側よりVTEC動作モニタを操作 0:VTEC OFF 1:VTECt ON
crc=crc+vga_vtecon;
delay_us(10);
//obd codeの文字列表示
//obdm=1 "Calc Load Value "をMODE-1で表示
//obdm=2 "Engine Coolant Temp "をMODE-1で表示
//obdm=3 "Short fuel trim BK1 "をMODE-1で表示
//obdm=4 "Long term fuel trim "をMODE-1で表示
//obdm=5 "Fuel pressure "をMODE-1で表示
//obdm=6 "InManiPressure kPaA "をMODE-1で表示
//obdm=7 "Engine RPM "をMODE-1で表示
//obdm=8 "Vehicle Speed km/h "をMODE-1で表示
//obdm=9 "Ignition timing Cyl "をMODE-1で表示
//obdm=10= "Intake Air Temp "をMODE-1で表示
//obdm=11 "MAF air flow rate "をMODE-1で表示
//obdm=12 "Throttle Position "をMODE-1で表示
//obdm=13"Not Selsect OBD-ii "をMODE-1で表示

spi_write(obdm);
crc=crc+obdm;
delay_us(10);
//OBD DATA
//valueはOBDiiにて取得した値(整数)
xmsb=make8(value,1);
xlsb=make8(value,0);
spi_write(xmsb);
crc=crc+xmsb;
delay_us(10);
spi_write(xlsb);
crc=crc+xlsb;
delay_us(10);
//MAX TORQU
vga_torqu=(long)(maxtorqu*10);
xmsb=make8(vga_torqu,1);//10倍して小数点1位まで送信
xlsb=make8(vga_torqu,0);
spi_write(xmsb);
crc=crc+xmsb;
delay_us(10);
spi_write(xlsb);
crc=crc+xlsb;
delay_us(10);
//maxtorqu_rpm
xmsb=make8(maxtorqu_rpm,1);//10倍して小数点1位まで送信
xlsb=make8(maxtorqu_rpm,0);
spi_write(xmsb);
crc=crc+xmsb;
delay_us(10);
spi_write(xlsb);
crc=crc+xlsb;
delay_us(10);
//CRC
spi_write(crc);
delay_us(10);
vew_vga=1;
}
タイマー割込みによる単位時間の生成
#int_timer0
void isr0()
{
set_timer0(59285);//5ms毎に、このルーティンを実行する割込み
ms=ms+5;
vga_time=vga_time+1;
vga_time2=vga_time2+1;
vga_time4=vga_time4+1;
if(vga_time>5200)
vga_time=0;
if(vga_time2>3400)
vga_time2=0;
if(vga_time4>6600)//6600x5=33000ms=33秒で0にする。
vga_time4=0;
if(ms>=1000)
{
sec=sec+1;
ms=0;
}
if(sec>=60)
{
min=min+1;
sec=0;
}
}