대부분의 자동화 기기에서 모든 입력(스위치, 센서류)는 항상 감시되고 있어야 하며, 해당 입력이 들어왔을때 상응하는 출력이 즉각적으로 나와주어야만 합니다.
이 경우, 기존 C언어 유저들은 외부 인터럽트등을 사용해서 충분히 코딩할 수 있을 것이라고 생각하겠지만, 그보다 훨씬 효율적인 방법이 있습니다.
PLC 라고 불리우는 자동화용 컨트롤러에서 사용하는 방법인데, 모든 I/O를 스캔하면서 빠른 속도로 무한 루핑을 하는 구조입니다.
스캔 루프 실행방식은 모든 포트를 읽고나서, 로직처리를 한뒤, 출력포트에 한꺼번에 전부 반영합니다. 그리고 이 과정을 반복합니다.
C언어는 매우 다재다능한 언어이므로, 충분히 PLC에서 사용하는 스캔 루프 실행방식으로 코딩할 수 있습니다.
모든 입력을 받아서 입력 배열 버퍼 (X[0] ~ X[127])에 저장하고, X배열과 Y배열을 대상으로 로직연산/처리를 한뒤, 출력 배열버퍼 (Y[0]~Y[127])에 있는 내용을 출력모듈에 반영하도록 하면 됩니다.
아래 그림처럼 입력8개, 출력8개가 모두 연결된 상황을 가정하고 아래 소스를 만들었습니다.
이렇게 전부 연결하지 않아도 본 소스는 동작됩니다. 연결하지 않은 I/O모듈에 할당된 배열은 무시하셔도 좋습니다.
이 소스를 ARDUINO IDE로 복사>붙여넣기로 사용하시면 됩니다.
#include "CFMEGA.h" CFNET cfnet; uint8_t X[128]; // Input Coil uint8_t Y[128]; // Output Coil void distribute_value(uint16_t val, uint8_t where) { for (int i = 0; i < 16; i++) { X[where++] = val & 1; val >>= 1; } } void input_proc() { for (int i = 0; i < 8; i++) { distribute_value(cfnet.digitalRead(i), i * 16); } } uint16_t collect_value(uint8_t where) { uint16_t tempV = 0; for (int i = 0; i < 16; i++) { tempV |= (Y[where++] & 1) << i; } return tempV; } void output_proc() { for (int i = 0; i < 8; i++) { cfnet.digitalWrite(i, collect_value(i * 16)); } } void setup() { } void loop() { input_proc(); Y[0] = X[0]; // Main Logic Program output_proc(); }
맨 아래 있는 input_proc와 output_proc 사이에 있는 부분이 바로 로직연산및 처리를 하는 부분인데, 마치 수식처럼 되어 있습니다.
Y[0] = X[0]; // Main Logic Program
이 수식이 바로 PLC에서 사용하는 레더로직을 C언어에서 쓰는 수식형태로 변형시켜 놓은 것입니다.
다음은 OR, AND 상황입니다.
이런식으로 변환하면, 레더로직으로 표현가능한 모든 회로를 C언어 수식으로 구현할 수 있게 됩니다.
이 소스는 여러분의 책임하에 운영하시기 바랍니다. 본 소스가 실제 프로젝트에 적용되었을 경우, 당사는 오류및 사고에 대한 어떠한 책임도 지지 않습니다. 이에 대한 동의가 있을 경우에만 본 소스를 사용하시기 바랍니다. 본 소스에 대한 기술문의는 받고 있지 않습니다. 이점 양해바랍니다.