https://m.blog.naver.com/kji9653/221900031533
위에 링크에 잘 나와있어서 퍼왔음.
※ 기초
▶ 1 byte는 8비트로 되어있다.
- 1111 1111 -> 8비트로 표현 가능한 최대 크기
- 0000 0000 -> 8비트로 표현 가능한 최소 크기
▶ 1byte는 256가지 표현가능하다.
▶ ASII코드는 127가지가 있다.
- 1 byte로 ASCII코드 하나씩 충분히 표현 가능하다.
https://ko.wikipedia.org/wiki/ASCII
▶ 진수 변환
- 0 또는 1로 표현되면 2진수이다. Binary Code(바이너리)라고 한다.
- 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 로 표현되면 10진수이다. Demical(데미칼)이라고 한다.
- 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , A , B , C , D , E , F 로 표현되면 16진수이다.
HEXADEMICAL(헥사)이라고 한다.
https://m.blog.naver.com/icbanq/221727893563
변환방법은 위 링크에 잘 나와있어서 퍼왔음.
▶ 2진수 -> 16진수
0000 1110의 2진수가 있다.
0000 / 1110의 4비트식 나눠서 계산하면 편하게 16진수를 구할 수 있다.
0 0 0 0 / 1 1 1 0
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
(2^3 * 0)+(2^2 * 0)+(2^1*0)+(2^0 * 0) / (2^3 * 1)+(2^2 * 1)+(2^1*1)+(2^0 * 0)
결론 : 0 / E -> 0E 헥사값이 됌
(^ 는 제곱을 의미함)
▶ 프로토콜(Protocol)
- 내가 상대방에게 데이터를 보내면 상대방이 무엇이 어떻게 어떤건지를 받는지를 알 수 없는 상태라면 내가 아무리 데이터를 보내도 상대방은 전혀 그 데이터의 내용을 모른다. 그래서 상대방이랑 나랑 같은 방식으로 보내고 받는다면 무슨말인지 알아 들을 수 있을 것이다. 그게 바로 프로토콜이다. (고오오오오급진 말로는 통신규약이다.)
※ 이제 한번 코딩을 해보자.
준비물 : C# , ls-ig5a 인버터 , ls-ig5a-manual , visual studio 2019 community
https://www.ls-electric.com/ko/product/view/P01187
ls-ig5a제품설명은 위 링크에 가면 잘 나와있다.
우선적으로 인버터랑 시리얼 포트를 연결해야된다.
위의 인버터에서 S+,S- 를 RS485 USB 컨버터에 D+,D-로 연결을 해준다.
(S+ → D+ 연결 , S- → D- 연결)
그다음 비쥬얼 스튜디오 2019를 켠다. 그다음은 순서대로 하면 됌(여기선 C#으로 함)
ls-ig5a 통신 메뉴얼을 보겠다.
11장 RS-485통신을 누른다.
스크롤을 내리다보면 통신선 연결 부분이 있다. 인버터에 설정하는 방법은 메뉴얼 보면 있으니 찾아서 RS-485통신에 맞게 설정해주자.
여기서 사용할 통신 프로토콜은 LS BUS 이다.
위의 그림에서 1번은 LS BUS 프로토콜이다.
"" 로 표시된것은 아스키값 , h가 붙은건 헥사값으로 넣으면 된다.
ⓐ ENQ -> 05h -> 1byte 의 뜻은 프로토콜 처음 시작이 ENQ이며 데이터 길이는 1byte이고 05h 는 05라는 hex값으로 넣으라는 의미이다.
ⓑ 국번-> "01" -> 2bytes 뜻은 프로토콜 두번째 시작이 국번이며 데이터 길이는 2bytes이고 "01"의 ASCII문자 값을 넣으라는 의미이다. 시리얼 통신은 1byte식 데이터를 송수신하기 때문에 "01"이 "0"-> 1byte에 저장 , "1" -> 1byte에 저장 하기 때문에 2byte 데이터 길이로 정해진다. 국번은 데이터를 송신할 때 필요한 인버터에게 송신을 하려고 할때 쓰인다. 만약 최대 31개의 인버터가 연결되어있으면 데이터는 다 송신 되지만 정확히 해석하는 인버터는 국번이 맞는 인버터만 해석을 한다. 나머지는 에러 수신을 한다.
ⓒ CMD-> "R" -> 1byte 는 위에 나와있듯이 명령어이다. R은 읽기 W는 쓰기 X는 모니터 등록요구 Y는 모니터 등록 실행. ASCII문자 값을 넣는다.
ⓓ 번지 -> "3000" -> 4bytes는 명령을 내릴 주소(Adress)이다. ASCII문자 값을 넣는다. 메뉴얼 아래에 보면 주소가 나와있다.
ⓔ 번지개수 -> "1"~"8" = n -> 1byte 주소안에 명령을 내릴 데이터의 총 갯수이다. 한꺼번에 명령을 8개나 내릴 수 있다. ASCII문자 값을 넣는다.
ⓕ SUM ->"A7" -> 2bytes 는 국번 , CMD, 번지 , 번지개수 를 더한값 즉 체크썸을 만든다. ASCII문자 값을 넣는다.(체크썸이란 프로토콜의 신뢰성 즉 데이터가 정확한가에 대해서 한번더 검사하기 위한 것이다.)
예를들어 만드는 방법
국번 | CMD | 번지 | 번지개수 | SUM합계 | |||||
"01" | "R" | "3000" | "1" | ||||||
"0" | "1" | "R" | "3" | "0" | "0" | "0" | "1" | ||
SUM | 30h(헥사) | 31h(헥사) | 52h(헥사) | 33h(헥사) | 30h(헥사) | 30h(헥사) | 30h(헥사) | 31h(헥사) | 1A7h(헥사) |
SUM = 30h + 31h + 52h + 33h + 30h + 30h + 30h + 31h = 1A7h 로 나온다. 하지만 2byte로 적용시켜서 1A7중 1은 없애고 "A7만 넣도록 한다."이제 코딩으로 들어가보자
WinForm하나 만들었다. 이것저것 붙여놨음. C#은 SerialPort 편하게 쓰게 만들어 놨으니 옮겨서 WinForm창에 넣으면 밑에 serialPort1이 생길것이다.
※정회전 통신을 보내 보겠다. 아래를 보도록 하자
ⓐ foreach(var key in System.IO.Ports.SerialPort.GetPortNames())
{
COMList.Items.Add(key);
}
Winform에서 국번설정 밑에 있는 txtbox가 COMlist이다. 실행시 디바이스에 열려있는 COMPORT를 가져온다.
ⓑ private void button1_Click(object sender, EventArgs e) 는 Winform에 COM연결이라는 버튼이 있다. 그것이다. 시리얼 포트 열기전 설정을 하고 열어준다.
설정하는 PortName , BaudRate, DataBits , Parity, StopBits는 장치관리자에 연결된 COMPort 속성이 가면 있다.
초기 설정값과 컴포트의 설정하는 값이 동일해야된다. 그래야 시리얼 포트가 열린다.
serialPort1.PortName -> 현재 연결된 COM이름으로 설정
serialPort1.BaudRate -> 비트 / 초랑 맞추며 된다.
serialPort1.Databits -> 데이터 비트랑 맞추면 된다.
serialPort1.Parity -> 패리티랑 맞추면 된다.
serialPort1.StopBits -> 정지 비트랑 맞추면 된다.
데이터를 보내보자.
메뉴얼에 보면 인버터에게 쓰기를 요청하는 프로토콜이 있다. 여기에서 아까 위에서 봤뜻이 형태는 같지만 "데이터"라는게 추가가된다. 똑같이 데이터를 가공해서 붙여주기만 하면 된다.
여기에선 강제로 하드코딩으로 값을 넣어줬다.
(테스트를 할 목적이기 때문에 통신만 된다면 데이터 가공은 능력껏 하면 되기 때문이다.)
여기서 주의할 점은 " " 안에 들어가는 문자들은 헥사값이다. 고로 문자화 된 헥사값을 넣는것이다. 중요하다.
ⓐ 쓰기 요구에 보면 byte가 1개 1데이터만 보내면 총 16바이트가 필요하다. 그래서 위에 바이트 메모리를 16개로 만들어줬다.
ⓑ ENQ는 05h이기 때문에 헥사값으로 넣어줬다.
ⓒ 국번은 1번지로 인버터에서 세팅 했기 때문에 "01"을 넣어야되지만, 국번 바이트수는 2byte를 넣게 되어있다. 그래서 "0" , "1"을 따로 넣는다. 그리고 "0"은 문자값이기 때문에 byte로 변환시켜줘야된다. C#은 문자값을 byte로 변환해주는 함수가 있다. 이것을 써서 변환해준다.(참고로 "0에 대한 아스키 코드의 16진수값을 넣어도되고 1도 마찬가지이다.)
ⓓ CMD는 쓰기요구이기 때문에 "W" 값이 들어간다. 아스키코드표를 보면 "W"의 16진수 값이 0x57이다. 이걸 넣어줬다.
ⓔ 번지는 위에 사진에서 보면 파라미터 코드 리스트에 보면 Address가 있을것이다. 운전지령의 Address는 0x0006이다. 그래서 번지자리에 "0","0","0","6"이 들어간다.
ⓕ 번지개수는 1~8개까지 가능한데 "1"을 넣어준이유는 위의 번지를 0006 하나밖에 안넣었기 때문에 1개로 넣어줬다.
ⓖ 데이터는 "0","0","0","2"가 들어간다. 왜 그런지 아래의 사진을 보자.
운전지령의 R/W를 보면 BIT 0 : 정지(0->1)이 되어있다. 이말이 무슨뜻이냐면 1byte는 8bit다. 8bit의 0번째 인덱스 즉 0000 0000 -> 0000 0001 가 되면 정지 지령의 데이터가 된다는 말이다. 이걸 토대로 정방향은 0000 0010 정방향 운전 데이터가 되고, 역방향은 0000 0100 역방향 데이터가 되겠다.
2진수를 16진수로 변환하면 0x00이 정지 , 0x02가 정방향 , 0x04가 역방향이 되겠다. 그러나 위에선 데이터가 4byte로 넣어야되기 때문에 0x0000 , 0x0002 , 0x0004로 되어야된다. (0x00 이나 0x0000이나 똑같음) 여기에선 정방향으로 운전을 하려고 하니 "0","0","0","2"를 넣어줬다.
ⓗ SUM은 체크썸 값을 넣어준다. 체크썸 값은 ENQ ,SUM , EOT를 제외한 나머지의 값들의 합이다. 고로 국번,CMD,번지,번지개수,데이터 들의 합이다. 다 더하면 625의 정수값(10진수)을 얻을 수 있는데 이것을 HEX로 변환하면 271의 값을 얻을 수 있다. 하지만 체크썸의 값은 2byte고 앞에서 봤듯이 뒤의 자리 2자리만 남기도록 하고있다. 그래서 "7","1"을 넣어줬다.
ⓘ EOT는 0x04이여서 0x04를 넣어줬다.
ⓙ 마지막으로 bBuffer배열에 바이트를 차례대로 넣어주고 serialPort1.Write(bBuffer , 0 , bBuffer.Length) 를 넣어주면 된다. 뒤에 0이랑 bBuffer.Length는 버퍼의 크기를 설정한다고 생각하면 된다. 0에서 버퍼의 최대크기를 넣는다.
이제 주파수를 넣어보자.
주파수를 넣어야되기 때문에 위와 동일한 쓰기 프로토콜로 넣어준다.
ⓐ ENQ ~ 쓰기 까지는 위와 동일하다.
ⓑ 주파수의 지령번지는 0x0005이다.
ⓒ 번지 개수도 지령번지 1개를 보내기 때문에 위와 동일하다.
ⓓ 데이터는 십진수 2000의 값에 대한 16진수 데이터 0x07D0의 값이 들어간다. 위에서 설명 했다 시피 문자화 된 헥사값을 넣어야 인버터에서 해석을 해 주파수 20.00이 들어간다. 왜 20.00이 들어가냐면 아래의 그림을 보자.
주파수의 단위가 0.01 hz이고 여기 인버터는 00.00hz ~ 60.00 hz를 지원하기 십진수 1을 넣으면 0.01hz가 증가될것이다. 고로 십진수 2000을 넣으면 인버터에서 20.00hz로 변환이 된다. (주파수를 이것저것 넣어 봤는데 최소 00.50hz이상부터 입력이 가능하더군요...)
ⓔ 체크썸도 위와 동일하다. 그래서 값을 구해서 뒤에 두자리만 구하면 "8","9"가 나온다.
이제 쓰기는 끝이났다. 어떻게 넣어야 될지를 알기 위해 하드코딩으로 강제로 넣었지만 이제 생각해서 코딩을 짜보길 바란다. 끗
'펌웨어프로그래밍 > 경기인력개발원 다닐 때 공부한 것' 카테고리의 다른 글
펌웨어 천천히 공부해봐야 될 것 (0) | 2022.07.15 |
---|---|
플로우차트 웹에서 사용하는 사이트 (0) | 2022.05.06 |
용어정리 (0) | 2022.05.02 |
아두이노 DHT 11 센서 메뉴얼보고 해석해보기 (0) | 2022.02.18 |