아두이노 컨트롤러

Hmmsim Metro에 아두이노로 구축한 커스텀 컨트롤러를 연동할 수 있습니다.​
아두이노의 시리얼 통신을 이용해 Hmmsim Metro에 연동하는 방법을 소개해드립니다.
​​​
아두이노에 대한 자세한 정보는 여기서 살펴보세요.
시리얼 통신이 가능하다면 아두이노가 아니더라도 구축할 수 있습니다.

‌시리얼 통신

1. 통신 규격
    초당 비트 : 115200
    데이터 비트 : 8

    아두이노 스케치에서는 다음과 같이 설정할 수 있습니다.

1
Serial.begin(115200);
cs
2. 출력 규칙
    키=값,키=값,키=값,키=값;

    키와 값의 쌍은 여러 개 출력할 수 있으며 콤마(,)로 구분합니다.
    출력의 마지막은 반드시 세미콜론(;)으로 출력해야 합니다.
3. 통신 지연
    데이터 대역폭 제한과 게임에서 처리할 수 있는 버퍼에 제한이 있기 때문에 통신 지연을 설정하는 것이 좋습니다.
    0.05~0.1초 지연 설정을 권장합니다.

    아두이노 스케치에서는 다음과 같이 설정할 수 있습니다.

1
delay(100);
cs

‌필수 키

1. DSD
    On, Off를 값으로 출력하여 DSD를 제어합니다.

    다음은 아두이노의 디지털 핀 입력으로 DSD를 제어하는 예시입니다.

1
2
3
4
5
6
7
8
if(digitalRead(2== HIGH)
{
    Serial.print("DSD=On");
}
else
{
    Serial.print("DSD=Off");
}
cs
2. Reverser
    Forward, Neutral, Off, Backward를 값으로 출력하여 전후진을 제어합니다.

    다음은 아두이노의 디지털 핀 입력으로 전후진을 제어하는 예시입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if(digitalRead(3== HIGH)
{
    Serial.print(",Reverser=Forward");
}
else if(digitalRead(4== HIGH)
{
    Serial.print(",Reverser=Neutral");
}
else if(digitalRead(5== HIGH)
{
    Serial.print(",Reverser=Off");
}
else if(digitalRead(6== HIGH)
{
    Serial.print(",Reverser=Backward");
}
cs
3. PowerNotch
    0에서 4사이 값을 출력하여 역행을 제어합니다.
4. BrakeNotch
    0에서 9사이 값을 출력하여 제동을 제어합니다.

    다음은 아두이노의 아날로그 (가변저항) 입력으로 원핸들 역행과 제동을 제어하는 예시입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
int iAnalog = analogRead(A0);
if(iAnalog  > 721)
{
    Serial.print(",PowerNotch=0,BrakeNotch=8");
}
else if(iAnalog  > 663)
{
    Serial.print(",PowerNotch=0,BrakeNotch=7");
}
else if(iAnalog  > 621)
{
    Serial.print(",PowerNotch=0,BrakeNotch=6");
}
else if(iAnalog  > 580)
{
    Serial.print(",PowerNotch=0,BrakeNotch=5");
}
else if(iAnalog  > 538)
{
    Serial.print(",PowerNotch=0,BrakeNotch=4");
}
else if(iAnalog  > 496)
{
    Serial.print(",PowerNotch=0,BrakeNotch=3");
}
else if(iAnalog  > 455)
{
    Serial.print(",PowerNotch=0,BrakeNotch=2");
}
else if(iAnalog  > 406)
{
    Serial.print(",PowerNotch=0,BrakeNotch=1");
}
else if(iAnalog  > 344)
{
    Serial.print(",PowerNotch=0,BrakeNotch=0");
}
else if(iAnalog  > 288)
{
    Serial.print(",PowerNotch=1,BrakeNotch=0");
}
else if(iAnalog  > 240)
{
    Serial.print(",PowerNotch=2,BrakeNotch=0");
}
else if(iAnalog  > 194)
{
    Serial.print(",PowerNotch=3,BrakeNotch=0");
}
else
{
    Serial.print(",PowerNotch=4,BrakeNotch=0");
}
cs

‌추가 키

필수 키 외에도 필요에 따라 운전실의 버튼이나 스위치에 연동할 수 있는 키가 있습니다.
ADS
ELBCOS
HLpS
HLpDS
TLS
BzS3
PanDS
PanUS
MCBCS
MCBOS
EPanDS
ACMCS
PBS
15KS
ASOS
Klaxon
DHS
DOSL
DCSL
DROSL
DoorKeyL
DOSR
DCSR
DROSR
DoorKeyR

교직절환
회생제동차단
전조등
전조등 반감
시간표등
승무원 연락부저
판타하강
판타상승
MCB투입
MCB차단
비상판타하강
보조공기압축기
주차제동
15Km/h
특수운전
경적
출입문 반감
왼쪽 출입문 열림
왼쪽 출입문 닫힘
왼쪽 출입문 재개폐
왼쪽 출입문 키
오른쪽 출입문 열림
오른쪽 출입문 닫힘
오른쪽 출입문 재개폐
오른쪽 출입문 키
AC, DC
Normal, Cut
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
On, Off
다음은 아두이노의 디지털 핀 입력으로 ADS를 제어하는 예시입니다.

1
2
3
4
5
6
7
8
if(digitalRead(10== HIGH)
{
    Serial.print(",ADS=AC");
}
else
{
    Serial.print(",ADS=DC");
}
cs

‌샘플 스케치

다음은 투핸들 제어를 구현한 샘플 스케치입니다.
아두이노 Due 보드를 기준으로 작성했으며 디지털 핀 입력은 풀업 저항으로 설정했습니다.
역행은 디지털 입력과 아날로그 (가변저항) 입력을 같이 사용하여 구현했으며 제동은 디지털 핀 입력만으로 구현했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
String g_sReverser = "Off";
String g_sPowerNotch = "0";
String g_sBrakeNotch = "9";
 
void setup()
{
    for(int a = 2; a  < <  /span >= 53; a++)
    {
        pinMode(a, INPUT_PULLUP);
    }
    Serial.begin(115200);
    while(!Serial);
}
 
void loop()
{
  // 전후진
  if(digitalRead(14) == LOW) g_sReverser = "Backward";
  else if(digitalRead(15) == LOW) g_sReverser = "Off";
  else if(digitalRead(16) == LOW) g_sReverser = "Neutral";
  else if(digitalRead(17) == LOW) g_sReverser = "Forward";
  Serial.print("Reverser=" + g_sReverser);
 
  // DSD
  if(digitalRead(18) == LOW) Serial.print(",DSD=On");
  else Serial.print(",DSD=Off");
 
  // 역행
  double dPowerNotch = min(max(map(analogRead(A0), 840, 410, 100, 400) * 0.01, 1.0), 4.0);
  if(digitalRead(19) == LOW) g_sPowerNotch = "0";
  else if(digitalRead(20) == LOW) g_sPowerNotch = String(dPowerNotch);
  Serial.print(",PowerNotch=" + g_sPowerNotch);
 
  // 제동
  if(digitalRead(29) == LOW) g_sBrakeNotch = "7";
  else if(digitalRead(28) == LOW) g_sBrakeNotch = "6";
  else if(digitalRead(27) == LOW) g_sBrakeNotch = "5";
  else if(digitalRead(26) == LOW) g_sBrakeNotch = "4";
  else if(digitalRead(25) == LOW) g_sBrakeNotch = "3";
  else if(digitalRead(24) == LOW) g_sBrakeNotch = "2";
  else if(digitalRead(23) == LOW) g_sBrakeNotch = "1";
  else if(digitalRead(22) == LOW) g_sBrakeNotch = "0";
  else if(digitalRead(30) == LOW) g_sBrakeNotch = "8";
  else if(digitalRead(31) == LOW) g_sBrakeNotch = "9";
  Serial.print(",BrakeNotch=" + g_sBrakeNotch);
  
  // ADS
  if(digitalRead(40) == LOW) Serial.print(",ADS=AC");
  else Serial.print(",ADS=DC");
 
  // BzS
  if(digitalRead(41) == LOW) Serial.print(",BzS3=On");
  else Serial.print(",BzS3=Off");
  
  // HLpS
  if(digitalRead(42) == LOW) Serial.print(",HLpS=On");
  else Serial.print(",HLpS=Off");
 
  // HLpDS
  if(digitalRead(43) == LOW) Serial.print(",HLpDS=On");
  else Serial.print(",HLpDS=Off");
 
  // ELBCOS
  if(digitalRead(44) == LOW) Serial.print(",ELBCOS=Normal");
  else Serial.print(",ELBCOS=Cut");
 
  Serial.print(';');
  delay(100);
}
cs
다음은 원핸들 제어를 구현한 샘플 스케치입니다.
아두이노 Uno 보드를 기준으로 작성했으며 디지털 핀 입력은 풀업 저항으로 설정했습니다.
역행과 제동은 아날로그 (가변저항) 입력만으로 구현했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
void setup()
{
    for(int= 2; a  < < /span>= 13; a++)
    {
        pinMode(a, INPUT_PULLUP);
    }
    Serial.begin(115200);
    while(!Serial);
}
 
void loop()
{
  // DSD
  if(digitalRead(2== LOW) Serial.print("DSD=On");
  else Serial.print("DSD=Off");
 
  // 전후진
  if(digitalRead(3== LOW) Serial.print(",Reverser=Backward");
  else if(digitalRead(4== LOW) Serial.print(",Reverser=Forward");
  else Serial.print(",Reverser=Off");
 
  // 역행/제동
  int iAnalog = analogRead(A0);
  if(iAnalog  > 721) Serial.print(",PowerNotch=0,BrakeNotch=8");
  else if(iAnalog  > 663) Serial.print(",PowerNotch=0,BrakeNotch=7");
  else if(iAnalog  > 621) Serial.print(",PowerNotch=0,BrakeNotch=6");
  else if(iAnalog  > 580) Serial.print(",PowerNotch=0,BrakeNotch=5");
  else if(iAnalog  > 538) Serial.print(",PowerNotch=0,BrakeNotch=4");
  else if(iAnalog  > 496) Serial.print(",PowerNotch=0,BrakeNotch=3");
  else if(iAnalog  > 455) Serial.print(",PowerNotch=0,BrakeNotch=2");
  else if(iAnalog  > 406) Serial.print(",PowerNotch=0,BrakeNotch=1");
  else if(iAnalog  > 344) Serial.print(",PowerNotch=0,BrakeNotch=0");
  else if(iAnalog  > 288) Serial.print(",PowerNotch=1,BrakeNotch=0");
  else if(iAnalog  > 240) Serial.print(",PowerNotch=2,BrakeNotch=0");
  else if(iAnalog  > 194) Serial.print(",PowerNotch=3,BrakeNotch=0");
  else Serial.print(",PowerNotch=4,BrakeNotch=0");
 
  Serial.print(';');
  delay(100);
}
cs