• 車種別
  • パーツ
  • 整備手帳
  • ブログ
  • みんカラ+

にゃんカラのブログ一覧

2018年02月04日 イイね!

Defi ADVANCE の通信について

簡単ですが、Defi ADVANCE の通信プロコトルについて調べたので書いておきます。
全部のプロトコルを調べたわけではありませんので、ご参考レベルにしてください。
(詳細を調べる気力がないので、詳細を知っている人がいたら教えていただけると嬉しいです)

ちなみに、過去にメーターを動かす実験をしています。この情報で、メーターを動かすくらいはできるはずです。
https://minkara.carview.co.jp/userid/2407630/blog/38798741/


◆物理結線について
Defi ADVANCE シリーズのコントロールユニットとメーターは、4本の線で結線されています。
そして、説明書などにも記載があるように、相互通信(双方向通信)です。
Defi Link は片方向の通信で、コントローラーからデータが一方的に送られるだけでしたが、ADVANCE は異なります。

具体的な結線は、以下の通りです。

黒線 ・・・ GND
赤線 ・・・ メーターからのデータ線(コントローラーが受信)
白線 ・・・ コントローラーからのデータ線(メーターが受信)
黄線 ・・・ 12V 電源

◆通信プロトコルその1
通信は RS232C 準拠の形式で、Defi LINK と同じです。
具体的には、以下の通りです。

通信速度: 19200bps
データ長: 8bit
パリティ: 偶数パリティ
ストップビット: 1bit

◆通信プロトコルその2
ADVANCE は機能が豊富なので、Defi LINK よりもプロトコルは複雑です。
ちなみに、アラームと調光の機能については解析していませんので、必要な方はご自分で解析をお願いします。

①初期化
IGNによってコントローラの電源を入れると、まずはコントローラーからメーターの初期化のパケットが流れます。(1回)
具体的には、下のようなものです(Cの配列で表現しています)。

uint8_t openGauge0[] = {0, 0xFF, 0xFF, 1, 1, 1, 4, 0, 1, 0xD8, 0, 0, 0, 1, 0xF4, 9, 3, 0, 0, 0, 1, 4, 0, 5, 1, 0};

おそらく、 00FF FF0x がパケットの区切りになっていると思います。
詳細は不明です。00FF がパケットの終わりで FF0x がパケットの開始なのか、00FF FF0x がパケットの開始なのか定かではありませんが、00FF FF0x を発信しておけばパケットの頭とみなされるようです。

②初期化その2
次に、以下のパケットがコントローラーから流されます。(同じものが 4、5回流れます)

uint8_t openGauge1[] = {0, 0xFF, 0xFF, 1, 0x11, 1, 4, 0, 1, 0xD8, 0, 0, 0, 1, 0xF4, 9, 3, 0, 0, 0, 1, 4, 0, 5, 1, 0};

③初期化その3
次は、以下です。x の部分(24番目)が 2 から 13 まで、1ずつカウントアップしていき、それぞれ 5回ずつです。

{0, 0xFF, 0xFF, 1, 0x11, 1, 4, 0, 1, 0xD8, 0, 0, 0, 1, 0xF4, 9, 3, 0, 0, 0, 1, 4, 0, 5, x, 0};


④初期化その4(メーター接続問い合わせ)
その次は、以下です。
メーターの接続状態を問い合わせているものと思われます。
各メーターには種類によってIDが振られているようで、自分が接続の問い合わせを受信したら、メータ自身が返信します。
xの部分は、1から7で一つずつカウントアップしていき、それぞれ 5回流れます。xの部分がメーターの ID だと思われます。

{0, 0xFF, 0xFF, 1, 0x21, 1, 4, 0, 1, 0xD8, 0, 0, 0, 1, 0xF4, 9, 3, 0, 0, 0, 1, 4, 0, 5, 0, x};

メーターの IDは、BOOST、TACO、FUEL PRESS などのメーターの種類に割り振られているものと思われます。
メーターは自分自身に接続の問い合わせがあった場合に、以下を返信します。

{0, 0xFF, 0xFF, 0x0A, y, 0, 0}

y の部分が、メーターから返信されるメーターの ID だと思われます。
具体的には、以下の通りです。(記載のないものは、メーターを持っていないので調べようがなく、わかりません。)
0x01 ・・・ BOOST METER
0x06 ・・・ TACO METER(80φ)
0x09 ・・・ OIL PRESS METER
0x0B ・・・ OIL TEMP METER
0x0C ・・・ WATER TEMP METER

⑤オープニング
次はオープニングのパケットが送られます。100回です。

{0, 0xFF, 0xFF, 1, 0x31, 1, 4, 0, 1, 0xD8, 0, 0, 0, 1, 0xF4, 9, 3, 0, 0, 0, 1, 4, 0, 5, 0, 0};

5番目のデータ 0x31 の部分が 0x30 だとオープニング A になり、0x31 だとオープニング B だと思います。(実験はしていません。)

ここまでで、初期化は終了です。
あとは、データのパケットが流れます。

⑥データパケット
データのパケットは1種類です。1つのパケットに全てのメーターのデータが入っています。(Defi LINK ではデータごとに1つのパケットでした。)
具体的には、以下のようなものです。

uint8_t dataGauge[] = {0, 0xFF, 0xFF, 3, 0, 1, 0, 0, 1, 0xD8, 0, 0, 0, 0, 0, 0, 0xEC, 3, 0x10, 0x10, 0, 0, 0x9F, 1, 0, 0, 0, 0, 0x74, 0, 0, 0, 0, 0};

15から28番目のデータが、メーターの数値のデータです。
15, 16番目が TACO METER です。(ビッグエンディアンです。LSB MSB の順です。)
17, 18番目が、BOOST
19, 20番目が、OIL PRESS
21, 22番目が、FUEL PRESS(推測)
23, 24番目が、OIL TEMP
25, 26番目が、WATER TEMP
27, 28番目が、EXT. TEMP(推測)

TACO は数値がそのまま PRM です。
BOOST は、1000(10進)がメーター盤の0.0、2000が1.0です。(盤面×1000+1000が値)
OIL PRESS は、1000が1.0、2000が2.0です。(盤面×1000が値)
FUEL PRESS は未確認ですが、おそらくOIL PRESS と同じだと思われます。
OIL TEMP は、2000が 100℃です(盤面×20が値)
WATER TEMP は、OIL TEMP と同様です。
EXT. TEMP も OIL TEMP と同じではないかと思います(推測)。

29から33が、メーターとセンサーが接続されているかの状態フラグです。
センサーが接続されていないがメーターが接続されている場合は、エラーになってブザーが鳴ると思います。
29 TACO?
30 ???
31 上位が OIL PRESS, 下位が BOOST
32 上位が OIL TEMP、下位が FUEL PRESS
33 上位が EXT.TEMP?、下位が WATAER TEMP

フラグの値は、
接続なしが 5
センサーのみ接続ありが 1
メーター、センサー双方接続ありが 0 です。
(コントローラーを偽装する場合は、全部0にしておけば問題ないようです)

なお、10バイト目の 0xD8 となっているところがメーターの明るさのデータだと思います。詳細は確認していませんが、ここを変えると明るさが変わります。

⑦クロージング
電源OFF時は、以下のパケットです。
{0, 0xFF, 0xFF, 2}; 1回
{1, 0xFF, 0xFF, 2}; 1回
{0x21, 0xFF, 0xFF, 2}; 105回(これがエンディングアニメーションと思われます。)
{0x51}; 1回



ご参考に、Arduino で試したプログラムを貼っておきます。
[code]
#include <CustomSoftwareSerial.h>

#define SIZEM(a)  (sizeof((a)) / sizeof((a[0])))
#define delayT  5

CustomSoftwareSerial* customSerial;               // Declare serial

uint8_t openGauge0[] = {0, 0xFF, 0xFF, 1,    1, 1, 4, 0, 1, 0xD8, 0, 0, 0, 1, 0xF4, 9, 3, 0, 0, 0, 1, 4, 0, 5, 1, 0}; //23
uint8_t openGauge1[] = {0, 0xFF, 0xFF, 1, 0x11, 1, 4, 0, 1, 0xD8, 0, 0, 0, 1, 0xF4, 9, 3, 0, 0, 0, 1, 4, 0, 5, 1, 0};
uint8_t dataGauge[]  = {0, 0xFF, 0xFF, 3,    0, 1, 0, 0, 1, 0xD8, 0, 0, 0, 0, 0, 0, 0xEC, 3, 0x10, 0x10, 0, 0, 0x9F, 1, 0, 0, 0, 0, 0x74, 0, 0, 0, 0, 0}; //31
uint8_t closeGauge[] = {0, 0xFF, 0xFF, 2};
uint8_t endGauge[]   = {0x51};

void sendOpen(void) {
  // 0 set
  Serial.println("0 set");
  sendData(openGauge0, SIZEM(openGauge0));
  delay(5);
  // 1st set
  Serial.println("1st set");
  openGauge1[4] = 0x11;
  openGauge1[24] = 1;
  openGauge1[25] = 0;
  for(int i = 0; i < 4; i++) {
    sendData(openGauge1, SIZEM(openGauge1));
    delay(delayT);
  }
  for(int i = 2; i < 14; i++) {
    openGauge1[24] = i;
    for(int j = 0; j < 5; j++) {
      sendData(openGauge1, SIZEM(openGauge1));
      delay(delayT);
    }
  }
  // 2nd set (May be DETECT Gauge)
  Serial.println("2nd set");
  openGauge1[4] = 0x21;
  openGauge1[24] = 0;
  for(int i = 1; i < 8; i++) {
    openGauge1[25] = i;
    for(int j = 0; j < 5; j++) {
      sendData(openGauge1, SIZEM(openGauge1));
      //delay(2);
      for (; customSerial->available(); ) {
        //Serial.write(customSerial->read());
        Serial.println(customSerial->read(), HEX);
      }
    }
  }
  // 3rd set (May be OPENING DEMO)
  Serial.println("3rd set");
  openGauge1[4] = 0x31;
  openGauge1[24] = 0;
  openGauge1[25] = 0;
  for(int i = 0; i < 100; i++) {
    sendData(openGauge1, SIZEM(openGauge1));
    delay(delayT);
  }
}

void sendClose(void) {
  Serial.println("Close 0");
  closeGauge[0] = 0;
  sendData(closeGauge, SIZEM(closeGauge));
  Serial.println("Close 1");
  closeGauge[0] = 1;
  sendData(closeGauge, SIZEM(closeGauge));
  //delay(delayT);
  Serial.println("Close 2");
  closeGauge[0] = 0x11;
  for(int i = 0; i < 105; i++) {
    sendData(closeGauge, SIZEM(closeGauge));
    //delay(delayT);
  }
  Serial.println("Close 3");
  closeGauge[0] = 0x21;
  for(int i = 0; i < 55; i++) {
    sendData(closeGauge, SIZEM(closeGauge));
    //delay(delayT);
  }
  Serial.println("Close End");
  sendData(endGauge, SIZEM(endGauge));
}

void sendData(uint8_t dat[], int siz) {
  for(int i = 0; i < siz; i++) {
    customSerial->write(dat[i]);
  }
}

// Init value
void setup() {
  Serial.begin(19200);
  delay(10);
  
  Serial.println("Start Setup");

  customSerial = new CustomSoftwareSerial(7, 6); // rx, tx
  customSerial->begin(19200, CSERIAL_8E1);         // Baud rate: 19200
  delay(100);
  
  Serial.println("Opening start");
  sendOpen(); 
  Serial.println("Opening end");
}

void loop() {
  //static uint16_t l = 0;
  //static uint16_t minus = 10;
  static uint16_t ii = 1;
  static uint16_t i;

  //if (customSerial->available())
  //  Serial.write(customSerial->read());
  if (Serial.available()) {
    i = Serial.parseInt();
  }
  //  customSerial->write(Serial.read());
  //} else {
    // Send data
    if(i != 0L) {
      if(i == 9999L){
        sendClose();
        i = 0;
      } else {
      // TACO 80
      dataGauge[15] = i >> 8; // MSB
      dataGauge[14] = i & 0xFF; // LSB
      // BOOST
      dataGauge[17] = i >> 8; // MSB
      dataGauge[16] = i & 0xFF; // LSB
      // OIL PRESS
      dataGauge[19] = i >> 8; // MSB
      dataGauge[18] = i & 0xFF; // LSB
      // FUEL PRESS
      dataGauge[21] = i >> 8; // MSB
      dataGauge[20] = i & 0xFF; // LSB
      // OIL TEMP
      dataGauge[23] = i >> 8; // MSB
      dataGauge[22] = i & 0xFF; // LSB
      // WATER TEMP
      dataGauge[25] = i >> 8; // MSB
      dataGauge[24] = i & 0xFF; // LSB
      // EXT. TEMP
      dataGauge[27] = i >> 8; // MSB
      dataGauge[26] = i & 0xFF; // LSB
      // ILLMINATION
      //dataGauge[9] = i & 0xFF; // MSB
      //dataGauge[8] = i & 0xFF; // LSB
      }
    }
    sendData(dataGauge, SIZEM(dataGauge));     
    //}
  //}
  ii = ii + 1;
  //delay(delayT);
}
[/code]



追記(2023/10/7):
当時のメモを貼っておきます。






追記です。(2025/6/4)
メーターに送られるデータは、全てが垂れ流されている訳ではありません。
センサーが接続されているという条件だけでなく、初期化時のメーター接続問い合わせで応答を返したメーターに対するデータだけが送信されます。
ですので、メーターを接続していない場合はそのままではデータが取れません。
初期化時の問い合わせに応答してあげる必要があります。


Posted at 2018/02/04 17:58:27 | コメント(4) | トラックバック(0) | 日記
2017年09月30日 イイね!

みんカラ:週末モニターキャンペーン【データシステム】

Q1. データシステム製品を使用したことがありますか?(製品名も)
回答:購入したが、まだ使っていない(MVC811)

Q2. ドライブレコーダーを選ぶ際に優先する機能は?
回答:(1)LED信号対応、(2)画質(ナンバー判別性能)


この記事は みんカラ:週末モニターキャンペーン【データシステム】 について書いています。


※質問を編集、削除しないでください。
Posted at 2017/09/30 21:40:58 | コメント(0) | トラックバック(0) | タイアップ企画用
2017年06月25日 イイね!

A型パナナビにB型サテライトスイッチを繋ぐの事

A型のパナナビでB型のサテライトスイッチを使うには、電圧信号の変換が必要です。
今回は、PICを使って変換してみました。
詳細は、整備手帳をご覧ください
https://minkara.carview.co.jp/userid/2407630/car/1917244/4314188/note.aspx

使ったPICは PIC16F1776 ですが、容量の1割も使っていないので 、メモリが少ない PIC16F1773 でも大丈夫です。
(なお、動作温度の範囲が広いPICを使った方が良いと思います。型番の後ろにIが付くものが、動作範囲が広いものです。)

ソースは以下です。
MPLAB X IDE 3.61、XC8 1.42 で作っています。
個人で利用する場合は、改変含めて自由にご利用ください。
営利目的の利用は、とりあえず禁止しておきます。(営利目的で利用したい方は、ご相談ください。儲ける気はありません。MITライセンスでも良いと思っています。)

(2017.9.7 少し改変しました。MFD SW の配線に常に電圧が掛かってしまうので、フォトカプラをかませました。RC5ピンで、フォトカプラの ON/OFF を切り替えています。模式図は以下の通りです。16番ピン(RC5)がLのとき、5V電源がPICに流れ込んで、フォトカプラがONになり、MFD SW の配線に接続されます。Hの時は、回路がMFD SW 配線から切断されます。)



/*
 * File:   main.c
 * Author: cottonhouse
 *
 * Created on June 14, 2017, 10:21 PM
 */

// PIC16F1776 Configuration Bit Settings
// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT enabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON        // Internal/External Switchover Mode (Internal/External Switchover Mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PPS1WAY = ON     // Peripheral Pin Select one-way control (The PPSLOCK bit cannot be cleared once it is set by software)
#pragma config ZCD = OFF        // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR)
#pragma config PLLEN = ON       // Phase Lock Loop enable (4x PLL is always enabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF      // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)

#define _XTAL_FREQ 32000000 

#include <PIC16F1776.h>
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

// wire
#define Blue    1
#define Orange  2
#define Mfd 3
// SW ap. B
#define NC          0
#define VOLPLUS     1
#define VOLMINUS    2
#define FORWORD     3
#define PREVIOUS    4
#define ZOOMMINUS   5
#define ZOOMPLUS    6
#define SRC         1
#define MAP         2
#define MUTE        3
#define RINGDOWN    4
#define RINGUP      5
//#define LOGIC5V
#ifdef  LOGIC5V
    // NAVI Logic 5V
    #define SW0     0UL
    #define SW1     255UL
    #define SW2     511UL
    #define SW3     767UL
    #define SWNC    1023UL
#else
    // NAVI Logic 3.3V
    #define SW0     0UL
    #define SW1     254UL // 1.24V
    #define SW2     440UL // 2.15V
    #define SW3     581UL // 2.84V
    #define SWNC    682UL // 3.3V
#endif
// for MFD SW
#define SWNC_MFD    1023UL
#define SWUP_MFD    0UL
#define SWENT_MFD   418UL
#define SWDOWN_MFD  740UL

void init(void) {
    OSCCON = 0b11110000; // Internal OSC 8MHz(32MHz)
    ADCON1 = 0b10100000;    // Right justified, AD変換クロック 2.0 micro sec, Vss, Vdd    
    
    ANSELA = 0b00000000;
    ANSELB = 0b00000001;    // RB0
    ANSELC = 0b10000000;    // RC7
    TRISA = 0b00000000;
    TRISB = 0b00000001;  // RB0 is INPUT
    TRISC = 0b10000000;  // RC7 is INPUT
    PORTA = 0b00000000;
    PORTB = 0b00000000;
    PORTC = 0b00000000;
 
    // DAC for Blue wire (10bit))
    DAC1CON0bits.FM = 0b0;
    DAC1CON0bits.OE1 = 0b0;
    DAC1CON0bits.OE2 = 0b0;
    DAC1CON0bits.PSS = 0b00;
    DAC1CON0bits.NSS = 0b00;
    DAC1CON0bits.EN = 1;
    
    // DAC for Orange wire (10bit))
    DAC2CON0bits.FM = 0b0;
    DAC2CON0bits.OE1 = 0b0;
    DAC2CON0bits.OE2 = 0b0;
    DAC2CON0bits.PSS = 0b00;
    DAC2CON0bits.NSS = 0b00;
    DAC2CON0bits.EN = 1;    
    
    // DAC for MFD (10bit))
    DAC5CON0bits.FM = 0b0;
    DAC5CON0bits.OE1 = 0b0;
    DAC5CON0bits.OE2 = 0b0;
    DAC5CON0bits.PSS = 0b00;
    DAC5CON0bits.NSS = 0b00;
    DAC5CON0bits.EN = 1;
    
    // OP Amp for Blue wire
    OPA1CONbits.UG = 1;
    OPA1CONbits.ORPOL = 0;
    OPA1CONbits.ORM = 0;
    OPA1NCHSbits.NCH = 0b0000;
    OPA1PCHSbits.PCH = 0b0010;  // DAC1 out
    OPA1CONbits.EN = 1;
   
    // OP Amp for Orange wire
    OPA2CONbits.UG = 1;
    OPA2CONbits.ORPOL = 0;
    OPA2CONbits.ORM = 0;
    OPA2NCHSbits.NCH = 0b0000;
    OPA2PCHSbits.PCH = 0b0011;  // DAC2 out
    OPA2CONbits.EN = 1;
        
    // OP Amp for FMD SW
    OPA3CONbits.UG = 1;
    OPA3CONbits.ORPOL = 0;
    OPA3CONbits.ORM = 0;
    OPA3NCHSbits.NCH = 0b0000;
    OPA3PCHSbits.PCH = 0b0010;  // DAC5 out
    OPA3CONbits.EN = 1;
}

// convert analog value to SW number
// 220R
int convSwVal(long sVal) {
  int retVal;

  if(sVal < 87L) {
    // 0R
    retVal = 1;
  } else if(sVal < 257L) {
    // 47R
    retVal = 2;
  } else if(sVal < 427L) {
    // 115R
    retVal = 3;
  } else if(sVal < 598L) {
    // 225R
    retVal = 4;
  } else if(sVal < 769L) {
    // 423R
    retVal = 5;
  } else if(sVal < 939L) {
    // 975R
    retVal = 6;
  } else {
    // 100KR
    retVal = 0;
  }
  return retVal;
}

void outDAC(int Wire, unsigned long AnalogVal) {
    switch(Wire) {
        case Blue: // Blue wire
            DAC1REFH = AnalogVal >> 8;
            DAC1REFL = AnalogVal & 0xFF;
            DACLDbits.DAC1LD = 0b1;
            __delay_us(20);
            break;
        case Orange: // Orange wire
            DAC2REFH = AnalogVal >> 8;
            DAC2REFL = AnalogVal & 0xFF;
            DACLDbits.DAC2LD = 0b1;
            __delay_us(20);
            break;
        case Mfd: // MFD SW
            // NCの時はRC5をHにし、それ以外はRC5をLにする(NCで結線を切断する)
            if (AnalogVal == SWNC_MFD) {
                    PORTCbits.RC5 = 0b1;
            } else {
                    PORTCbits.RC5 = 0b0;
            }
            DAC5REFH = AnalogVal >> 8;
            DAC5REFL = AnalogVal & 0xFF;
            DACLDbits.DAC5LD = 0b1;
            __delay_us(20);
            break;
        default:
            break;
    }    
}

// Output to pins
void outputSwData(int wire, int SW) { 
    static int  isOnMFD = Blue;
    
    switch(wire) {
        case Blue: // Blue
            switch(SW) {
                case NC: // (NC)
                    if(isOnMFD == Blue) {
                        isOnMFD = 0;
                        outDAC(Mfd, SWNC_MFD);
                    }
                    outDAC(Blue, SWNC);
                    break;
                case VOLPLUS: // VOL +
                    outDAC(Blue, SW2);
                    break;
                case VOLMINUS: // VOL -
                    outDAC(Blue, SW3);
                    break;
                case FORWORD: // >
                    outDAC(Blue, SW0);
                    break;
                case PREVIOUS: // <
                    outDAC(Blue, SW1);
                    break;
                case ZOOMMINUS: // Zoom (-)
                    isOnMFD = Blue;
                    outDAC(Mfd, SWUP_MFD);
                    break;
                case ZOOMPLUS: // Zoom (+)
                    isOnMFD = Blue;
                    outDAC(Mfd, SWDOWN_MFD);
                    break;
                default:
                    break; 
            }
            break;
        case Orange: // Orange
            switch(SW) {
                case NC: // (NC)
                    if(isOnMFD == Orange) {
                        isOnMFD = 0;
                        outDAC(Mfd, SWNC_MFD);
                    }
                    outDAC(Orange, SWNC);
                    break;
                case SRC: // SRC
                    outDAC(Orange, SW0);
                    break;
                case MAP: // MAP
                    isOnMFD = Orange;
                    outDAC(Mfd, SWENT_MFD);
                    break;
                case MUTE: // Mute
                    outDAC(Orange, SW3);
                    break;
                case RINGDOWN: // Ring off
                    outDAC(Orange, SW1);
                    break;
                case RINGUP: // Ring up
                    outDAC(Orange, SW2);
                    break;
                default:
                    break;
            }
            break;
        default:
            break;
    } 
}

void main(void) {
    long    blueVal;
    int     blueSw;
    long    orangeVal;
    int     orangeSw;
    
    init();
    
    while(1) {
        // Blue wire
        ADCON0 = 0b00110001;    // AN12 ADC Start (RB0) 21pin
        __delay_us(20);
        ADCON0bits.GO = 1;
        while(ADCON0bits.GO);
        blueVal = ADRESL + (ADRESH * 256);
        blueSw = convSwVal(blueVal);
        
        outputSwData(Blue, blueSw);
        
        // Orange wire
        ADCON0 = 0b01001101;    // AN19 ADC Start (RC7) 18pin
        __delay_us(20);
        ADCON0bits.GO = 1;
        while(ADCON0bits.GO);
        orangeVal = ADRESL + (ADRESH * 256);
        orangeSw = convSwVal(orangeVal);
        
        outputSwData(Orange, orangeSw);
    }
}
Posted at 2017/06/25 23:20:54 | コメント(0) | トラックバック(0) | 日記
2017年05月20日 イイね!

A型にSRVD設置の追加情報

A型にSRVD設置の追加情報A型にSRVDを設置しています。
以前に概要をご紹介していますが、以前のやり方と一部変えているところがあります。それは、CAN の配線です。

以前にご紹介したやり方だと、OBD のコネクタから CAN の枝線を延長しています。
しかし、このやり方は CAN の規格としてはあまり良くありません。なぜなら、CAN の枝線は長さが決まっており、大体 60cm くらいが長さの目安です。(線の端で信号が反射しますが、線が長いと反射した信号と元の信号に時間差によるズレが生じ、信号がボヤケてしまうためです。信号の読み取りエラー率が高くなります。)

枝線を車体前側から後部まで引くと、60cmでは到底済みません。
(多分、枝線の終端に 60Ω程度の抵抗を付ければ反射は抑えられると思うのですが、BUS 全体のインピーダンスに問題が出そうな気がします。)

枝線を引けないとすると、どうすればいいのか?
幹線を引っ張って行くしかありません。幹線を引いていって、幹線から60cm程度の枝線を出し、また幹線を、前に戻してやるのが正攻法です。(B型はそのように配線されています。)

手書きが好きなのでまた手書きですが、下の模式図のように配線しています。




CAN の幹線は、ボディ統合ユニットのコネクタから取り出していますが、模式的に図で表すと下の図のようになっています。



コネクタからピンを抜き、抜いたピンを適当なメスピンに収めています。(追記:すいません。オスとメスが逆でした。逆に読み替えて下さい。)
その線を車体後部まで持っていき、また戻してきてオスピンをつないで、コネクタに刺しています。
つまり、線を延長して後ろまで迂回させています。
迂回させた幹線から枝線を出し、レーダーにつないでいます。

線をぶった切って延長しても意味は同じです。単に車体ハーネスを切りたくなかったので、ピンを抜いているだけです。
CAN の規格上は、幹線を延長するのが一番安定するはずです。

(ボディ統合ユニットのコネクタからピンを抜くのは、針のような工具が必要です。
 そして、ピンの構造がわかっていないと、なかなか抜けません。)

さて、幹線を延長するのはハードルが高い場合、枝線を延長する方法を採ることになります。
枝線を延長する場合、枝線はなるべく短い方が CAN 通信が安定するはずです。

ショートレンジレーダー(SRR)のマスターは助手席側後方ですので、運転席側にある OBD のコネクタから取るより、助手席に近いところから取れると好都合です。

衝撃センサー付きでない車体の場合、いい位置に枝線が出ていますので、これを使うのが良いと思います。
助手席グローブボックスの左側、下の図の位置です。



具体的には、下の写真のコネクタです。
ピンクのテープでハーネスに固定されていますが、テープを外すと少し伸ばすことができます。



メスのコネクタが車体側です。コネクタの結線は、以下の図の通りです。
オスのコネクタを購入して結線しても良いですし、カニ(エレクトロタップ)で線から取っても良いと思います。



ちなみに、オスのコネクタですが、auto-epartsさんにあります。
http://auto-eparts.ocnk.net/product/831



5pin 6pin が CAN の線です。




実際にCANの線(5,6)とIGN(1),GND(7)を繋いでいるのが以下の写真です。


その他の補足です。
スイッチですが、SRRマスターの 8pin に結線しています。
8pin に 12V が一度流れると SRVD の機能が OFF になり、もう一度流れると ON になります。(トグル式で切り替わります。)
なので、スイッチは押している間だけ繋がるスイッチ(モーメンタリースイッチ)で OK です。
ON にするとミラーの LED が一度点灯するので、スイッチが機能しているかどうかが判定できます。

具体的には、私は下のようなスイッチを使っています。XV HV 用のスイッチです。ちなみに、隣のスイッチは飾りですw



それから、私はヒューズを後ろの方に設置していますが、前の方とかメンテしやすいところに設置した方が良いです。


おまけです。
上で紹介した衝撃センサーのコネクタの図に書いてあるように、このコネクタにはイモビライザーの LED 点滅の信号が来ています。
バッテリー電源も来ているので、お手軽にイモビライザーの LED が増設できます。


追加です。
幹線とか枝線のイメージ図です。




BIU のところの CAN の線は、枝線ではなく幹線です。
幹線を取れるところは、あまりありません。PC LAN の HUB スイッチのように、ジャンクションとしてまとめられてしまっているためです。BIU のところと、ステアリング裏あたりにあるコネクタからくらいしか取るところがありません。
Posted at 2017/05/20 14:47:19 | コメント(5) | トラックバック(0) | クルマ
2017年02月14日 イイね!

A型でSRVDのブザーを鳴らそう

今回、A型にSRVDのブザーを追加していますが、機器の構成は以下のようになっています。
CAN BUS に接続するモジュール、Arduino が2台、他励式の圧電スピーカーです。


■CAN BUS Shield 用ライブラリの準備
CAN に接続してデータを取得するモジュールは、MCP2515というICを使っていてるものなら使えると思います。

ただし、以下の Seeed Studio のライブラリは、CAN モジュールの動作クロックが 16MHz として作られています。中華製の CAN BUS モジュールは、動作クロックが 8MHz のものが多いようです。動作クロックが 8MHz の場合は、ライブラリの修正が必要です。(私も修正しようとしましたが、うまく動かすことができませんでした。)
ソフトウェアを修正したくない場合は、水晶発振器を 8MHz のものから 16MHz のものに載せ替えれば動作するハズです。私はそうしました。

今回のプログラムに使用したライブラリは、Seeed Studio の CAN BUS Shield 用のものです。以下に ありますので、ダウンロードして下さい。

http://wiki.seeed.cc/CAN-BUS_Shield_V1.2/

Arduino UNO など、一般的な Arduino を使う場合はそのまま使えますが、今回私が使ったような Digispark の ATTiny85 を載せている Arduino を使う場合、通常の SPI のライブラリが使えないために、ライブラリを一部書き換える必要があります。

書き換えると一般の Arduino では使えなくなってしまうので、コピーを取ってファイル名を変更するのが良いと思います。

CAN BUS Shield 用のライブラリは3つのファイルで構成されていますので、以下のようにファイル名を変更します。

mcp_can.h   →  mcp_can_digi.h
mcp_can.cpp  →  mcp_can_digi.cpp
mcp_can_dfs.h  →  mcp_can_dfs_digi.h

次にファイルの中身を書き換えます。
ファイル:map_can_digi.h
#include "mcp_can_dfs.h"

#include "mcp_can_dfs_digi.h"
に変更。

ファイル:map_can_digi.cpp
#include "mcp_can.h"

#include "mcp_can_digi.h"
に変更。

ファイル:mcp_can_dfs_digi.h
#include <SPI.h>

#include <bitBangedSPI.h> 
に変更。

上記3つのファイルを Arduino のライブラリのフォルダに適当なフォルダを作って格納します。

■SPI ライブラリの準備
次に、Digispark の小型 Arduino で使える SPI ライブラリをダウンロードします。以下にあります。

https://github.com/nickgammon/bitBangedSPI

ファイルの中身を修正します。
ファイル:bigBandedSPI.h
クラス定義の最後に以下の行を追加します。ファイルの一番最後の行でOKです。
extern bitBangedSPI SPI;


bigBandedSPI.h とbigBandedSPI.cpp をArduino のライブラリのフォルダに適当なフォルダを作って格納します。

■Arduino のプログラム
CAN パケット判定用のDigispark 版のプログラムは以下のようなものです。
(非商用なら自由に使って頂いて結構です。改変も自由に行ってくださって構いません。)

// for Digispark
#define __AVR_ATtiny85__
#include "mcp_can_digi.h"
// SPI用
#define MOSI 0    // PB0
#define MISO 1    // PB1
#define SCK  2    // PB2
#define SS   3    // PB3
// ブザー出力用
#define OPIN1  4
// CAN用
MCP_CAN CAN(SS);   // Set SS pin
bitBangedSPI SPI(MOSI, MISO, SCK);  // MOSI, MISO, SCK

// winker flag
unsigned char winkerLeft = 0; 
unsigned char winkerRight = 0; 

// for CAN Message
unsigned char len = 0;
unsigned char buf[8];
unsigned long id;

void setup() {
    pinMode(OPIN1, OUTPUT);   // ブザー ON/OFF 出力用
    digitalWrite(OPIN1, LOW);
START_INIT:
    if(CAN_OK != CAN.begin(CAN_500KBPS)) {  // init can bus : baudrate = 500k
        goto START_INIT;
        delay(100);
    }
}

void loop() {
    if(CAN_MSGAVAIL == CAN.checkReceive()) { // check if data coming
        CAN.readMsgBufID(&id, &len, buf);    // read data,  id: CAN Id, len: data length, buf: data buf
        switch (id) {
          case 0x282:
            (buf[5] & 0x20) ? (winkerRight = 0xFF): (winkerRight = 0);  // right winker flag
            (buf[5] & 0x10) ? (winkerLeft = 0xFF): (winkerLeft = 0);    // left winker flag
            break;
          case 0x25C:
            // Back | something is approaching | something is in the blind spot
            ((buf[5] & 0xC0) | (buf[5] & 0x4 & winkerRight) | (buf[5] & 0x8 & winkerLeft) | (buf[4] & 0x1 & winkerRight) | (buf[4] & 0x2 & winkerLeft)) ? digitalWrite(OPIN1, HIGH): digitalWrite(OPIN1, LOW);
            break;
          default:
            break;
        }
    }
}

ブザーを鳴らすべきだと判定されたら、4ピンが HIGH になります。
ゼビウスの効果音を鳴らすプログラムを使う場合、4ピンとゼビウス効果音のモジュールの 3ピンを接続します。
CAN BUS モジュールへの接続は、SI が 0ピン、SO が 1ピン、SCK が 2ピン、CS が 3ピンです。
(今回使用した中華製のモジュールの場合、CS を繋がないとうまく動きませんでした。SPI は 1モジュールだけの接続の場合は CS を GND に落とすことで代用できるハズなのですが、うまく動かすことができませんでした。)  

Arduino Uno など一般的な Arduino とSeeed Studio の CAN BUS Shield  を使う場合は、以前に整備手帳に記載したプログラムが使えますので、そちらをご覧ください。

Posted at 2017/02/14 22:57:18 | コメント(10) | トラックバック(0) | 日記

プロフィール

「[整備] #レヴォーグ ツイーターバッフル 3Dプリント https://minkara.carview.co.jp/userid/2407630/car/3056290/8313411/note.aspx
何シテル?   07/27 22:49
にゃんカラです。 単なる自慢ではなく、役に立つことを書きたいと思います。 よろしくお願いします。
みんカラ新規会員登録

ユーザー内検索

<< 2025/8 >>

     12
3456789
10111213141516
17181920212223
24252627282930
31      

リンク・クリップ

VNレヴォーグ(E型)/CAN通信調査(3) Mのギア等 
カテゴリ:その他(カテゴリ未設定)
2025/05/23 01:41:24
アクセサリーライナースイッチ D型へ交換 
カテゴリ:その他(カテゴリ未設定)
2025/03/31 00:01:17
STIレザーシート塗装補修 
カテゴリ:その他(カテゴリ未設定)
2024/07/03 00:38:09

愛車一覧

スバル レヴォーグ スバル レヴォーグ
VM4から乗り換えました。車体色はまたレッドです。 初めてローンを使って購入しました。ロ ...
スバル インプレッサスポーツワゴン スバル インプレッサスポーツワゴン
重い車体に 1.5L NAエンジンで非力でしたが、挙動が素直なクルマでした。 扁平率82 ...
スバル レガシィツーリングワゴン スバル レガシィツーリングワゴン
10年乗りましたが、不注意で少しコスってしまって入庫した時にオイル漏れなどがわかり、いろ ...
スバル レヴォーグ スバル レヴォーグ
現在スバル車3台目です。 A型は初めてです。

過去のブログ

2018年
01月02月03月04月05月06月
07月08月09月10月11月12月
2017年
01月02月03月04月05月06月
07月08月09月10月11月12月
2016年
01月02月03月04月05月06月
07月08月09月10月11月12月
2015年
01月02月03月04月05月06月
07月08月09月10月11月12月
ヘルプ利用規約サイトマップ
© LY Corporation