사용자 도구

사이트 도구


products:mpaino_24a24r

문서의 이전 판입니다!


MPAINO-24A24R

MPAINO Series는 CPU 모듈과 디지털 입력 및 디지털 출력 모듈이 결합된 조립형 산업용 아두이노입니다.
아날로그 입력/출력, 온도센서 입력, 고속펄스 출력 모듈을 옵션에서 추가할 수 있습니다.
선택한 I/O모듈과 옵션 모듈이 한 개의 제품으로 조립되어 출고됩니다. 사용자가 모듈을 추가/제거할 수 없습니다.

아날로그 입력 X모듈 상세 안내 — DIP 설정·배선·프로그램 예제 → PT100 입력 F모듈 상세 안내 — 결선·채널·프로그램 예제 → 아날로그 출력 Y모듈 상세 안내 — DIP 설정·배선·프로그램 예제 → 고속펄스 출력 K모듈 상세 안내 — 채널·Timer·프로그램 예제 →

MPAINO-24A24R는 디지털 입력 24점과 릴레이 출력 24점을 제공합니다.

Arduino IDE(Arduino C/C++) 또는 MPINO STUDIO 2(Arduino C/C++ & 래더로직)로 프로그램할 수 있습니다.

MPAINO Arduino IDE 설정표에서 MPAINO-24A24R에 사용할 보드 이름, 연결 방법과 첫 입출력 번호를 확인할 수 있습니다.






MPAINO-24A24R 커넥터 안내

제품 사양서

구분 개수 접점명 사양
보드 - - ATmega2560
Arduino Mega 2560 호환
전원 - 전원전압 DC 12~24V
DC 24V 사용 시 0.5A 이상 전원공급장치 권장
디지털 입력 24점
(절연)
모듈 0: D0~D7
모듈 1: D8~D15
모듈 2: D16~D23
동작 입력 전압: DC 0~40V
HIGH 인식 전압: DC 5V 이상
4점/1COM
NPN·PNP 입력 지원
릴레이 출력 24점
(절연·무전압 접점)
모듈 0: D64~D71
모듈 1: D72~D79
모듈 2: D80~D87
연결 전압: DC 0~30V 또는 AC 0~250V
최대 허용전류: 5A/1점, 8A/1COM
4점/1COM
고속 입력·인터럽트 2점
(절연)
D0(INT0), D1(INT1) / COM0 최대 8kHz
디지털 입력과 공유
2점
(비절연)
SDA(D20·INT2), SCL(D21·INT3) 최대 50kHz
4.7kΩ 풀업 내장
I²C 통신과 공유
통신 채널 1채널
(비절연)
I²C SDA(D20), SCL(D21)
Wire 사용
RS-232 Serial1 사용
RS-485 Serial2 사용
UART CPU 모듈의 TXD·RXD 단자
Serial3 사용
메모리 - Flash 256KB
SRAM 8KB
EEPROM 4KB

디지털 입력

처음 결선할 때는 디지털 입력 한 채널 확인 순서를 함께 보십시오. →

모듈 그룹 단자 입력 구성 단자대 및 결선 예시
모듈 0 COM0
COM1
D0~D3
D4~D7
절연 디지털 입력 8점
D0·D1은 INT0·INT1 겸용
MPAINO-24A24R 디지털 입력 단자대와 NPN·PNP 결선
모듈 1 COM0
COM1
D8~D11
D12~D15
절연 디지털 입력 8점
모듈 2 COM0
COM1
D16~D19
D20~D23
절연 디지털 입력 8점

디지털 입력은 포토커플러로 절연되어 있으며 DC 5~24V의 NPN 또는 PNP 방식 스위치·센서를 연결할 수 있습니다. 입력 방식은 각 모듈의 COM 단자 결선 방향으로 선택합니다.

  • 입력 단자에 DC 5~24V가 들어오는 구성: 해당 COM을 GND에 연결합니다.
  • 입력 단자에 GND가 들어오는 구성: 해당 COM을 DC 5~24V에 연결합니다.

예제 프로그램 · 디지털 입력

입력 논리 번호 0~23의 상태를 digitalRead()로 읽습니다. 현재 ILOGICS 코어는 단자에 인쇄된 기존 물리 D번호를 내부에서 변환합니다.

void setup() {
  Serial.begin(115200);
}
 
void loop() {
  for (uint8_t ch = 0; ch < 24; ++ch) {
    Serial.print(ch);
    Serial.print(": " );
    Serial.println(digitalRead(ch));
  }
  delay(500);
}

관련 내장 명령어

함수 예제 · 연속 판독 필터: IdigitalRead()

함수 원형

bool IdigitalRead(uint8_t pin, uint8_t samples);

IdigitalRead(0, 5)는 입력 0을 5회 연속 판독합니다. 모두 HIGH 또는 모두 LOW일 때 상태를 갱신하고, 값이 섞이면 이전 상태를 유지합니다. 시간 기준의 채터링 필터와 달리 판독 사이에 지연을 넣지 않습니다.

void setup() {
  Serial.begin(115200);
}
 
void loop() {
  const bool inputOn = IdigitalRead(0, 5);  // 입력 0을 5회 연속 판독해 안정된 상태 반환
  Serial.println(inputOn ? F("입력 0 ON") : F("입력 0 OFF"));
  delay(200);
}

함수 예제 · 채터링 방지: Ibounce(), IbounceOn(), IbounceOff()

함수 원형

bool Ibounce(uint8_t pin, uint32_t debounceTime);
bool IbounceOn(uint8_t pin, uint32_t debounceTime);
bool IbounceOff(uint8_t pin, uint32_t debounceTime);

입력 0을 세 가지 필터로 비교합니다. 반환값은 필터 처리된 ON/OFF 상태입니다.

  • Ibounce(0, 30): ON과 OFF 모두 30ms 이상 안정된 뒤 반영합니다.
  • IbounceOn(0, 500): ON만 500ms 지연하고 OFF는 즉시 반영합니다.
  • IbounceOff(0, 500): OFF만 500ms 지연하고 ON은 즉시 반영합니다.

각 함수는 같은 핀에서도 독립적으로 동작합니다. 필터를 loop()마다 실행하고 결과만 200ms 간격으로 표시합니다.

unsigned long lastPrint = 0;
 
void setup() {
  Serial.begin(115200);
}
 
void loop() {
  const bool stable = Ibounce(0, 30);  // 입력 0의 ON/OFF 채터링을 30ms로 필터링
  const bool onDelayed = IbounceOn(0, 500);  // 입력 0의 ON만 500ms 지연, OFF는 즉시 반영
  const bool offDelayed = IbounceOff(0, 500);  // 입력 0의 OFF만 500ms 지연, ON은 즉시 반영
 
  if (millis() - lastPrint >= 200) {
    lastPrint = millis();
    Serial.print(F("Ibounce: "));
    Serial.print(stable);
    Serial.print(F(", IbounceOn: "));
    Serial.print(onDelayed);
    Serial.print(F(", IbounceOff: "));
    Serial.println(offDelayed);
  }
}

함수 예제 · 입력 토글: Ialt()

함수 원형

void Ialt(bool input, bool &state_var);

Ialt(input, state)는 입력이 OFF에서 ON으로 바뀔 때마다 state를 반전합니다. 입력 0을 한 번 누르면 출력 64가 ON, 다시 누르면 OFF가 되며 누르고 있는 동안은 유지됩니다. 예제는 Ibounce(0, 30)로 채터링을 걸러 Ialt()에 전달합니다. outputOn은 호출 사이에 유지되는 전역 변수이며, Ialt()가 이 값을 직접 변경합니다.

bool outputOn = false;
 
void setup() {
  Serial.begin(115200);
  digitalWrite(64, LOW);
}
 
void loop() {
  const bool previous = outputOn;
  const bool inputOn = Ibounce(0, 30);  // 입력 0의 ON/OFF 채터링을 30ms로 필터링
  Ialt(inputOn, outputOn);  // 입력이 OFF→ON일 때 outputOn 반전
  digitalWrite(64, outputOn ? HIGH : LOW);
 
  if (outputOn != previous) {
    Serial.println(outputOn ? F("출력 64 ON") : F("출력 64 OFF"));
  }
}

릴레이 출력

처음 결선할 때는 릴레이 출력 한 채널 확인 순서를 함께 보십시오. →

모듈 그룹 출력 단자 접점 구성 단자대 및 결선 예시
모듈 0 COM2
COM3
D64~D67
D68~D71
릴레이 출력 8점
4점/1COM
MPAINO-24A24R 출력 단자대와 부하 결선
모듈 1 COM2
COM3
D72~D75
D76~D79
릴레이 출력 8점
4점/1COM
모듈 2 COM2
COM3
D80~D83
D84~D87
릴레이 출력 8점
4점/1COM

릴레이 출력은 무전압 접점입니다. 출력이 ON되면 해당 출력 단자와 COM 단자가 물리적으로 연결되므로 DC와 AC 부하를 제어할 수 있습니다. 부하 전원은 COM 쪽에 별도로 연결합니다.

항목 정격
연결 전압 DC 0~30V 또는 AC 0~250V
최대 허용전류 5A/1점
COM당 최대 허용전류 8A/1COM

예제 프로그램 · 릴레이 출력

입력 0~23을 출력 64~87에 대응시킵니다. HIGH이면 무전압 릴레이 접점이 ON됩니다.

void setup() {
  for (uint8_t ch = 0; ch < 24; ++ch) digitalWrite(64 + ch, LOW);
}
 
void loop() {
  for (uint8_t ch = 0; ch < 24; ++ch) {
    digitalWrite(64 + ch, digitalRead(ch));
  }
}

인터럽트·고속 입력

단자 구성 최대 입력 주파수 함께 사용할 수 없는 기능 엔코더 결선
D0(INT0), D1(INT1) / 모듈 0 COM0 절연 입력 8kHz YK·Y2K·K2·Y3·Y4 옵션 구성 MPAINO-24A24R I2C 단자대와 엔코더 결선
SDA(D20·INT2), SCL(D21·INT3) 비절연 입력, 4.7kΩ 풀업 내장 50kHz I²C 통신

엔코더는 SDA(D20)를 A상, SCL(D21)을 B상으로 사용하여 연결할 수 있습니다. SDA·SCL을 엔코더 또는 인터럽트 입력으로 사용하면 같은 단자에서 I²C 통신을 동시에 사용할 수 없습니다.

예제 프로그램 · 펄스 카운트

I²C 단자의 SDA(D20)는 4.7kΩ 풀업 입력입니다. 이 예제는 I²C 통신과 동시에 사용하지 않습니다. MPAINO 보드 패키지의 digitalPinToInterrupt() 인수 2는 디지털 입력 2가 아니라 SDA에 배정된 인터럽트 논리 번호입니다. SDA가 HIGH에서 LOW로 바뀌는 FALLING 에지를 계수합니다. 소프트웨어 ISR 예제이며 최대 주파수에서 무손실을 보장하지 않습니다.

#include <util/atomic.h>
 
static_assert(digitalPinToInterrupt(2) == 3, "SDA interrupt mapping");
volatile uint32_t pulseCount = 0;
void onPulse() { ++pulseCount; }
 
void setup() {
  Serial.begin(115200);
  attachInterrupt(digitalPinToInterrupt(2), onPulse, FALLING);
}
 
void loop() {
  uint32_t count;
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { count = pulseCount; }
  Serial.println(count);
  delay(500);
}

예제 프로그램 · 엔코더 입력

I²C 단자의 SDA(D20)는 4.7kΩ 풀업 입력입니다. 이 예제는 I²C 통신과 동시에 사용하지 않습니다. MPAINO 보드 패키지의 digitalPinToInterrupt() 인수 2는 디지털 입력 2가 아니라 SDA에 배정된 인터럽트 논리 번호입니다. SDA에 A상, SCL에 B상을 연결하고 A상 하강 시 B상이 HIGH이면 증가, LOW이면 감소합니다. 방향은 A·B상 연결에 따라 바뀝니다. SCL은 디지털 모듈 논리 번호와 겹치므로 실제 핀 상태를 직접 읽습니다.

#include <util/atomic.h>
 
static_assert(digitalPinToInterrupt(2) == 3, "SDA interrupt mapping");
volatile int32_t position = 0;
 
void onEncoder() {
  // 디지털 모듈 논리 번호와 겹치므로 실제 SCL 핀을 직접 읽음
  const bool bHigh = (*portInputRegister(digitalPinToPort(SCL)) & digitalPinToBitMask(SCL)) != 0;
  if (bHigh) ++position;
  else --position;
}
 
void setup() {
  Serial.begin(115200);
  attachInterrupt(digitalPinToInterrupt(2), onEncoder, FALLING);
}
 
void loop() {
  int32_t value;
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { value = position; }
  Serial.println(value);
  delay(500);
}

통신과 프로그램 업로드

기능 Arduino 객체 단자·핀 상대 기기 결선
프로그램 업로드·모니터링 Serial 다운로드 포트 MPAINO-24A24R 통신 커넥터와 상대 기기 결선
RS-232 Serial1 CPU 모듈 RS-232 단자
RS-485 Serial2 CPU 모듈 RS-485 단자
UART Serial3 CPU 모듈 TXD·RXD 단자
I²C Wire SDA: D20, SCL: D21

RS-232, RS-485, UART 채널에서는 Modbus RTU Master·Slave 내장 명령어와 LS산전 Cnet 내장 명령어를 사용할 수 있습니다.

예제 프로그램 · 기본 통신

Serial(115200bps)과 RS-232(Serial1, 9600bps, 8N1) 사이에서 문자를 전달합니다. 각 포트 예제는 독립 실행합니다.

// USB 다운로드 포트의 Serial 모니터 ↔ RS-232 Serial1
void setup() {
  Serial.begin(115200);
  Serial1.begin(9600);  // 상대 기기도 9600 bps, 8-N-1 설정
}
 
void loop() {
  if (Serial.available() && Serial1.availableForWrite()) {
    Serial1.write(Serial.read());
  }
  if (Serial1.available() && Serial.availableForWrite()) {
    Serial.write(Serial1.read());
  }
}

Serial(115200bps)과 RS-485(Serial2, 9600bps, 8N1) 사이에서 문자를 전달합니다. 각 포트 예제는 독립 실행합니다.

// USB 다운로드 포트의 Serial 모니터 ↔ RS-485 Serial2
void setup() {
  Serial.begin(115200);
  Serial2.begin(9600);  // 상대 기기도 9600 bps, 8-N-1 설정
}
 
void loop() {
  if (Serial.available() && Serial2.availableForWrite()) {
    Serial2.write(Serial.read());
  }
  if (Serial2.available() && Serial.availableForWrite()) {
    Serial.write(Serial2.read());
  }
}

Serial(115200bps)과 UART(Serial3, 9600bps, 8N1) 사이에서 문자를 전달합니다. 각 포트 예제는 독립 실행합니다.

// USB 다운로드 포트의 Serial 모니터 ↔ UART Serial3
void setup() {
  Serial.begin(115200);
  Serial3.begin(9600);  // 상대 기기도 9600 bps, 8-N-1 설정
}
 
void loop() {
  if (Serial.available() && Serial3.availableForWrite()) {
    Serial3.write(Serial.read());
  }
  if (Serial3.available() && Serial.availableForWrite()) {
    Serial.write(Serial3.read());
  }
}

예제 프로그램 · I²C 통신

SDA·SCL의 I²C 장치 주소를 검색합니다. 같은 단자를 사용하는 펄스·엔코더 예제와 동시에 실행하지 않습니다.

#include <Wire.h>
 
void setup() {
  Serial.begin(115200);
  Wire.begin();
  Wire.setClock(100000);
}
 
void loop() {
  uint8_t found = 0;
  for (uint8_t address = 0x08; address <= 0x77; address++) {
    Wire.beginTransmission(address);
    const uint8_t result = Wire.endTransmission();
    if (result == 0) {
      Serial.print(F("I2C: 0x"));
      if (address < 16) Serial.print('0');
      Serial.println(address, HEX);
      found++;
    }
  }
  Serial.print(F("Devices: "));
  Serial.println(found);
  delay(3000);
}

예제 프로그램 · Modbus RTU 통신

관련 내장 명령어

함수 예제 · Modbus RTU Slave: ImodbusRTUMem(), ImodbusRTUAdr(), ImodbusRTUInit(), ImodbusRTU()

함수 원형

void ImodbusRTUMem(uint16_t m_size, uint16_t d_size);
void ImodbusRTUAdr(uint16_t m_offset, uint16_t d_offset);
void ImodbusRTUInit(HardwareSerial& serialPort, uint8_t slaveId, long baudrate);
void ImodbusRTU();

입력 0 상태를 M[0], 동작 시간(초)을 D[0]에 넣어 상대 기기에서 읽습니다. RS-485(Serial2), 국번 1, 9600bps, 8N1로 설정하고, M[0]은 FC01·시작 주소 0·1비트, D[0]은 FC03·시작 주소 0·1워드로 읽습니다. 주소는 실제 전송 주소(0부터) 기준입니다. 통신 함수는 loop()마다 호출하며 출력은 제어하지 않습니다.

M과 D는 코어가 제공하는 공유 전역 메모리입니다. 이 스케치는 단독 실행하며, 다른 프로토콜과 함께 사용할 때는 메모리를 중복 할당하지 않습니다.

unsigned long lastPrint = 0;
bool memoryReady = false;
 
void setup() {
  Serial.begin(115200);
  ImodbusRTUMem(8, 8);  // M 8비트와 D 8워드 메모리 할당
  ImodbusRTUAdr(0, 0);  // M과 D의 통신 시작 주소를 0으로 설정
  ImodbusRTUInit(Serial2, 1, 9600);  // RS-485를 국번 1, 9600bps로 시작
  memoryReady = (M != nullptr && D != nullptr);
  if (!memoryReady) Serial.println(F("Memory allocation failed"));
}
 
void loop() {
  if (!memoryReady) return;
  M[0] = digitalRead(0);
  D[0] = (uint16_t)(millis() / 1000UL);
  ImodbusRTU();  // 수신한 Modbus RTU 요청 처리
 
  if (millis() - lastPrint >= 1000) {
    lastPrint = millis();
    Serial.print(F("M[0]: "));
    Serial.print(M[0]);
    Serial.print(F(", D[0]: "));
    Serial.println(D[0]);
  }
}

함수 예제 · Modbus RTU Master: ImodbusRTUmasterInit(), ImodbusRTUmaster()

함수 원형

void ImodbusRTUmasterInit(HardwareSerial& serialPort, long baudrate, uint8_t config);
uint8_t ImodbusRTUmaster(HardwareSerial& serialPort, uint8_t slaveId, uint8_t functionCode, uint16_t address, uint16_t quantity, uint16_t* data, uint16_t timeoutMs = 100);

RS-485(Serial2)로 상대 슬레이브의 홀딩 레지스터 1개를 1초마다 읽습니다. 상대 기기는 국번 1, 9600bps, 8N1, FC03·실제 시작 주소 0으로 준비합니다. 응답은 received[0]에 저장하며 성공한 경우에만 표시합니다. 오류 코드는 16진수로 표시합니다. 위 슬레이브 예제와는 별도 스케치이며, M/D 메모리 대신 수신 배열을 사용합니다.

unsigned long lastRequest = 0;
uint16_t received[1];
 
void setup() {
  Serial.begin(115200);
  ImodbusRTUmasterInit(Serial2, 9600, SERIAL_8N1);  // RS-485를 Modbus 마스터로 시작
}
 
void loop() {
  if (millis() - lastRequest < 1000) return;
  lastRequest = millis();
  const uint8_t result = ImodbusRTUmaster(Serial2, 1, 3, 0, 1, received, 200);  // 국번 1의 주소 0에서 1워드 읽기, 제한 200ms
 
  if (result == IMODBUS_RTU_SUCCESS) {
    Serial.print(F("Register 0: "));
    Serial.println(received[0]);
  } else {
    Serial.print(F("Modbus error: 0x"));
    Serial.println(result, HEX);
  }
}

예제 프로그램 · LS산전 Cnet 통신

관련 내장 명령어

함수 예제 · LS산전 Cnet SLave: ICnetMem(), ICnetAdr(), ICnetInit(), ICnet()

함수 원형

void ICnetMem(uint16_t m_size, uint16_t d_size, uint16_t r_size = 100);
void ICnetAdr(uint16_t m_offset, uint16_t d_offset, uint16_t r_offset = 0);
void ICnetInit(HardwareSerial& serialPort, uint8_t slaveId, long baudrate);
void ICnet();

입력 0 상태를 M[0], 동작 시간(초)을 D[0]에 넣어 HMI에서 읽습니다. 상대 기기는 LS산전 Cnet, RS-232, 국번 1, 9600bps, 8N1로 설정합니다. 비트는 %MX00000(M[0]), 워드는 %DW0(D[0])을 읽습니다. 통신 함수는 loop()마다 호출하며 출력은 제어하지 않습니다.

M·D·R은 코어가 제공하는 공유 전역 메모리이며, 이 예제는 R을 사용하지 않습니다. Modbus 예제와는 단독 실행하며, 다른 프로토콜과 함께 사용할 때는 메모리를 중복 할당하지 않습니다.

unsigned long lastPrint = 0;
bool memoryReady = false;
 
void setup() {
  Serial.begin(115200);
  ICnetMem(8, 8, 0);  // M 8비트와 D 8워드 할당, R은 사용하지 않음
  ICnetAdr(0, 0, 0);  // M과 D의 통신 시작 주소를 0으로 설정
  ICnetInit(Serial1, 1, 9600);  // RS-232를 국번 1, 9600bps로 시작
  memoryReady = (M != nullptr && D != nullptr);
  if (!memoryReady) Serial.println(F("Memory allocation failed"));
}
 
void loop() {
  if (!memoryReady) return;
  M[0] = digitalRead(0);
  D[0] = (uint16_t)(millis() / 1000UL);
  ICnet();  // 수신한 LS Cnet 요청 처리
 
  if (millis() - lastPrint >= 1000) {
    lastPrint = millis();
    Serial.print(F("M[0]: "));
    Serial.print(M[0]);
    Serial.print(F(", D[0]: "));
    Serial.println(D[0]);
  }
}

옵션 모듈

출고 시 해당 옵션 모듈이 포함된 제품에서 사용하는 예제입니다. 예제에 표시한 모듈 구성과 실제 출고 구성을 일치시킵니다.

예제 프로그램 · 아날로그 입력 (X 모듈 장착 시)

X 모듈 1개를 실제 장착하고 Analog Input Module → X를 선택한 구성입니다. analogRead(0~3)은 첫 X 모듈의 ADS1118 원시값(0~32767)을 읽습니다. 채널별 DIP와 배선을 입력 신호에 맞춥니다.

void setup() {
  Serial.begin(115200);
}
 
void loop() {
  for (uint8_t ch = 0; ch < 4; ++ch) {
    Serial.print(ch);
    Serial.print(": " );
    Serial.println(analogRead(ch));
  }
  delay(500);
}

관련 내장 명령어

함수 예제 · 입력 범위 환산: IanalogRead(), IanalogReadf()

함수 원형

int32_t IanalogRead(uint8_t ch, int32_t min, int32_t max);
float IanalogReadf(uint8_t ch, float min, float max);

X 모듈의 채널 0을 0~5V, 채널 1을 전류 입력 모드로 설정한 예제입니다. 두 함수는 ADC 입력을 지정한 min~max 범위로 환산합니다. IanalogRead()는 소수부를 버린 정수, IanalogReadf()는 실수를 반환합니다. 채널 0의 0~5V 입력을 0~100%와 전압으로 각각 표시합니다. 채널 1의 0~20mA 입력은 0~20 범위를 지정하여 실제 전류로 읽습니다.

void setup() {
  Serial.begin(115200);
}
 
void loop() {
  const int32_t percent = IanalogRead(0, 0, 100);  // 0 입력을 0~100% 정수로 환산
  const float voltage = IanalogReadf(0, 0.0f, 5.0f);  // 0 입력을 0~5V 실수로 환산
  const float current = IanalogReadf(1, 0.0f, 20.0f);  // 1 입력을 0~20mA 실수로 환산
  Serial.print(F("0: "));
  Serial.print(percent);
  Serial.print(F(" %, "));
  Serial.print(voltage, 2);
  Serial.print(F(" V, 1: "));
  Serial.print(current, 2);
  Serial.println(F(" mA"));
  delay(500);
}

함수 예제 · 4~20mA 범위 환산: IanalogRead2(), IanalogRead2f()

함수 원형

int32_t IanalogRead2(uint8_t ch, int32_t min, int32_t max);
float IanalogRead2f(uint8_t ch, float min, float max);

X 모듈의 채널 0을 0~5V, 채널 1을 전류 입력 모드로 설정한 예제입니다. 채널 1에 연결한 4~20mA 센서 입력을 사용자 범위로 환산합니다. IanalogRead2(채널 1, 0, 100)는 4mA를 0%, 20mA를 100%로 변환한 정수를 반환합니다. IanalogRead2f(채널 1, 4.0f, 20.0f)는 전류를 실수로 반환합니다. 약 3.6mA 미만은 두 함수 모두 ANALOG_READ2_ERROR(65535), 약 3.6~4mA는 지정한 최솟값을 반환합니다.

void setup() {
  Serial.begin(115200);
}
 
void loop() {
  const int32_t percent = IanalogRead2(1, 0, 100);  // 1의 4~20mA를 0~100% 정수로 환산
  const float current = IanalogRead2f(1, 4.0f, 20.0f);  // 1의 4~20mA를 전류 실수값으로 환산
  if (percent == ANALOG_READ2_ERROR ||
      current == (float)ANALOG_READ2_ERROR) {
    Serial.println(F("1: 4-20mA input error"));
  } else {
    Serial.print(F("1: "));
    Serial.print(percent);
    Serial.print(F(" %, "));
    Serial.print(current, 2);
    Serial.println(F(" mA"));
  }
  delay(500);
}

함수 예제 · 이동 평균: analogReadAvg(), analogRead2Avg()

함수 원형

int32_t analogReadAvg(uint8_t ch, uint8_t samples);
int32_t analogRead2Avg(uint8_t ch, uint8_t samples);

X 모듈의 채널 0을 0~5V, 채널 1을 전류 입력 모드로 설정한 예제입니다. analogReadAvg(채널 0, 5)는 채널 0의 ADC 원시값(0~32767)을, analogRead2Avg(채널 1, 5)는 채널 1의 4~20mA 보정값(4mA=0, 20mA=32767)을 이동 평균으로 반환합니다. 최근 호출에서 읽은 정상값을 최대 5개까지 누적해 평균하며, 한 번에 5회 읽는 함수가 아닙니다. samples는 최대 20입니다. analogRead2Avg()는 약 3.6mA 미만 입력에서 ANALOG_READ2_AVG_ERROR(-1)를 반환합니다.

void setup() {
  Serial.begin(115200);
}
 
void loop() {
  const int32_t voltageAvg = analogReadAvg(0, 5);  // 최근 0 ADC 값 최대 5개의 이동평균
  const int32_t currentAvg = analogRead2Avg(1, 5);  // 최근 1의 4~20mA 보정값 최대 5개의 이동평균
  Serial.print(F("0 ADC average: "));
  Serial.print(voltageAvg);
  Serial.print(F(", 1 4-20mA average: "));
  if (currentAvg == ANALOG_READ2_AVG_ERROR) {
    Serial.println(F("input error"));
  } else {
    Serial.println(currentAvg);
  }
  delay(500);
}

예제 프로그램 · NTC 온도센서 입력 (X 모듈 장착 시)

X 모듈 1개, Analog Input Module → X 구성에서 채널 0을 NTC 모드로 설정합니다. analogRead(0)으로 원시값을 먼저 확인합니다.

void setup() {
  Serial.begin(115200);
}
 
void loop() {
  Serial.println(analogRead(0));
  delay(500);
}

관련 내장 명령어

함수 예제 · NTC 온도 변환: ntcRead(), ntcReadf()

함수 원형

int ntcRead(uint8_t ch);
float ntcReadf(uint8_t ch);

X 모듈 채널 0을 NTC 모드로 설정하고 NTC 3950 10kΩ 센서를 연결합니다. ntcRead()는 섭씨 온도×10 정수, ntcReadf()는 섭씨 실수를 반환합니다. 범위를 벗어난 입력은 -40~120°C 끝값으로 제한되므로 단선 판정 함수로 사용하지 않습니다.

void setup() {
  Serial.begin(115200);
}
 
void loop() {
  const int temp10 = ntcRead(0);  // X 채널 0의 섭씨 온도×10
  const float tempC = ntcReadf(0);  // X 채널 0의 섭씨 온도 실수
  Serial.print(temp10);
  Serial.print(", " );
  Serial.println(tempC, 1);
  delay(500);
}

예제 프로그램 · PT100 온도센서 입력 (F 모듈 장착 시)

관련 내장 명령어

함수 예제 · PT100 입력값 읽기: pt100Read()

함수 원형

int pt100Read(uint8_t ch);

F 모듈 1개를 실제 장착하고 Temperature Sensor Input Module → F를 선택합니다. 0~3은 첫 F 모듈 채널입니다. F 모듈 채널 0~3의 입력값을 Serial 모니터에 표시합니다.

void setup() {
  Serial.begin(115200);
}
 
void loop() {
  for (uint8_t ch = 0; ch < 4; ++ch) {
    const int value = pt100Read(ch);  // F 모듈의 해당 채널 입력값 읽기
    Serial.print(ch);
    Serial.print(": " );
    Serial.println(value);
  }
  delay(500);
}

예제 프로그램 · 아날로그 출력 (Y 모듈 장착 시)

Y 모듈 1개를 실제 장착하고 Analog Output Module → Y를 선택합니다. analogWrite(0~2, 값)의 값은 0~65535입니다. 채널 0에 중간값 32768을 출력하며 출력 전압·전류 범위는 모듈 DIP 설정에 따릅니다.

void setup() {
 
}
 
void loop() {
  analogWrite(0, 32768);
  delay(500);
}

관련 내장 명령어

함수 예제 · 출력 범위 환산: IanalogWrite(), IanalogWritef()

함수 원형

void IanalogWrite(uint8_t ch, int32_t min, int32_t max, int32_t value);
void IanalogWritef(uint8_t ch, float min, float max, float value);

Y 모듈 채널 0에 정수 기준 50%, 채널 1에 실수 기준 25%를 출력합니다. min·max는 사용자 값의 범위이며 전기적 출력 모드는 모듈 DIP가 결정합니다.

void setup() {
 
}
 
void loop() {
  IanalogWrite(0, 0, 100, 50);  // Y 채널 0에 50% 출력
  IanalogWritef(1, 0.0f, 100.0f, 25.0f);  // Y 채널 1에 25% 출력
  delay(500);
}

예제 프로그램 · PWM 출력 (K 모듈 장착 시)

K 모듈 1개를 실제 장착하고 High-Speed Pulse Output Module → K를 선택하며 Y 모듈은 None입니다. Arduino analogWrite()는 20~25, 내장 PWM 계열은 0~5, GPIO 제어는 130~135를 사용합니다. 첫 K 출력에 약 50% 듀티를 출력합니다.

void setup() {
 
}
 
void loop() {
  analogWrite(20, 128);
  delay(500);
}

관련 내장 명령어

함수 예제 · 듀티값 지정: PWM()

함수 원형

void PWM(uint8_t pin, uint16_t val, bool onDutybit16 = false);

K 모듈 1개, Y 모듈 없음, High-Speed Pulse Output Module → K 구성입니다. 논리 채널 0~2는 Timer1, 3~5는 Timer5를 공유하므로 같은 그룹은 같은 주파수를 사용합니다. K 채널 0에 16비트 중간 듀티값 32768을 출력합니다. PWM()의 기본 8비트 범위는 0~255, true 지정 시 0~65535입니다.

void setup() {
  PWM_RESET();  // PWM 타이머를 정지하고 모드 초기화
  PWM(0, 32768, true);  // K 채널 0에 16비트 중간 듀티값 출력
}
 
void loop() {
}

함수 예제 · 주파수·듀티 설정: FDPWM()

함수 원형

void FDPWM(uint8_t pin, int32_t intHz, float Duty);

K 모듈 1개, Y 모듈 없음, High-Speed Pulse Output Module → K 구성입니다. 논리 채널 0~2는 Timer1, 3~5는 Timer5를 공유하므로 같은 그룹은 같은 주파수를 사용합니다. K 채널 0에 1kHz, 50% 듀티를 출력합니다. 별도 FPWM()은 코어에 없으며 FDPWM()을 사용합니다.

void setup() {
  PWM_RESET();  // PWM 타이머를 정지하고 모드 초기화
  FDPWM(0, 1000, 50.0f);  // K 채널 0에 1kHz, 50% 듀티 출력
}
 
void loop() {
}

함수 예제 · 지정 개수 펄스 출력: NPWM_BEGIN(), NPWM()

함수 원형

void NPWM_BEGIN(uint8_t pin, uint32_t intHz, float Duty, uint32_t N);
void NPWM(uint8_t pin);

K 모듈 1개, Y 모듈 없음, High-Speed Pulse Output Module → K 구성입니다. 논리 채널 0~2는 Timer1, 3~5는 Timer5를 공유하므로 같은 그룹은 같은 주파수를 사용합니다. K 채널 0에 1kHz, 50% 펄스 100개를 한 번 출력합니다. NPWM()은 loop()마다 호출하며 delay()를 넣지 않습니다.

void setup() {
  PWM_RESET();  // PWM 타이머를 정지하고 모드 초기화
  NPWM_BEGIN(0, 1000, 50.0f, 100);  // K 채널 0에 1kHz, 50% 펄스 100개 준비
}
 
void loop() {
  NPWM(0);  // 준비한 펄스 출력 진행 및 완료 처리
}

함수 예제 · 채널 출력 정지·재개: PWMOFF()

함수 원형

void PWMOFF(uint8_t pin, bool POff);

K 모듈 1개, Y 모듈 없음, High-Speed Pulse Output Module → K 구성입니다. 논리 채널 0~2는 Timer1, 3~5는 Timer5를 공유하므로 같은 그룹은 같은 주파수를 사용합니다. K 채널 0을 2초 켜고 2초 정지합니다. PWMOFF() 플래그 뒤 FDPWM()을 호출하여 상태를 반영하고 GPIO 번호 130을 LOW로 유지합니다. NPWM()에는 이 정지 플래그가 적용되지 않습니다.

void setup() {
  PWM_RESET();  // PWM 타이머를 정지하고 모드 초기화
}
 
void loop() {
  PWMOFF(0, false);  // K 채널 0 정지 상태 해제
  FDPWM(0, 1000, 50.0f);  // 해제를 반영해 1kHz, 50% 출력 시작
  delay(2000);
 
  PWMOFF(0, true);  // K 채널 0 정지 상태 설정
  FDPWM(0, 1000, 50.0f);  // 정지를 반영해 PWM 출력 연결 해제
  digitalWrite(130, LOW);
  delay(2000);
}

함수 예제 · PWM 타이머 정지·초기화: PWM_RESET()

함수 원형

void PWM_RESET();

K 모듈 1개, Y 모듈 없음, High-Speed Pulse Output Module → K 구성입니다. 논리 채널 0~2는 Timer1, 3~5는 Timer5를 공유하므로 같은 그룹은 같은 주파수를 사용합니다. K 단독 구성의 Timer1·Timer5를 정지·초기화합니다. 채널 0을 2초 출력한 뒤 정지합니다. 같은 타이머를 공유하는 K 출력 전체에 영향을 줍니다.

void setup() {
  PWM_RESET();  // PWM 타이머를 정지하고 모드 초기화
  FDPWM(0, 1000, 50.0f);  // K 채널 0에 1kHz, 50% 듀티 출력
  delay(2000);
  PWM_RESET();  // Timer1·Timer5의 모든 PWM 정지 및 초기화
  digitalWrite(130, LOW);
}
 
void loop() {
}

상태 LED

CPU 모듈의 STATUS LED는 LED_BUILTIN(D128)으로 제어합니다.

예제 프로그램 · 상태 LED

입력 0의 상태를 CPU 모듈 STATUS LED(LED_BUILTIN, 논리 번호 128)에 표시합니다.

void setup() {
 
}
 
void loop() {
  digitalWrite(LED_BUILTIN, digitalRead(0));
}

개발 환경 설정

  1. 컴퓨터와 CPU 모듈의 다운로드 포트를 USB 케이블로 연결합니다.
  2. 장치 관리자에서 다운로드 포트의 COM 번호를 확인합니다.
  3. Arduino IDE의 도구 → 포트에서 확인한 COM 번호를 선택합니다.
  4. 도구 → 보드에서 MPAINO-24A24R(T)을 선택합니다.
  5. Arduino IDE 상단에서 검증(✓)을 누르고 오류가 없으면 업로드(→)를 눌러 프로그램을 전송합니다.

MPAINO 사용설명서 다운로드

외형 치수

항목 치수
제품 폭 109mm
본체 높이 108mm
전체 높이 클립 열림 120.42mm
클립 닫힘 115.16mm
제품 깊이 본체 79mm
단자 포함 최대 83mm
장착 홀 간격 81mm
장착 홀 지름 Ø4mm
DIN 레일 35mm
정면도 측면도
후면도

← MPAINO Series 비교표로 돌아가기

products/mpaino_24a24r.1789445714.txt.gz · 마지막으로 수정됨: 저자 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki