산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

아두이노로 모델 레일 디지털 DCC 명령국 만들기 - 무료 앱 포함

부품 목록

부품수량비고
스파크펀 아두이노 프로 미니 328 - 5V/16MHz1
LMD18200T1H-브리지 드라이버
PCB1
리니어 레귤레이터 78051
3.6V 0.5W 제너 다이오드1
HC-06 블루투스 모듈1
0.1옴 2와트 저항1전류 감지용
커패시터 220µF116V
커패시터 10µF116V
세라믹 커패시터 0.1µF3
저항 10k옴2
저항 4.7k옴1
스크류 터미널 2P 3.5mm1전원 입력
스크류 터미널 6P 2.54mm1트랙 출력
4핀 2.54mm 소켓1블루투스 모듈용
12핀 2.54mm 소켓2아두이노 프로 미니용

앱 및 온라인 서비스

프로젝트 소개

이 시스템의 차별점: 매우 간단한 전자 회로로 DCC 신호와 트랙 전력을 공급하지만, 실제 복잡한 작업은 스마트폰 앱이 수행합니다. 휴대폰의 컴퓨팅 파워를 활용해 각 명령 패킷을 구성하므로 아두이노 컨트롤러의 부담이 크게 줄어듭니다.

업데이트 내역:

아두이노로 모델 레일 디지털 DCC 명령국 만들기 - 무료 앱 포함
아두이노로 모델 레일 디지털 DCC 명령국 만들기 - 무료 앱 포함
아두이노로 모델 레일 디지털 DCC 명령국 만들기 - 무료 앱 포함
아두이노로 모델 레일 디지털 DCC 명령국 만들기 - 무료 앱 포함
아두이노로 모델 레일 디지털 DCC 명령국 만들기 - 무료 앱 포함

이 시스템은 NMRA 호환 디코더와 작동합니다. 앱 'LocoMotive'가 DCC 패킷을 구성해 블루투스로 아두이노에 전송하면, 아두이노는 DCC 클럭 신호와 결합해 트랙으로 내보냅니다. 부품비 약 £20(이베이 구매 기준).

주요 기능

이전 DCC 무선 시스템 작업을 발전시켜, HC-06 블루투스 모듈과 LMD18200 H-브리지(2A)를 탑재한 수신기 아두이노 회로와 블루투스 명령국을 구성했습니다.

1단계: 아두이노 스케치

전체 스케치는 첨부 파일 참조. 핵심은 루프와 데이터 수신부입니다. 안드로이드 앱이 완성된 패킷을 보내면 여기서 디코딩해 DCC 패킷 포맷으로 변환합니다.

void loop() {
  if (bluetooth.available() > 0) {
    inString = bluetooth.readStringUntil('\n');
  }
  if (inString.substring(0, 1) == "D") {
    string();
  }
  delay(20);
}

string() 함수는 수신한 텍스트 문자열을 파싱해 DCC 패킷의 적절한 위치에 각 명령을 배치합니다.

예시:

NMRA 패킷 표준 참고: S-9.2.1 표준 문서

LMD18200은 DIR 핀에 DCC 신호, PWM 핀은 HIGH 고정 필요.

2단계: 프리칭 회로도

아두이노 프로 미니가 HC-06으로 블루투스 데이터 수신 → NMRA 표준 클럭 사이클로 패킷 생성 → 새 데이터 수신 시 시퀀스 인터럽트 및 패킷 업데이트 → 트랙으로 전송.

필수 부품 (이베이 구매 가능):

HC-06 안테나 연장: 모듈 안테나 끝에 31.2mm 단단한 구리선(접지선 활용) 납땜. 수신 범위 크게 향상. 안테나 선은 슬리브로 피복해 타 부품과 쇼트 방지.

주의: HC-06 연결은 PCB Rx → 모듈 Rx, PCB Tx → 모듈 Tx (크로스 아님).

전류 감지 보호 회로: 0.1옴 감지 저항으로 아날로그 입력 A0에서 0~200mV(0~2A) 측정. 약 5mV/스텝 → 50mA 정밀도. 2A 도달 시 아두이노 D13 HIGH로 LMD18200 브레이크 핀 작동해 출력 차단. LMD18200 내장 과열 보호도 백업으로 동작.

if (C > 2000) { // 2A
  Serial.println("Over Current");
  digitalWrite(13, HIGH); // 브레이크 작동
}

소비 전류 값을 매초 블루투스로 앱에 전송:

void send_c() {
  t = millis() - lastmillis;
  if (t >= interval) {
    bluetooth.write(sensorValue);
    bluetooth.write('c');
    lastmillis = millis();
  }
}

3단계: 안드로이드 앱

코드

locomotive_dcc_sep19.ino (아두이노)

// 1 Sep 2019
// Android App 'Locomotive DCC'용 스케치, LMD18200 H-브리지 사용
// CV 읽기/쓰기 기능 추가

#include <SoftwareSerial.h>
SoftwareSerial bluetooth(8,9); // RX, TX

int C; int sensorValue;
long t = 0, lastmillis = 0, interval = 1000;
String inString;
int a[8];
int preamable_type = 0;
int Address;
float CV_VAL, cv_val, cv_val0, cv_val1, cv_val2, cv_val3, cv_val4, cv_val5, cv_val6, cv_val7;
int test_num, cv_write_val, Cs;
boolean cv_logic, ok;
int num;

#define TIMER_SHORT 0x8D  // 58µs 펄스
#define TIMER_LONG  0x1B  // 116µs 펄스
unsigned char last_timer = TIMER_SHORT;
unsigned char flag = 0;
unsigned char every_second_isr = 0;

#define PREAMBLE 0
#define SEPERATOR 1
#define SENDBYTE 2
unsigned char state = PREAMBLE;
unsigned char preamble_count = 16;
unsigned char outbyte = 0, cbit = 0x80;
unsigned char xdata = 0, data = 0, data_f = 0, data_f1 = 0, data_f2 = 0;
int locoAdr = 9;

struct Message { unsigned char data[7]; unsigned char len; };
#define MAXMSG 3
struct Message msg[MAXMSG] = {
  { {0xFF,0,0xFF,0,0,0,0}, 3 }, // 아이들 메시지
  { {locoAdr,0,0,0,0,0,0}, 3 }  // 128 스텝 속도 메시지 (0x3f)
};
int msgIndex = 0, byteIndex = 0;

void SetupTimer2() {
  TCCR2A = 0;
  TCCR2B = (0<= MAXMSG) msgIndex = 0;
          byteIndex = 0;
        }
        break;
      case SEPERATOR:
        flag = 0;
        state = SENDBYTE;
        cbit = 0x80;
        outbyte = msg[msgIndex].data[byteIndex];
        break;
      case SENDBYTE:
        if (outbyte & cbit) flag = 1; else flag = 0;
        cbit >>= 1;
        if (cbit == 0) {
          byteIndex++;
          if (byteIndex >= msg[msgIndex].len) {
            state = PREAMBLE;
            preamble_count = (preamable_type == 0) ? 16 : 24;
          } else {
            state = SEPERATOR;
          }
        }
        break;
    }
    if (flag) { latency = TCNT2; TCNT2 = latency + TIMER_SHORT; last_timer = TIMER_SHORT; }
    else { latency = TCNT2; TCNT2 = latency + TIMER_LONG; last_timer = TIMER_LONG; }
  }
}

void setup() {
  Serial.begin(115200);
  analogReference(INTERNAL);
  pinMode(13, OUTPUT);
  bluetooth.begin(9600); delay(500);
  Serial.println("Bluetooth Started");
  bluetooth.println("Bluetooth Started");
  DDRD = B01100000; // D5, D6 출력
  SetupTimer2();
  t = millis(); lastmillis = millis();
  digitalWrite(6, LOW); digitalWrite(13, HIGH); // 브리지 출력 끔
  int get_cv_val = cv_calc(test_num);
}

void current() {
  int value = 0;
  for (int i = 0; i < 5; i++) { value += analogRead(A0); delay(1); }
  sensorValue = value / 5;
  C = 10.8 * sensorValue; // mA (내부 레퍼런스 1.1V, 0.1옴 감지 저항)
  if (C > 2000) {
    Serial.println("Over Current");
    bluetooth.println("Short!");
    digitalWrite(6, LOW); digitalWrite(13, HIGH);
    bluetooth.println(C);
  }
}

void loop() {
  if (bluetooth.available()) { inString = bluetooth.readStringUntil('\n'); Serial.println(inString); }
  if (inString.substring(0,1) == "D") { string(); }
  if (inString.substring(0,1) == "C") { digitalWrite(6, HIGH); digitalWrite(13, LOW); } // 과전류 후 리셋
  if (inString.substring(0,1) == "G") { digitalWrite(6, HIGH); digitalWrite(13, LOW); current(); bluetooth.println(C); } // 전류 요청
  if (inString.substring(0,1) == "A") { digitalWrite(6, HIGH); digitalWrite(13, LOW); get_cv_data(); cv1_prog(); digitalWrite(6, LOW); digitalWrite(13, HIGH); } // CV1 쓰기
  if (inString.substring(0,3) == "get") { cv_val = 0; digitalWrite(6, HIGH); digitalWrite(13, LOW); get_cv_num(); cv_read(); digitalWrite(6, LOW); digitalWrite(13, HIGH); } // CV 읽기
  if (inString.substring(0,3) == "add") { cv_write_val = 0; digitalWrite(6, HIGH); digitalWrite(13, LOW); get_cv_new_val(); repeat_cv_write(); digitalWrite(6, LOW); digitalWrite(13, HIGH); } // CV 쓰기
  if (inString.substring(0,1) == "V") { delay(50); bluetooth.print("CV1 updated"); Serial.println(Address); }
  if (inString.substring(0,1) == "E") { digitalWrite(6, LOW); digitalWrite(13, HIGH); } // 비상 정지
  inString = "";
}

// --- 헬퍼 함수들 (파싱, 패킷 구성, CV 읽기/쓰기 시퀀스 등) ---
// 원본 코드의 모든 헬퍼 함수(string, amend_len3/4, assemble_3/4_byte, print_data,
// cv_current, cv_read, cv1_prog, reset_packet, page_preset_packet, cv1_write_packet,
// cv_verify1/0_packet, cv_write_packet, valid_packet, repeat_cv_write, cv_write,
// cv_calc) 포함 생략. 필요시 원본 참조.

커스텀 파트 및 인클로저

인클로저 내부에 완성된 회로

아두이노로 모델 레일 디지털 DCC 명령국 만들기 - 무료 앱 포함

회로도

bluetooth_android_dcc_lmd18200_S8NTVsI4LY.fzz (프리칭 파일)
앱 사용 설명서 첨부

제조공정

  1. MrRobot: 음성·터치·흔들기로 제어하는 우분투 모바일 라피로 로봇
  2. 아두이노 기반 6연발 칵테일 제조기 – 나만의 자동 바텐더 만들기
  3. 아두이노 디지털 주사위: LCD 기반 랜덤 넘버 제너레이터 만들기
  4. DIY 아두이노 USB 게임 컨트롤러 - 나만의 고성능 게임패드 만들기
  5. 아두이노 우노로 만드는 LCD 애니메이션 & 게임 기초
  6. 에너지 하베스팅 내장 스마트 자동 끈 신발 제작기
  7. 아두이노 소나 & 프로세싱으로 실시간 거리 측정 및 시각화
  8. 픽셀 체이서: 아두이노 나노로 만든 인터랙티브 원탭 LED 게임
  9. 볼트 IoT와 아두이노 우노로 구현하는 무선 LED 밝기 제어 (PWM 6채널)
  10. 1만 원대 휴대용 아두이노 날씨 스테이션 – 나노, DHT22, BMP180, LCD로 직접 제작