출처 : https://www.jetbrains.com/help/pycharm/installation-guide.html

 

Install PyCharm - Help | PyCharm

To create a desktop entry, do one of the following: On the Welcome screen, click Configure | Create Desktop EntryFrom the main menu, click Tools | Create Desktop Entry Install using snap packages For Ubuntu 16.04 and later, you can use snap packages to ins

www.jetbrains.com

블로그의 글보다는 만든 회사에서 제공하는 설치 방법이 최고겠쥬?

 

01. 설치

$ sudo snap install pycharm-community --classic

설치 완료 후 재시작을 하면 "pycharm-community" 명령어로 실행 가능

$ sudo add-apt-repository ppa:mystic-mirage/pycharm
$ sudo apt-get update
$ sudo apt-get install pycharm
너무 느림

 

02. 실행

$ pycharm-community

 

03. 삭제

$ sudo apt-get remove pycharm-community
$ sudo apt-get remove pycharm
$ sudo add-apt-repository --remove ppa:mystic-mirage/pycharm
이하 동문

1. Anaconda 다운로드

 

2. 명령어 입력

설치
$ bash [다운로드 받은 *.sh 파일]

계속 enter 누르다가

yes 입력

 

 

3. bashrc 실행

$ source ~/.bashrc

 

4. Anaconda 설치 확인

$ conda --version

conda: command not found 에러가 발생했을 경우

=> .bashrc 파일 수정

 

1. vi 열기

$ vi ~/.bashrc

2. 경로 추가

export PATH = ~/anaconda3/bin:$PATH

 

3. bashrc 실행

4. Anaconda 설치 확인

01. 한글 키보드 설치

출처 : https://snowdeer.github.io/linux/2018/01/21/ubuntu-16p04-install-korean-keyboard/

한글 키보드 설치

Ubuntu 16.04 LTS 버전 기준으로 한글 키보드를 설치하는 방법입니다.

먼저 아래의 명령어를 수행해서 fcitx-hangul 패키지를 설치합니다.

sudo apt-get install fcitx-hangul

그리고 아래의 절차를 진행합니다.

  • System Settings 실행
  • Language Support 아이콘 실행
  • 언어팩을 설치하라는 팝업창이 뜨면 ‘설치’ 선택
  • ‘Keyboard input method system’ 항목을 fcitx로 변경
  • 재부팅

오른쪽 한/영키(Alt 키)를 이용한 한/영 전환

Unbuntu에서는 기본적으로 오른쪽 Alt 키가 커맨드 실행 기능으로 맵핑이 되어 있습니다. 한/영 전환 키로 활용하고 싶으면 다음과 같이 세팅하시면 됩니다.

  • System Settings에서 Keyboard 실행
  • Shortcuts 탭 선택한 후 Typing 항목 선택
  • 모든 항목(Switch to next source, Switch to previous source, Alternative Characters Key)을 Disabled로 설정(Back 키를 누르면 Disabled가 됨)
  • Compose Key 항목을 Right Alt로 변경
  • Switch to next source를 선택한 다음 오른쪽 Alt 키(한/영 키)를 누르면 Multikey라는 항목으로 값이 설정됨

 

fcitx 설정

  • 설정의 system setting 선택
  • Text Entry 선택
  • 추가 버튼을 이용하여 Hangul(Fcitx)와 English(US)를 추가

02. vim 설치

$ sudo apt-get install vim

vim은 리눅스의 메모장 같은 프로그램이다. 여러가지 단축키를 이용하여 텍스트 파일을 편집할 수 있다.

처음 ubuntu를 깔게 되면 vim을 실행시킬 수는 있지만 방향키를 눌렀을 때 동일한 글자가 반복되는 등의 문제가 발생할 수 있다.

그럴 때를 대비하여 미리 설치해놓으면 나중에 편하다.


03. root 계정 암호 설정

$ sudo passwd [사용자계정]
$ sudo passwd root

개발을 진행하다보면 관리자로 로그인해야 하는 경우가 생긴다. 그 때 비밀번호를 치라그러는데 비밀번호 설정이 안되있으면... 좀 그렇다 ㅋㅋㅋ

그래서 미리 설정해주자

 

plc와 pc 연동을 C#, python으로 구현해보고, npm에 modbus-serial 모듈이 있는 것을 알고 난 후 nodejs를 활용하여 plc와의 연동을 테스트해보았다.

 

예제 코드도 가지고 있었던 터라 아무 문제 없이 해결할 수 있을 줄 알았지만 예상치 못한 문제가 발생하였다.

 

Issue

콜백 함수의 향연으로 Thread를 신경쓰지 않아도 되는 nodejs 특성상 어떤 놈이 먼저 실행이 될 지 알 수가 없다...ㅋ

그러다 보니 serial 통신을 이용해서 하나의 데이터만 가져오는 것은 아무 상관이 없었는데, read를 두 번 이상 하니 이 함수 놈이 요청하고, serial통신 버퍼에 있는 데이터를 몽땅 가져오는 바람에 뒤에 실행되는 read함수에서 데이터가 없다며 에러를 토해내는 것이 아닌가..

 

그렇다면 내가 할 수 있는 최선은 이 중구난방으로 실행되는 비동기 함수들을 순차적으로 실행시켜주면 되는 일..

 

그래서 Async.series를 사용해서 문제를 해결하였다.

 

p.s. series는 단순 순차 실행, waterfall은 순차 실행인데 결과를 다음 콜백 함수에 전달 할 수 있다고 한다더라.

 

해결

개발 환경 : Ubuntu 64bit 16.04

IDE : vscode

nodejs version : v13.11.0

npm package : modbus-serial, async

 

더보기

코드

const ModbusRTU = require("modbus-serial")
var async = require("async");

var client = new ModbusRTU();
var timeoutConnectRef = null

function connect(){
    console.log("Connecting..!!");
    clearTimeout(timeoutConnectRef);

    if(client.isOpen){
        console.log('Already connected!!');
        run();
    }

    client.connectRTUBuffered("/dev/ttyUSB0", {dataBits: 8, stopBits: 1, baudRate: 115200})
    .then(setClient)
    .then(function() {console.log("Connected");})
}

function setClient(){
    console.log("Set client ID..!!");
    client.setID(1);
    client.setTimeout(3000);

    run();
}

var task = [
    function(callback) {
        client.readDiscreteInputs(1,4, function(err, res_read){
            console.log("L1: " ,res_read.data[0], res_read.data[1], res_read.data[2], res_read.data[3])
            callback()
        })
    },
    function(callback){
        client.readHoldingRegisters(1,4, function(err, res_read){
            console.log("L1Q: " ,res_read.data[0], res_read.data[1], res_read.data[2], res_read.data[3])
            callback()
        })
    }
]

function run(){
    var setLoop = setInterval(function(){
        async.series(task, function(err, results){
            console.log("done")
        })
    }, 1000)
}

connect()

 

출력 결과

ㅣ1은 bit를, L1Q는 word를 읽는 것.

github : https://github.com/Mistive/-js-modbusRTU.git

 

task 변수를 생성하여 순차적으로 동작시킬 task를 설정해주고, 1초에 한번씩 위의 동작을 반복하여 내가 필요한 값을 읽어들이는 작업을 수행하였다.

 

처음에 callback()을 function(callback){} 안에 넣지 않고 밖에 넣었더니 순차적으로 진행이 되지 않는 실수를..ㅎ;;

1번의 콜백 함수가 호출이 된 후, 콜백 함수가 수행이 되고, 1의 결과를 출력하고 그 다음 콜백 함수를 수행하는 형식으로 동작한다.

 

이거야 함수가 2개밖에 안되서 콜백에 콜백을 써도 되겠지만..... 한 3~4개만 되도 보는 사람 빡치게 만들기 충분한 코드가 될 것이라고 확답할 수 있다..ㅎㅎ

 

python으로 구현할 때는 thread timer를 이용하여 일정 주기로 Read&Write를 수행했는데, 흠.... js가 좀 더 깔끔한거 같기도 하고...ㅎㅎ

 

무튼 재밌다 코딩 ㅋㅋ

'PLC' 카테고리의 다른 글

[PLC, Python]PLC를 통한 PC 동영상 제어  (9) 2020.02.28

참고 문헌 : http://www.simplymodbus.ca/ASCII.htm

 

Modbus ASCII vs RTU | Simply Modbus Software

 

www.simplymodbus.ca

Modbus RTU는 구현을 했고... Modbus Ascii를 구현하기 위해 필요한 LRC...

 

LRC가 뭔지 찾아보니깐 Longitudinal Redundancy Check 라는 놈이란다.

 

구글 번역기 왈 "종 방향 중복검사"

 

흠... 뭔 소리지... 일단 에러 체크 방법 중 하나기는 한데...

 

에러를 어떻게 체크하는지 알아보니깐

 

LRC 이전 Ascii 코드를 바이너리로 다 바꾼 다음에,

다 더하고, 2의 보수를 취해준 결과값을 LRC랑 비교를 한다고 한다.

 

음... 그렇구나 ㅎㅎ

 

그건 그렇고 그래서 LRC는 어떻게 구하는데?

 

찾아보니

 

이렇게 구한단다.

 

1. byte를 모두 더해준다~

2. 8bit가 넘어가는 carry는 삭제!

3. 2의 보수를 취해준다~

4. 쨘

 

무지 간단하네 ㅋㅋㅋ

 

바로 코드로 옮겨보았다.

calcLRC()_python

def calcLRC(data):
    #Add the RTU Value
    RTU_sum = ((sum(data) & 0xff) ^ 0xff) + 0x01

    lrc = [RTU_sum >> 4, RTU_sum & 0xf]
    
    return lrc

뭐가 이리 간단해?ㅋㅋㅋ

 

입력값은 이렇다.

 LRC = calcLRC([0x11, 0x03, 0x00, 0x6B, 0x00, 0x03])

위의 코드를 해석해보자면.... 음... 일단 다 더하고? 비트 연산을 이용해서 8bit 이후의 값은 제거해주고, 1의 보수를 취해준 다음에 1을 뙇 더해주면?(2의 보수지요)

끗.

 

그 결과를 Hi, Lo 두 개로 나눠서 리스트에 넣고 반환해줬다.

 

진짜 되는지는 PLC에서 확인해봐야겠찌 ㅎㅎ

hexToAscii()_python

def hexToAscii(data):
    ret = []
    for d in data:
        ret.append(ord(format(d, 'X')))

    return ret

추가로 hex를 Ascii로 바꿔주는 함수이다.

 

data 타입은 calcLRC와 동일!

 

코드를 쪼금만 분석해보자면....

 

format(d, 'X') : d를 대문자 hexa형태의 String으로 변환해주는 것이다.

즉, d에 10이라는 int 타입이 있다면 10의 hex값은 A이니깐

format(d, 'X') = "A"라는 의미.

 

ord(parameter) : parameter를 Ascii값으로 바꿔주는 놈이다!

c의 경우 char라는 아주 좋은 타입이 있어서 'A' 하면 바로 Ascii로 인식되지만 이놈의 파이썬은 타입관련된 내용들이 참 그지같다..ㅎ

무튼 parameter가 'A'라면 A의 아스키코드값은 65(=0x41) 이므로 해당 값을 int 형태로 반환한다.

 


추가_2020.09.16

 

Java로 코드를 짜봤다.

 

이번에는 인풋이 그냥 ASCII String 형태로 들어올 때 출력해주는 걸로 짜봤다.

 

package test;

class Hello {
 
	public static void main(String[] args) {
		String s = "0101000A0001";
		
		//반환된 LRC값을 기존 명령 코드에 추가한다.
		s=s + calcLRC(s);
		
		//완성된 명령 코드 앞뒤에 Head와 Tail을 붙여 ASCII to Byte로 변환한 후 전송한다.
		
		byte[] s_byte = s.getBytes();
		byte[] head = {0x3A};
		byte[] tail = {0x0D, 0x0A};
		byte[] result_b = new byte[head.length + s_byte.length + tail.length];
		
		System.arraycopy(head, 0, result_b, 0, head.length);
		System.arraycopy(s_byte, 0, result_b, head.length, s_byte.length);
		System.arraycopy(tail, 0, result_b, head.length+s_byte.length, tail.length);
		
		String result_s = new String(result_b);
		System.out.print("HEX : ");
		for (byte b : result_b){
			System.out.print("0x"+Integer.toHexString(b).toUpperCase()+ " ");
		}
		
		System.out.println();
		
		System.out.println("ASCII: " + result_s);
		System.out.println("(CR LF는 공백이라서 표시 안됨)");
	}
	
    static String calcLRC(String s) {
        int sum = 0;
        
        int len = s.length();
        for(int i=0; i<len; i=i+2) {
        	//String을 1byte씩 잘라 Integer로 변환 한 값을 전부 더한다.
        	String subS = s.substring(i, i+2);
        	sum += Integer.parseInt(subS, 16);
        }
        
        //2's complement 수행
        sum = (((sum & 0xff) ^ 0xff) + 0x01);
        
        //상위 4bit, 하위 4bit로 자른다.
        int lrcH = sum >> 4;
        int lrcL = sum & 0xf;
        
 
        //자른 Bit를 다시 ASCII(HexaString 형태)로 변환한다.
        String res = Integer.toHexString(lrcH) + Integer.toHexString(lrcL);       
        return res.toUpperCase();
    }
   
  
}

Test 결과

 

제발 이거 보고 짜길 바란다..ㅎ;;;

Pycharm에서 새로운 아나콘다 가상환경을 설정하고, 인터프리터로 설정한 후에 opencv-python을 쓰기 위해

 

$ pip install opencv-python

을 친 결과....

Fatal error in launcher: Unable to create process using..?

이건 또 무슨 에러이길래.... 하고 인터넷을 찾아보니

 

PATH 설정이 잘못(or 안되)있어서 발생하는 문제라고 한다.

 

PATH가 무슨 역할을 하느냐... 예를 들어 pip이라는 명령어를 사용하고 싶다면 pip을 실행시켜줄 실행파일을 찾아야한다... 하지만 PATH가 설정이 잘못되어 있을 경우 이 실행파일을 찾을 수 없으므로 위와 같은 오류가 발생하는 것...

 

어떻게 해결을 하냐...

 

일단 나는 anaconda 가상환경에서 환경 설정을 수행할 것이다. 그러려면 터미널이 아나콘다에 접속을 해야 된다.

 

즉, 가장 먼저 아나콘다에 접속을 해줄 수 있게 PATH 설정을 해줄 것이다.

 

Anaconda3 PATH 설정(환경 변수 설정

1. 아래와 같이 시스템 환경 변수 편집 창으로 들어간다.

2. 아래와 같이 들어가준다.

3. 아래와 같이 3개의 PATH를 추가한다.

4. 그리고 컴퓨터를 껐다 켜주면 PATH가 반영이 된다.

 


자... 이제 PATH 설정이 모두 끝이 났다.

 

그럼 다시 내가 개발할 pycharm 프로젝트에 들어가서 아나콘다에 접속을 해보자.

 

Pyhcharm 터미널에서

$ conda activate [가상환경명]

을 입력하면 해당 가상환경으로 접속이 되면서 명령어 입력창 앞쪽에 (opencv)라고 뜬 것을 확인할 수 있다.

 

여기서 다시 pip을 입력하면?

pip list는 현재 가상환경에 깔려있는 패키지 정보를 출력하는 명령어이다.

오류 없이 pip 명령어가 잘 출력되는 것을 확인할 수 있다.


참고로 이러한 환경변수를 설정하는 귀찮은 짓을 안하려면 처음 아나콘다를 설치할 때

All Users로 선택하면 알아서 PATH가 추가될 것이다..ㅎㅎ

pytube는 pip에 두가지 종류가 있다. pytube와 pytube3

 

만약 이 두가지를 같이 설치하게 될 경우 충돌이 발생한다.

 

따라서 하나만 설치해야 된다.

 

pytube

 

pytube3

사용 가능한 python 버전을 보면 pytube3의 경우 3.6/3.7/3.8에서 가능하다고 한다.

나는 python3.7을 사용하기 때문에 두 개 다 사용할 수 있겟지만 나중을 생각해서 조금더 버전이 높은 놈을 선택했다.

 

#-*- coding:utf-8 -*-
#Youtube download module is pytube3, pytube.
#pytube3 is available to python 3.6/7/8
#if you download both, happen to abort
from pytube import YouTube

yt = YouTube('http://youtube.com/watch?v=9bZkp7q19f0')

print(yt.streams.filter())

그러고 테스트를 해보니 성공적으로 수행 완료

 

내가 만났던 에러 : ImportError: cannot import name 'quote' from 'pytube.compat'

와... 이거 쳐봐도 진심 1도 안나오더라...ㅋㅋㅋ

 

이렇게 문제가 발생하였을 땐

$ pip uninstall pytube
$ pip uninstall pytube3
$ pip insatll pytube3

모두 지우고 다시 패키지를 설치하면 잘 동작한다.

서론

PLC의 데이터를 이용하여 PC의 동영상을 켜고 끄는 동작을 구현해보려고 한다.

 

참 많은 우여곡절이 있었다...

 

처음엔 라즈베리파이의 omxplayer를 이용하여 구현해보려고 했는데.... omxplayer-wrapper는 2.7버전에서 구동테스트를 하고, modbus는 3.5버전에서 구동 테스트를 하고....ㅋ

 

동영상 플레이어를 어떻게 제어할까 고민하다가 subprocess를 이용하여 다른 프로세스에 명령을 보내는(?) 방법을 찾아보던 중 pytube라는 패키지에 눈이 돌아갔다.

(나도 왜 돌아갔는지는 모르겠지만..ㅋ)

 

그런데 pytube를 아무리 설치해도 안되더라.... 자꾸 quote가 없다고 에러가 뜨는데 인터넷을 아무리 뒤져봐도 이 에러에 대한 원인을 찾을 수 없었다....ㅋㅋㅋ

 

그러던 중 내가 환경 설정을 아주 x같이 했다는 것 역시 깨닫게 되었고.... 오늘 python 가상환경에 대해서 한 걸음 더 나아갈 수 있었다.


본론

각설하고, 결국 최종적으로 결정한 나의 테스트 환경은 이러하다.

  • PC
    • ubuntu 16.04 LTS
    • python 3.7 with anaconda
    • python-vlc
    • pyserial
  • PLC
    • xg5000
    • LS 산전 제품

참 우여곡절이 많았다....

 

오늘 회사에 라즈베리파이를 들고가서 이것저것 테스트 해보려고 하다가 바보같이 micro sd카드를 뽀개먹었다. 그것도 케이스에 끼우다가...ㅋ

 

당연히 동작은 맛이 갔고... 나는 오늘 무엇을 해야하는가 고민하다가....

 

rasbian과 같은 리눅스 계열인 ubuntu를 이용하여 한 번 테스트를 진행해봐야겠다라고 결심을 하고 실행에 옮기기 시작했다.

 

그러던 중 서론에서 이야기 했던 pytube관련 issue를 만나게 되었고 삽질을 오질나게 했다는 것...ㅋ


아나콘다3 가상환경 설정

아나콘다..... python을 이용하여 프로젝트를 진행하다보면 다양한 패키지들을 활용하게 되는데 이러한 패키지 설치 환경을 구분해주는 일종의 프레임워크를 만들 수 있는 도구라고 볼 수 있을 것 같다.

 

나는 pytube라는 패키지 때문에 ubuntu에 아나콘다를 깔게 되었다.

 

처음에는 그냥 내가 프로젝트 해봤자 이 환경에서 얼마나 하겠어... 하고 그냥 초기의 ubuntu 환경에서 작업을 진행하려고 했다.

 

하지만 ubuntu 16.04 LTS에는 python 2.7 버전과 python 3.5 버전이 이미 깔려있더라....

pip으로 패키지를 깔면 2.7에 저장되고, pip3로 패키지를 깔면 3.5에 저장이 되고.... 설상가상으로 pytube는 계속 인터넷에 쳐도 안나오는 오류 메세지를 내보내고..ㅋㅋ

 

그래서 ubuntu에 아나콘다를 깔았다.

 

ubuntu에 아나콘다 까는 법

간단하다.

1. 아나콘다3 홈페이지에서 linux 버전의 아나콘다3를 다운받는다.(~~~~~.sh 파일임)

2. 다운받은 쉘 파일을 설치해준다.

$ bash Anaconda3-2019.03-Linux-x86_64.sh

3. 아나콘다에서 설치한 환경변수를 반영하기 위해서 bashrc를 읽는다(터미널을 껐다 켜도 된다)

$ source ~/.bashrc

4. 가상환경을 만든다.

아래는 conda에서 자주 쓰이는 명령어들이다. 진짜 많이 쓰이더라.

※ 설치
$ conda create -n [가상환경 이름] [파이썬 버전]
$ conda create -n py356 python=3.5.6

※ 제거
$ conda remove -n [가상환경 이름] --all
$ conda remove -n py356 --all
 
※ 확인
$ conda info --envs

※ 실행
$ conda activate [가상환경 이름]
$ conda activate py356

※ 종료
$ conda deactivate

5. 환경 변수를 설정을 하고 나면 다음부 ubuntu의 터미널을 키게 되면 앞에 저런게 붙는다. 아나콘다3의 root 환경이라는 의미다.

 

저기서 conda activate를 수행하면 (base)가 [가상환경 이름]으로 바뀌는 것을 알 수 있다.

 

추가적으로 나는 ubuntu에 pycharm을 직접 깔아서 개발을 진행하려고 생각했다


pycharm-community 설치하는 법

너무 간단하다.

※ 설치
$ sudo apt install snapd snapd-xdg-open

$ sudo snap install pycharm-community --classic

※ 실행
$ pycharm-community

pycharm 가상환경 설정하는 법

1. 아나콘다 가상환경 생성(가상환경 이름 : test, python 버전 = 3.7)

$ conda create -n test python=3.7

 

2. 가상환경 생성 여부 확인 

$  conda info --envs

잘 생성 되었다


3. pycharm-community 실행(시간 조금 걸림... 아 겁나 느리네)

$  pycharm-community


4. Configure -> Settings 클릭

 

5. Project Interpreter -> 톱니바퀴 아이콘 -> Show All

 

6. 아까 만든 가상환경 설정에서 python interpreter 설정

 

7. 가상환경 선택

 

8.  새 프로젝트 생성

 

9. 아까 만든 인터프리터 설정 후 create

9.1 만약 인터프리터를 변경하고 싶다면 생성된 프로젝트-> Setting에서도 변경 가능

10. 생성된 프로젝트에서 pycharm에 존재하는 Terminal을 켜게 되면 프로젝트 생성 가능

 

11. 해당 터미널에서 설치하고 싶은 패지키 설치

 

12. 설치된 pip 패키지 정보들 확인

$ pip list

 

 

12.1 Setting(Ctrl + Alt + S) -> Project Interpreter에서도 확인 가능


다음으로는 vlc를 설치해서 프로젝트를 진행해보려 한다.

python-vlc로 동영상 제어하기

※ vlc player  설치
$ sudo apt-get install vlc

※ python-vlc  설치
$ pip install python-vlc

▼ 예제 코드 입력(파일 위치 수정이 필요할 경우 수정)

#-*- coding:utf-8 -*
#https://www.videolan.org/developers/vlc/doc/doxygen/html/group__libvlc__video.html#gabdbb7230cc3db78e73070ce10e679315

import vlc
import time
class Player():
    def __init__(self):
        self._instance = vlc.Instance(['--video-on-top', '--input-repeat=-1'])  #동영상 재생 반복
        self._player = self._instance.media_player_new()
        self._player.set_fullscreen(True)	#동영상을 전체화면으로 실행

    def play(self, path):
        media = self._instance.media_new(path)
        self._player.set_media(media)
        self._player.play()

    def stop(self):
        self._player.stop()

p=Player()
p.play('./videos/01.mp4')
time.sleep(5)
p.stop()
p.play('./videos/02.mp4')
time.sleep(5)

잘 동작하는 것을 확인할 수 있다.

 

▼ 간단하게 이런 식으로도 가능

import vlc
import time

player = vlc.MediaPlayer("./videos/01.mp4")
vlc.libvlc_set_fullscreen(player, True)
player.play()
time.sleep(5)

가상환경에서 외부 usb Serial 포트 연결

을 하기 위해서는 ubuntu에서 현재 사용자 계정이 Serial Port로 접근을 할 수 있게 권한을 설정해주어야 함.

root 계정으로 로그인
$ sudo su

passwd 입력

※ /dev 폴더로 이동
$ cd /dev


※ tttyUSB0 권한 등록
$ chown [사용자 계정 이름] ttyUSB0
chown mistive ttyUSB0

 

'PLC' 카테고리의 다른 글

[plc&pc 연동] nodejs를 이용한 modbus RTU 구현  (0) 2020.03.17


신경 써야 할 것

1. XBee S2C 모델은 공급 전압이 2.1V~3.6V이다. 즉, 라즈베리파이 같이 5V 입출력을 지닌 장치와 연결하여 사용하기 위해서는 추가적인 장치가 필요하다.


2. XBee의 초기 설정을 위해서 DIGI사의 XCTU라는 프로그램이 필요하다. (다운로드 받는데 심하게 느리다.)


3. 



0: 너 이거 왜하는데?

PLC와 PC 통신을 하려고 그런다.

1: 어떻게 할껀데?

일단 PLC와 PC 통신 하기 전에 usb to rs232 Converter를 이용해서 Tx로 쏜걸 Rx에서 받는 걸 파이썬(pyserial)으로 구현할꺼다.



서론 : 시리얼 통신이 뭔데?



시리얼 통신이 무엇일까?


단어를 이해하기 위해서는 각 단어의 의미를 먼저 알아보는게 좋다.


통신은 지나가는 유치원생한테 물어봐도 대충 무슨 의미인지는 알겠고... 시리얼... 시리얼...


시리얼? 이미지 검색결과


이 시리얼을 의미하는 것은 절대 아닐테고....(죄송합니다)


시리얼은 Serial. 즉 직렬이란 의미이다.


직렬의 반대는 그럼 병렬일텐데...


A컴퓨터와 B컴퓨터가 서로 통신한다고 쳤을 때 병렬은 한 번에 여러개의 데이터를 전송할 수 있다. 왜냐? 병렬이니깐

하지만 병렬로 A컴퓨터와 B컴퓨터를 연결하면 돈이 많이들겠다. 왜냐?? 세상에 공짜는 없으니깐 말이다. 한 번에 여러 개의 데이터를 보낸다는 의미는 말그대로 전선이 많이 들어갔다는 소리다.


반대로 직렬은 그럼... 선이 한 개이고 이 하나의 선만으로 데이터를 전송하는 것이다.


자.... 그럼 하나의 선만으로 어떻게 데이터를 주고 받을 것인가?


컴퓨터는 알다시피 머리가 상당히 나빠 0이랑 1밖에 모른다. 당연히 전선이 하나만 연결이 되어있으니깐 두 컴퓨터간에 약간의 약속이 필요하다. 그게 바로 baud rate(보레이트)라고 하는 놈이다.


만약 A컴퓨터가 0000 1111 0101 1010 이라는 데이터를 보내고 싶어한다. 그런데 B라는 놈은 000 011 110 101 101 0 과 같은 식으로 데이터를 받았다고 치자. 그럼 두 놈이 원활한 의사소통이 되겠는가? 당연히 될 수가 없다.


그래서 일반적으로 serial 통신을 할 때는 baud rate를 통신하려는 기기끼리 서로 맞춰준다.



그리고 또 솔직히 말하면 serial 통신이 전선이 딱 하나만 있는 건 아니다. 송신선과 수신선이 서로 나뉘어져 있어 송신과 수신을 동시가 할 수 있는 것도 있고(full duplex) 송신선과 수신선이 하나로 이루어져 있어 한 번에 송신과 수신을 할 수 없는 놈도 있다.(half duplex)


또한 단순히 전압의 차이만을 이용하여 회로 구성이 간단하지만 노이즈에 좀 취약한 가장 기본적인 시리얼 통신인 RS-232가 있고, 232에서는 송신선을 하나의 전선으로 구성했다면, 2개의 전선을 이용하여 그 2개의 전선의 전위차를 가지고 통신하는 RS-422, 485와 같은 Serial 통신 방법 등 다양하게 있다.


각 시리얼 통신의 차이를 구글에 검색해보면 정말 잘 나와있는 글들이 많으니 시리얼 통신 설명은 여기까지 하겠다.


준비물



1. RS233 to usb converter
2. Jump Cable(female - female)
3. 컴퓨터

만 있으면 테스트 해볼 수 있다.


준비 과정


1. 위의 그림처럼 점프 케이블을 이용해 RS232의 Rx와 Tx를 연결시켜준다.



2. ["Win + X" -> 장치관리자]에서 "USB Serial Converter"가 있는지 확인한다.


3. 만약 연결이 안되었거나, 앞에 느낌표가 있으면 온라인으로 드라이버 찾기 하면 자알 찾아준다.


4. 처음 연결해서 드라이버를 설치하면 컴퓨터를 껐다 켜야 제대로 인식한다.



5. 위의 사진처럼 USB Serial Port의 번호(COM3)를 확인한다.


6. pip install pyserial을 이용하여 pyserial을 설치해주고


7. 아래의 코드를 한 번 집어넣어본다.

import serial

ser = serial.Serial("COM3", 115200, timeout = 1)
while True:
print("insert op :", end=' ')
op = input()
ser.write(op.encode())
print("R: ", ser.readline())

if op is 'q':
ser.close()


8. 참고로 COM 포트 번호는 사람마다 다 다를 수 있다.


9. 출력 결과는 이와 같이 Rs232에서 출력한 값을 받아오는 것이다. 


10. 앞에 b는 byte 표시다. byte 타입의 문자열로 보내는 이유는(op.encode()) 유니코드로 보내면 에러 떠서 못받는다.




























+ Recent posts