Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일

라즈베리 파이를 이용해 원격 컴퓨터의 전원 스위치 제어

개발자라면 다들 공감하시겠지만, 사실 업무와 공부의 경계가 많이 모호한 면이 있습니다. 이 때문에 회사 컴퓨터를 켜놓고 집에서 접속해야 할 경우가 종종 있는데요, 그렇다 해도 많지는 않아서 항상 켜놓기에는 전기 사용이 좀 아깝습니다. 하지만, 꺼놓고 퇴근하자니 또 집에서 필요해지면 아쉽기 때문에 그러는 것도 좀 망설여지는데요.

그래서 ^^ 만들었습니다. 회사 컴퓨터의 전원을 원격으로 제어가 가능하도록 하는 것입니다.




이를 구현하기 위해, 6년 전에 구매했던 - 먼지가 내려앉은 넷두이노를 꺼냈습니다. ^^

.NET Micro Framework - 넷두이노 플러스
; https://www.sysnet.pe.kr/2/0/1392

(이제는 지원도 끊겨 버렸지만) 마지막 firmware 버전인 4.2.0.1로 업그레이드까지 하고 네트워크 구현까지 완료했지만... 아쉽게도 이더넷 LAN 포트가 접촉 불량 문제가 발생했습니다. 납땜의 문제는 아닌 것 같고 랜 소켓 자체가 내부에 이더넷 케이블과 접촉되는 공간이 유격이 발생한 듯 케이블을 살짝 움직일 때마다 네트워크 접속이 끊어져 버리는 것입니다.

할 수 없이 ^^; 다시 먼지가 쌓이도록 창고에 두고.

그다음 제가 가지고 있는 보드 중,


후보로 떠오른 것이 "라즈베리 파이 제로 W"입니다. WiFi를 기본 제공하고 RPi의 특성상 PC 환경에 준하는 개발 환경을 가지고 있기 때문에 프로그램 작성도 매우 용이합니다.

한 가지 아쉬운 것은 제가 가지고 있는 "라즈베리 파이 제로 W"가 Data Pin 쪽에 헤더가 납땜되어 있지 않은 모델이라는 점입니다. (혹시, 제로 W 모델을 구매하시려는 분이 있다면 "with Headers" 모델을 추천합니다.)

[그림 - 출처 http://www.icbanq.com/P008219607]
raspberry_pi_zero_w_with_no_pin_header_1.jpg

그래서 저걸로 Data Pin을 제어하려면 핀 헤더를 납땜해야 하는 불편함이 있습니다.

How to solder header pins to the Raspberry Pi Zero (W) 
; https://www.youtube.com/watch?v=UDdbaMk39tM

가벼운 문제라면, 제가 인두기가 없습니다. ^^ 고민하던 차에 생각난 것이 바로 FTDI 장치입니다.

PC에 연결해 동작하는 자신만의 USB 장치 만들어 보기
; https://www.sysnet.pe.kr/2/0/11606

FTDI 장치를 rpi에 연결하면 이후부터는 Serial port를 제어하는 방식으로 코딩할 수 있기 때문에 다음의 글에서 설명한 데로,

Raspberry PI Zero (W)에 FTDI 장치 연결 후 C/C++로 DTR 제어
; https://www.sysnet.pe.kr/2/0/11716

간단하게 해결할 수 있습니다.




남은 작업은 FTDI의 GND 선과 DTR 신호를 컴퓨터에 연결하는 것입니다. 참고로 제가 가지고 있는 "GIGABYTE GA-Z87-HD3" 메인 보드는,

GIGABYTE GA-Z87-HD3
; https://www.gigabyte.com/Motherboard/GA-Z87-HD3-rev-1x#ov

다음과 같은 PW+, PW- 핀 배열을 가지고 있습니다.

turn_on_the_device_1.png

따라서, FTDI의 GND를 PW-에 연결하고 DTR 선을 PW+에 연결하면 됩니다.

turn_on_the_device_2.png

참고로, PW+와 PW-간의 전압을 측정해 보면 약 3.347V가 나옵니다. FTDI의 DTR 라인은 아두이노의 데이터 핀처럼 별도의 전원을 제공하는 것이 아닌, 단순히 선을 연결해 주는 동작만 하는 것이기 때문에 컴퓨터 전원 스위치를 켜는 용도로 사용할 수 있습니다.

이렇게 연결을 한 후, FtdiApp 프로젝트의 소스 코드를 다음과 같이 변경해 DTR 신호를 사람이 Power 스위치를 누르는 동안 정도의 시간만큼 ON 시켜 주는 것으로 바꿔줍니다.

#include <stdio.h>
#include <string>
#include <vector>
#include <iostream>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>

using namespace std;

int main(int argc, char *argv[])
{
    // http://xanthium.in/Controlling-RTS-and-DTR-pins-SerialPort-in-Linux

    string portNumber = "0";
    string portName = "/dev/ttyUSB";

    if (argc < 2)
    {
        cout << "FtdiApp [portNumber]" << endl;
        cout << "ex - set DTR on /dev/ttyUSB0" << endl;
        cout << "\t" << "FtdiApp 0" << endl;
        return 1;
    }

    portNumber = argv[1];
    portName.append(portNumber);

    int fd = open(portName.c_str(), O_RDWR | O_NOCTTY);
    if (fd == -1)
    {
        cout << "NO Port: " << portName << endl;
        return 1;
    }

    int dtrFlag = TIOCM_DTR;
    ioctl(fd, TIOCMBIS, &dtrFlag);

    usleep(500 * 1000); // 500ms

    ioctl(fd, TIOCMBIC, &dtrFlag);
    close(fd);

    return 0;
}

자.. 이제 ^^ 컴퓨터 케이스를 열고 DTR, GND를 각각 PW+, PW- 선과 연결한 다음 Raspberry PI 콘솔에서 다음과 같이 실행해 주면,

$ ./FtdiApp.out 0

컴퓨터가 켜지는 것을 볼 수 있습니다. 마찬가지로 한 번 더 실행해 주면, 운영체제가 (제어판의 전원관리에서 설정한 동작에 따라) Shutdown이나 최대 절전 모드로 들어가게 됩니다.




주의할 것은, 반드시 DTR과 PW+를 연결하고 GND와 PW-를 연결해야 합니다. 컴퓨터 케이스의 Power Switch는 물리적으로 접점이 끊긴 것을 연결하는 것이기 때문에 +/- 극을 맞출 필요가 없지만 FTDI 장치는 극이 맞아야 합니다. 저도 내부적인 FTDI 장치의 배선을 몰라 자세하게 설명할 수는 없지만, 현상 자체는 DTR을 PW-, GND를 PW+에 연결하는 경우 그 순간 컴퓨터 전원이 들어오게 됩니다. 계측기로 + 단자를 DTR에 - 단자를 GND에 놓고 측정하면 저항이 무한대가 되지만, 그 반대로 하는 경우에는 약 250K 정도의 저항이 측정되는 걸로 봐서 선이 연결된 것과 유사한 역할을 하는 것 같습니다.

이제 나머지 문제는, "마감"을 훌륭하게 하는 것입니다. 대충 해 놓으면 동작은 하겠지만 실 사용 환경에서라면 좀 더 완성도를 높이는 게 좋습니다. 일단 FTDI와 라즈베리 파이를 연결하는 것은 USB 케이블로 깔끔하게 해결은 됩니다. 하지만 FTDI의 DTR, GND와 메인 보드 간의 연결을 하는 것은 그다지 매끄럽게 해결이 안 됩니다. 우선, 기존의 컴퓨터 케이스에 있는 Power Switch를 안 쓰는 걸로 가정하고 다음의 케이블을 사용할 수 있습니다.

PC 파워 전원 스위치 케이블/메인보드연결
; http://item.gmarket.co.kr/detailview/item.asp?goodscode=995567752

computer_power_cable_1.png

Female Header 부분이 메인 보드의 Power Pin에 정확히 연결할 수 있기 때문에 편리하긴 한데 문제는 반대쪽 스위치를 잘라내고 FTDI의 DTR, GND에 연결하는 것이 불편합니다. 이 케이블의 선은 단선이 아닌 연선인데다 제가 가지고 있는 와이어 스트리퍼 기준으로,

Vessel 3500E-2
; https://www.eleparts.co.kr/goods/view?no=5803

24AWG(0.5mm)로 피복이 벗겨지는데 따라서 FTDI의 DTR, GND 소켓에 끼우기에는 너무 얇습니다. (악어 클립으로 집는 것도 그다지 권장할 수 없습니다.)

차라리 그보다는 22AWG 단선으로 "PC 파워 전원 스위치 케이블"과 납땜으로 연결하거나, 아니면 Female-Female 케이블22AWG 단선으로 FTDI와 납땜 없이 연결하는 것이 좋습니다.




그런데 결론적으로는, 라즈베리 파이도 사용하지 않았습니다. 왜냐하면 이게 영... 마감이 좋지 않습니다. ^^; 라즈베리 파이 용 케이스도 구매해야 하고 라즈베리 파이 쪽에 별도의 휴대폰 어댑터로부터 5VDC도 공급해야 합니다. 당연히 필요한 것이 아니냐??? 라고 할 텐데, 제가 다른 방법을 하나 더 찾아냈습니다. 바로 회사 컴퓨터 외에 늘 켜져 있는 NAS 장비를 이용하는 것입니다.

Synology NAS(DS216+II)에 docker 설치 후 .NET Core 2.1 응용 프로그램 실행하는 방법
; https://www.sysnet.pe.kr/2/0/11713

이건 다음에 다시 정리해서 올리겠습니다. ^^




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]





[최초 등록일: ]
[최종 수정일: 10/7/2018 ]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer@outlook.com

비밀번호

댓글 쓴 사람
 




1  2  3  [4]  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
12255정성태7/6/2020267.NET Framework: 923. C# - ETW(Event Tracing for Windows)를 이용한 Finalizer 실행 감시파일 다운로드1
12254정성태7/2/2020198오류 유형: 626. git - REMOTE HOST IDENTIFICATION HAS CHANGED!
12253정성태7/2/2020335.NET Framework: 922. C# - .NET ThreadPool의 Local/Global Queue파일 다운로드1
12252정성태7/2/2020504.NET Framework: 921. C# - I/O 스레드를 사용한 비동기 소켓 서버/클라이언트파일 다운로드2
12251정성태7/1/2020384.NET Framework: 920. C# - 파일의 비동기 처리 유무에 따른 스레드 상황파일 다운로드2
12250정성태7/1/2020743.NET Framework: 919. C# - 닷넷에서의 진정한 비동기 호출을 가능케 하는 I/O 스레드 사용법 [1]파일 다운로드1
12249정성태6/29/2020207오류 유형: 625. Microsoft SQL Server 2019 RC1 Setup - 설치 제거 시 Warning 26003 오류 발생
12248정성태6/29/2020197오류 유형: 624. SQL 서버 오류 - service-specific error code 17051
12247정성태6/29/2020401.NET Framework: 918. C# - 불린 형 상수를 반환값으로 포함하는 3항 연산자 사용 시 단축 표현 권장(IDE0075) [2]파일 다운로드1
12246정성태6/29/2020289.NET Framework: 917. C# - USB 관련 ETW(Event Tracing for Windows)를 이용한 키보드 입력을 감지하는 방법
12245정성태6/25/2020539.NET Framework: 916. C# - Task.Yield 사용법 (2) [2]파일 다운로드1
12244정성태8/28/2020378.NET Framework: 915. ETW(Event Tracing for Windows)를 이용한 닷넷 프로그램의 내부 이벤트 활용파일 다운로드1
12243정성태6/23/2020234VS.NET IDE: 147. Visual C++ 프로젝트 - .NET Core EXE를 "Debugger Type"으로 지원하는 기능 추가
12242정성태6/24/2020240오류 유형: 623. AADSTS90072 - User account '...' from identity provider 'live.com' does not exist in tenant 'Microsoft Services'
12241정성태6/26/2020398.NET Framework: 914. C# - Task.Yield 사용법파일 다운로드1
12240정성태6/23/2020331오류 유형: 622. 소켓 바인딩 시 "System.Net.Sockets.SocketException: An attempt was made to access a socket in a way forbidden by its access permissions" 오류 발생
12239정성태6/21/2020287Linux: 30. (윈도우라면 DLL에 속하는) .so 파일이 텍스트로 구성된 사례
12238정성태6/21/2020321.NET Framework: 913. C# - SharpDX + DXGI를 이용한 윈도우 화면 캡처 라이브러리
12237정성태7/8/2020335.NET Framework: 912. 리눅스 환경의 .NET Core에서 "test".IndexOf("\0")가 0을 반환
12236정성태6/19/2020268오류 유형: 621. .NET Standard 대상으로 빌드 시 dynamic 예약어에서 컴파일 오류 - error CS0656: Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'
12235정성태6/19/2020244오류 유형: 620. Windows 10 - Inaccessible boot device 블루 스크린
12234정성태6/19/2020247개발 환경 구성: 494. NuGet - nuspec의 패키지 스키마 버전(네임스페이스) 업데이트 방법
12233정성태6/19/2020222오류 유형: 619. SQL 서버 - The transaction log for database '...' is full due to 'LOG_BACKUP'. - 두 번째 이야기
12232정성태6/19/2020197오류 유형: 618. SharePoint - StoreBusyRetryLater 오류
12231정성태6/15/2020377.NET Framework: 911. Console/Service Application을 위한 SynchronizationContext - AsyncContext
12230정성태6/15/2020241오류 유형: 617. IMetaDataImport::GetMethodProps가 반환하는 IL 코드 주소(RVA) 문제
1  2  3  [4]  5  6  7  8  9  10  11  12  13  14  15  ...