16芯 配線チェッカー試作版 RS-485 バージョン 2020/11/06

 配線の端末側から電線を識別する「配線対照機」で、極性なし、コモン線も不要です。

 電線 16 本だけでなく、うまく使えば離れたところからケーブル 8 本の識別も可能です。
 RS-485 通信を使っているので、数100m 離れたところでも識別可能と思われます。

 TTL/RS-485 モジュールは、現場でも安定、安心して使えるように絶縁型を使用しています。

 ※RS-485 は基本的に「活線挿抜」禁止なので、こういう使い方が大丈夫なのか・・・は不明。



■送信側
 配線をチェックする電線(最大 16 本)を接続します。(活線では使用できません)
 ※写真↑には 4 桁 LED がありますが、速度アップのために省いています。

■受信側
 チェックする配線のうち2本を接続します。
 識別番号(1~16)が、A+側、B- 側の順で表示されます。同時にブザーがピッと鳴ります。
 表示されるタイミングは RS-485 9600bps の場合、1.5 秒に 1 回程度です。
 19200bps にすればもう少し速くなります。

■弱点
 配線抵抗が 1kΩ程度でも通信できてしまうので、確実につながっているとは判断できない。
 また、他の配線と 3kΩ程度以下で接続されている場合、短絡と判断される。

■仕組み
 16 本のうちどれか 2 本を選んで RS-485 で識別番号を送信します。これを総当たりで行います。
 配線の切り換えは、リードリレー 16 個 × 2 組と I2C I/Oエキスパンダ(16 点用)を使っています。
 同じ配線の組み合わせで 2 回チェック(2 回目は極性反転)しているため、時間がかかています。
 
 受信側は、単に RS-485 で受信した識別番号を表示させているだけです。
 送信、受信とも非常にシンプルです。

■接続図
 接続図(PDF)は、こちらです。


// *********************************
// 送信側 Arduino nano
// *********************************

/* 16 芯配線チェッカー RS-485 版 送信側
 * I/O エキスパンダ MCP23108 2個を使ってリードリレー16個 × 2 を切り換え、総あたりで線番を RS-485 送信
 * 2020/11/06
 */

#include "Wire.h";
// MCP23108 No.1
const uint8_t ADDR1 = 0x20; // address 0x20 (ADDR to GND)
// MCP23108 No.2
const uint8_t ADDR2 = 0x27; // address 0x27 (ADDR to VCC)

#define LED  7 // 動作中点滅
#define DERE 2 // rs-485 ED/~RE

void setup() {
  Serial.begin(9600); // for RS-485
  Wire.begin();  
  // MCP23108 No.1
  Wire.beginTransmission(ADDR1);
  Wire.write(0x00); // port-A i/o direction register
  Wire.write(0x00); // 0=output, 1=input
  Wire.endTransmission();
  Wire.beginTransmission(ADDR1);
  Wire.write(0x01); // port-B i/o direction register
  Wire.write(0x00); // 0=output, 1=input
  Wire.endTransmission();
  // MCP23108 No.2
  Wire.beginTransmission(ADDR2);
  Wire.write(0x00); // port-A i/o direction register
  Wire.write(0x00); // 0=output, 1=input
  Wire.endTransmission();
  Wire.beginTransmission(ADDR2);
  Wire.write(0x01); // port-B i/o direction register
  Wire.write(0x00); // 0=output, 1=input
  Wire.endTransmission();

  pinMode(DERE, OUTPUT);       // RS-485 H= 送信,L= 送信 
  digitalWrite(DERE, HIGH);    // RS-485 常に送信 
  pinMode(LED, OUTPUT);       // LED 
  digitalWrite(LED, HIGH);    // LED 
}

void loop() {
  char hex[17] = "0123456789ABCDEF";
  int a, b, c, d;
  // 全数チェック
  for (int i = 0; i <= 15; i++){
    digitalWrite(LED, !digitalRead(LED)); // LED 点滅
    if (i < 8){
      a = 1 << i;
      b = 0;
    }
    else {
      a = 0;
      b = 1 << (i - 8);
    }
    // No.1 リレー切替 
    Wire.beginTransmission(ADDR1);
    Wire.write(0x12); 
    // NOT(~) で反転: 1 = ON(LOW), 0 = OFF(HIGH)
    Wire.write(~a);
    Wire.endTransmission();
    // out B
    Wire.beginTransmission(ADDR1);
    Wire.write(0x13); //talk to GPIOB register
    // Active LOW なので NOT(~) で反転: 1 = ON(LOW), 0 = OFF(HIGH)
    Wire.write(~b);
    Wire.endTransmission();
    for (int j = 0; j <= 15; j++){
      if (i != j){
        if (j < 8){
          c = 1 << j;
          d = 0;
        }
        else {
          c = 0;
          d = 1 << (j - 8);
        }
        // No.2 リレー切替
        Wire.beginTransmission(ADDR2);
        Wire.write(0x12); 
        // NOT(~) で反転: 1 = ON(LOW), 0 = OFF(HIGH)
        Wire.write(~c);
        Wire.endTransmission();
        // out B
        Wire.beginTransmission(ADDR2);
        Wire.write(0x13); //talk to GPIOB register
        // NOT(~) で反転:1 = ON(LOW), 0 = OFF(HIGH)
        Wire.write(~d);  
        Wire.endTransmission();
        // リードリレー切替待ち
        delay(1);
        // 送信
        byte buf[4];
        buf[0] = 0x02; // STX
        buf[1] = hex[i];
        buf[2] = hex[j];
        buf[3] = 0x03; // ETX
        // 送信は 1 回のみ
        Serial.write(buf, 4);
        Serial.flush();
      }
    }
  }
}

// *********************************
// 受信側 Arduino nano
// *********************************

/* 16 芯配線チェッカー RS-485 版 受信側
 * 2020/11/06 f.izawa
 */
/* TM1637.cpp の TubeTab[] に マイナス'-' 0b01000000 を追加している
 * static int8_t TubeTab[] = {0x3f,0x06,0x5b,0x4f,
                           0x66,0x6d,0x7d,0x07,
                           0x7f,0x6f,0x77,0x7c,
                           0x39,0x5e,0x79,0x71,
                           0b01000000,0b01000110};//0~9,A,b,C,d,E,F,-,-|
 */
// 4-Digit LED Display
#include "TM1637.h"
#define CLK 7 //pins definitions for TM1637 and can be changed to other ports
#define DIO 8
TM1637 tm1637(CLK, DIO);
#define DERE 2 // rs-485 ED/~RE
#define BZ 13  // Buzzer
int idx;

void setup() {
  Serial.begin(9600, SERIAL_8N1);
  Serial.setTimeout(10);
  pinMode(DERE, OUTPUT);
  // DE/~RE 受信だけなので、常に LOW
  digitalWrite(DERE, LOW);
  tm1637.init();
  // BRIGHT_TYPICAL = 2, BRIGHT_DARKEST = 0, BRIGHTEST = 7;
  tm1637.set(BRIGHT_TYPICAL);  
}

void loop() {
  byte res[4];
  tm1637.clearDisplay();    
  while (Serial.available() > 0){
    byte b = Serial.read();
    if (b == 0x02){ // STX
      idx = 0;
      res[0] = 0x02;
    }
    else if (b == 0x03){ // ETX
      if (res[0] == 0x02){
        // LED 表示
        int i;
        if (res[1] <= 0x39) i = res[1] - 0x30; // 0..9
        else i = res[1] - 0x41 + 10; // A..F
        i++;
        if (i < 10){
          tm1637.display(1, i);
        }
        else{
          tm1637.display(0, 1);
          tm1637.display(1, i - 10);
        }

        if (res[2] <= 0x39) i = res[2] - 0x30;
        else i = res[2] - 0x41 + 10;
        i++;
        if (i < 10){
          tm1637.display(2, 16); // '-'
          tm1637.display(3, i);
        }
        else{
          tm1637.display(2, 1);
          //tm1637.display(2, 17); // '-|'
          tm1637.display(3, i - 10);
        }
        tone(BZ, 1200, 100) ;  // ブザー
        //delay(200);
        //tone(BZ, 1200, 100) ;  
        delay(500);
      }  
    }
    else{
      idx ++;
      if (idx <= 2) res[idx] = b;
    }
  }
}