MODBUS 통신
MODBUS 읽기, 쓰기 관련 함수들은 rlModbus 에 정의되어있습니다.작성하는 mask에서 이 함수들을 사용하기 위해서는 slot 에 주석처리되어 있는 다음 구문의 주석처리를 제거하시기 바랍니다.
//extern rlModbusClient modbus; //Change if applicable
modbus 객체를 만들어 주는 구문입니다.
읽기 함수
- readShort()
Word Data 읽기 - readByte()
Byte Data 읽기 - readBit()
Bit Data 읽기
먼저, 워드형(Word type) 데이터를 읽는 방법에 대해 알아보죠. readShort()함수는 다음과 같이 정의되어 있습니다.
offset, number 인자를 이용하여 정수형 데이터를 얻고 있습니다. 이 함수의 소스 코드를 확인해 보죠.
Modbus 데몬을 만들때, 정의한 rlsharedMemory 에서 offset 과 number를 이용하여 데이터를 읽어 들입니다.
rlsharedMemory에서 원하는 데이터를 읽기 위한 함수의 정의입니다.
이 함수를 내부를 대강 둘러보면 rlsharedMemory (Modbus 통신데이터 저장 파일)에 있는 데이터를 mutex 방식을 이용하여 데이터를 읽어내는 코드를 포함하고 있습니다.
너무 깊숙이 들어온 것 같은데, 여하튼 rlsharedmemory에서 원하는 데이터를 가지고 오는 군요.
readShort() 함수 인자 중 offset은 베이스 주소 라고 생각해도 무방합니다. 실제 rlSharedMemory에서 읽어 오는 값의 위치는 offset + (number*2) 이며, 이 위치의 값을 정수형으로 읽어들이죠.
rlSharedMemory에 저장되어 있는 내용들은 기본적으로 Byte입니다.
예를 들어 50 번지의 내용을 읽고 싶다면
modbus.readShort(50, 0 );
modbus.readShort(45, 5 );
modbus.readShort(40, 10 );
이런 식으로 표현할 수 있습니다. 전체적으로 동일한 50번째 위치에서(정확하게는 x2) 두개의 byte를 읽어와 정수형 데이터를 반환해 줍니다.
써넣고 보니, 무슨 말을 하려고 하는 건지 잘 모르겠다.
잠깐, modbus 데몬 정의에 대해 알아보죠.
modbus를 정의할 때 cycle 구문을 한개만 사용한다면 별의미가 없지만, 두 개인 경우는 어떤식으로 구성해야 할까요. 또, 워드형만 읽지않고, 코일 형(bit)도 읽어들이고 싶다면.
한번 살펴보죠.
사이클 1개로 워드형 데이터만 읽어들이면 될 경우 아래와 같은 형태로 쓰면 됩니다.
Cycle1, 한개로 Address 0 ~ 28 까지 29개의 데이터를 읽어들이는 구문입니다.
이것을 두개의 Cycle로 읽어 들인다면.
Cycle1에서 0 ~9 까지 10개의데이터를 읽어들이고, cycle2에서 10 ~ 28 까지 19개의 데이터를 읽어들이고 있습니다.
이때 주의할 점은 cycle2의 시작 주소(start_adr)입니다. 이 값을 기준으로 shm파일(rlSharedMemory)의 저장 위치가 결정되는 것 같습니다. 연속으로 저장하기 위해 이 값을 cycle1 기준으로 맞춰주는 것이 중요합니다.
그림 1. Modbus Daemon 동작상태 |
그림 1과 같은 경우가 modbus 데몬이 통신기기와 정상 연결된 상태입니다. 만약 정상 연결이 되지 않았다면 ret 값이 -1 로 나타납니다. 즉 읽어들인 데이터가 없다
그림 1은 stat_adr=0, num_register=1 즉 , 1 word 데이터를 읽어 들이는 경우 입니다. 1 word는 2byte 이므로 ret값에 2가 나타납니다.
그림2. Modbus Daemon 동작상태 (Cycle=1) |
그림 2는 stat_ad=0, num_register=29로 설정한 경우 입니다. 29x2=58byte 따라서 ret 값이 58입니다.
그림 3. Modbus Daemon 동작상태(Cycle =2) |
자, 그럼 간단한 GUI 화면을 작성하여 Arduino에서 넘어온 데이터를 확인해 보았습니다.
그림 4. pvbrowser 실행 화면 |
지금까지는 cycle에서 function 3을 이용하여 word 데이터 만 읽어 들였습니다. 이 경우 만약 word 데이터를 이용하여 bit 처리(INPUT/OUTPUT)을 하려고 하면 많이 번거롭죠. 어떻게 해야 할까요. Single Coil 형태로 읽어 들이면 간단히 해결할 수 있습니다.
아두이노에서 32개의 INPUT Coil (32/16 = 2 Word), 32개의 OUTPUT Coil (32/16 = 2 Word)값을 입력받는다고 생각해보죠,
우선, 아두이노 modbus 통신용 데이터를 다음과 같이 정의하였습니다.
uint16_t au16data[29];
아두이노 Modbus 통신 데이터 au16data[0], au16data[1]은 Input Coil, au16data[2], au16data[3]은 Output Coil, 22 개는 측정데이터 혹은 내부 설정데이터, 나머지 3개는 mobus 상태로 구성하겠습니다.
au16data[0] <--Input coil (Bit 16)
au16data[1] <--Input coil (Bit 16)
au16data[2] <--Output coil (Bit 16)
au16data[3] <--Output coil (Bit 16)
au16data[4] <--Data (Word)
|
au16data[26] <--Data (Word)
au16data[27] <--Modbus Status (Word)
au16data[28] <--Modbus Status (Word)
au16data[29] <--Modbus Status (Word)
이 경우 Cycle은 어떻게 설정해야 할 까요.
저는 이런 식으로 정의했습니다.
그림 5. Modbus daemon 실행 화면 |
Modbus daemon 작동상태를 확인해 보니 ret 값이 4, 4, 50 반복되고 있습니다. 정확히 동작하는 것 같군요.
자, 그럼 이것을 이용해 다음 GUI를 조금 더 수정해 보았습니다.
QImage 위젯을 이용하여 LED 형태를, 대강 만든 후, 비트 값을 검사하여 1인 경우 파란색, 0인경우 흰색으로 나타나게 해 보았습니다. 잘 작동하는 군요.
GUI 제어용 slot 코드입니다.
Arduino 소스 코드 입니다.
추가적인 것은 직접 해보시기 바랍니다.
댓글 없음:
댓글 쓰기