products:mpino_8a4t_s
차이
문서의 선택한 두 판 사이의 차이를 보여줍니다.
| 양쪽 이전 판이전 판다음 판 | 이전 판 | ||
| products:mpino_8a4t_s [2026/09/07 16:19] – 바깥 편집 127.0.0.1 | products:mpino_8a4t_s [2026/09/15 17:45] (현재) – 바깥 편집 127.0.0.1 | ||
|---|---|---|---|
| 줄 4: | 줄 4: | ||
| Arduino IDE(Arduino C/C++) 또는 MPINO STUDIO 2(Arduino C/C++ & 래더로직)로 프로그램할 수 있습니다. | Arduino IDE(Arduino C/C++) 또는 MPINO STUDIO 2(Arduino C/C++ & 래더로직)로 프로그램할 수 있습니다. | ||
| + | |||
| + | [[: | ||
| + | |||
| + | |||
| + | |||
| + | |||
| {{ : | {{ : | ||
| 줄 24: | 줄 30: | ||
| | ::: | ::: | SRAM | 4KB | | | ::: | ::: | SRAM | 4KB | | ||
| | ::: | ::: | EEPROM | | ::: | ::: | EEPROM | ||
| + | |||
| + | **Markdown 자료:** [[https:// | ||
| + | |||
| ===== 디지털 입력 ===== | ===== 디지털 입력 ===== | ||
| + | [[: | ||
| ^ 단자 ^ Arduino 핀 ^ 입력 구성 ^ 단자대 및 결선 예시 ^ | ^ 단자 ^ Arduino 핀 ^ 입력 구성 ^ 단자대 및 결선 예시 ^ | ||
| | P0~P3 | D0~D3 | 디지털 입력 4점, COM0 공유 | {{: | | P0~P3 | D0~D3 | 디지털 입력 4점, COM0 공유 | {{: | ||
| 줄 35: | 줄 45: | ||
| ==== 예제 프로그램 · 디지털 입력 ==== | ==== 예제 프로그램 · 디지털 입력 ==== | ||
| - | Arduino IDE에서 보드를 **MPINO-8A4R(T)-S**로 선택합니다. 아래 코드는 각각 별도 스케치로 실행합니다. | + | digitalRead()로 P0~P7의 입력 상태를 읽어 200ms마다 시리얼 모니터에 표시합니다. |
| - | + | ||
| - | **기본 예제** | + | |
| - | + | ||
| - | **P0~P7 입력 상태 읽기** | + | |
| - | + | ||
| - | IdigitalRead(pin, | + | |
| <code cpp> | <code cpp> | ||
| 줄 54: | 줄 58: | ||
| Serial.print(pin); | Serial.print(pin); | ||
| Serial.print(' | Serial.print(' | ||
| - | Serial.print(IdigitalRead(pin, 5)); // 5회 판독이 일치하면 상태 갱신 | + | Serial.print(digitalRead(pin)); |
| Serial.print(' | Serial.print(' | ||
| } | } | ||
| 줄 62: | 줄 66: | ||
| </ | </ | ||
| - | **관련 내장함수 · 기본 함수** | + | **관련 내장 |
| - | 함수 | + | === 함수 예제 |
| - | === 함수 | + | **함수 |
| - | ILOGICS 내장 함수: | + | <code cpp> |
| + | bool IdigitalRead(uint8_t | ||
| + | </ | ||
| + | |||
| + | IdigitalRead(0, | ||
| <code cpp> | <code cpp> | ||
| 줄 76: | 줄 84: | ||
| void loop() { | void loop() { | ||
| - | const bool inputOn = IdigitalRead(0, | + | const bool inputOn = IdigitalRead(0, |
| Serial.println(inputOn ? F("P0 ON") : F("P0 OFF" | Serial.println(inputOn ? F("P0 ON") : F("P0 OFF" | ||
| delay(200); | delay(200); | ||
| 줄 82: | 줄 90: | ||
| </ | </ | ||
| + | === 함수 예제 · 채터링 방지: Ibounce(), IbounceOn(), | ||
| - | ===== 트랜지스터 출력 ===== | + | **함수 원형** |
| - | ^ 단자 ^ Arduino 핀 ^ 출력 방식 ^ 최대 정격 ^ 단자대 및 결선 예시 ^ | + | <code cpp> |
| - | | P32 | D32 | SINK 출력 | DC 100V, 1A/1점 | {{: | + | bool Ibounce(uint8_t pin, uint32_t debounceTime); |
| - | | P33 | D33 | SINK 출력 | DC 100V, 1A/1점 | ::: | | + | bool IbounceOn(uint8_t pin, uint32_t debounceTime); |
| - | | P34 | D34 | SINK 출력 | DC 100V, 1A/1점 | ::: | | + | bool IbounceOff(uint8_t pin, uint32_t debounceTime); |
| - | | P35 | D35 | SINK 출력 | DC 100V, 1A/1점 | ::: | | + | </code> |
| - | 트랜지스터 출력은 ON될 때 출력 단자가 V-와 연결되는 SINK 방식입니다. | + | P0 입력을 세 가지 필터로 비교합니다. |
| - | ==== 예제 프로그램 · 트랜지스터 출력 ==== | + | * '' |
| + | * '' | ||
| + | * '' | ||
| - | Arduino IDE에서 | + | 각 함수는 같은 핀에서도 독립적으로 동작합니다. |
| - | **기본 예제** | + | <code cpp> |
| + | unsigned long lastPrint = 0; | ||
| + | |||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | const bool stable = Ibounce(0, 30); // P0의 ON/OFF 채터링을 30ms로 필터링 | ||
| + | const bool onDelayed = IbounceOn(0, | ||
| + | const bool offDelayed = IbounceOff(0, | ||
| + | |||
| + | if (millis() - lastPrint >= 200) { | ||
| + | lastPrint = millis(); | ||
| + | Serial.print(F(" | ||
| + | Serial.print(stable); | ||
| + | Serial.print(F(", | ||
| + | Serial.print(onDelayed); | ||
| + | Serial.print(F(", | ||
| + | Serial.println(offDelayed); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| - | **P0~P3 | + | === 함수 예제 · 입력 |
| - | IdigitalRead(channel, | + | **함수 |
| <code cpp> | <code cpp> | ||
| - | // MPINO-8A4T-S: | + | void Ialt(bool input, bool & |
| + | </code> | ||
| + | |||
| + | Ialt(input, state)는 | ||
| + | |||
| + | <code cpp> | ||
| + | bool outputOn = false; | ||
| void setup() { | void setup() { | ||
| - | | + | |
| - | digitalWrite(32 | + | digitalWrite(32, |
| - | } | + | |
| } | } | ||
| void loop() { | void loop() { | ||
| - | | + | |
| - | digitalWrite(32 | + | const bool inputOn = Ibounce(0, 30); // P0의 ON/OFF 채터링을 30ms로 필터링 |
| + | Ialt(inputOn, | ||
| + | digitalWrite(32, | ||
| + | |||
| + | if (outputOn != previous) { | ||
| + | Serial.println(outputOn ? F("P32 ON") : F("P32 OFF")); | ||
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | **관련 내장함수 · 기본 함수** | ||
| - | 함수 이름을 누르면 설명과 독립 실행 예제가 펼쳐집니다. | + | ===== 트랜지스터 출력 ===== |
| - | === 함수 예제 · digitalWrite() === | + | [[: |
| + | ^ 단자 ^ Arduino 핀 ^ 출력 방식 ^ 최대 정격 ^ 단자대 및 결선 예시 ^ | ||
| + | | P32 | D32 | SINK 출력 | DC 100V, 1A/1점 | {{: | ||
| + | | P33 | D33 | SINK 출력 | DC 100V, 1A/1점 | ::: | | ||
| + | | P34 | D34 | SINK 출력 | DC 100V, 1A/1점 | ::: | | ||
| + | | P35 | D35 | SINK 출력 | DC 100V, 1A/1점 | ::: | | ||
| - | Arduino 기본 함수: digitalWrite(pin, | + | 트랜지스터 |
| + | |||
| + | ==== 예제 | ||
| + | |||
| + | digitalRead()로 읽은 P0~P3 상태를 digitalWrite()로 P32~P35에 출력합니다. | ||
| <code cpp> | <code cpp> | ||
| + | // MPINO-8A4T-S: | ||
| void setup() { | void setup() { | ||
| - | digitalWrite(32, | + | |
| + | | ||
| + | } | ||
| } | } | ||
| void loop() { | void loop() { | ||
| - | | + | |
| - | digitalWrite(32, | + | digitalWrite(32 |
| - | | + | |
| } | } | ||
| </ | </ | ||
| 줄 147: | 줄 202: | ||
| | A6, A7 | NTC 온도센서 입력 | NTC 10kΩ, 3950K | ::: | | | A6, A7 | NTC 온도센서 입력 | NTC 10kΩ, 3950K | ::: | | ||
| + | ==== 예제 프로그램 · 아날로그 입력 ==== | ||
| - | ==== 예제 프로그램 · 아날로그 입력ㆍ온도센서 입력 ==== | + | analogRead()로 A0~A5의 ADC 원시값(0~1023)을 읽어 시리얼 모니터에 |
| - | + | ||
| - | Arduino IDE에서 보드를 **MPINO-8A4R(T)-S**로 선택합니다. 아래 코드는 각각 별도 스케치로 실행합니다. | + | |
| - | + | ||
| - | **기본 예제** | + | |
| - | + | ||
| - | **전압·전류와 NTC 온도 읽기** | + | |
| - | + | ||
| - | IanalogReadf()로 A0·A1은 V(0~5V), A2·A3은 mA(0~20mA), A4·A5는 V(0~10V)를 | + | |
| <code cpp> | <code cpp> | ||
| 줄 164: | 줄 212: | ||
| void loop() { | void loop() { | ||
| - | const uint8_t pins[] = {A0, A1, A2, A3, A4, A5, A6, A7}; | + | const uint8_t pins[] = {A0, A1, A2, A3, A4, A5}; |
| - | for (uint8_t channel = 0; channel < 8; channel++) { | + | for (uint8_t channel = 0; channel < 6; channel++) { |
| Serial.print(' | Serial.print(' | ||
| Serial.print(channel); | Serial.print(channel); | ||
| Serial.print(F(": | Serial.print(F(": | ||
| - | | + | Serial.println(analogRead(pins[channel])); |
| - | Serial.print(IanalogReadf(pins[channel], | + | |
| - | | + | |
| - | } else if (channel < 4) { | + | |
| - | Serial.print(IanalogReadf(pins[channel], 0.0f, 20.0f), 3); | + | |
| - | Serial.println(F(" | + | |
| - | } else if (channel < 6) { | + | |
| - | Serial.print(IanalogReadf(pins[channel], | + | |
| - | Serial.println(F(" | + | |
| - | } else { | + | |
| - | Serial.print(ntcReadf(pins[channel]), | + | |
| - | Serial.println(F(" | + | |
| - | } | + | |
| } | } | ||
| Serial.println(); | Serial.println(); | ||
| 줄 188: | 줄 224: | ||
| </ | </ | ||
| - | **관련 내장함수 · 기본 함수** | + | **관련 내장 |
| - | 함수 | + | === 함수 예제 |
| - | === 함수 | + | **함수 |
| + | |||
| + | <code cpp> | ||
| + | int32_t IanalogRead(uint8_t ch, int32_t min, int32_t max); | ||
| + | float IanalogReadf(uint8_t ch, float min, float max); | ||
| + | </ | ||
| - | ILOGICS 내장 | + | 두 함수는 ADC 입력을 |
| <code cpp> | <code cpp> | ||
| 줄 202: | 줄 243: | ||
| void loop() { | void loop() { | ||
| - | const float voltage = IanalogReadf(A0, | + | |
| - | const float current = IanalogReadf(A2, | + | |
| + | const float current = IanalogReadf(A2, | ||
| Serial.print(F(" | Serial.print(F(" | ||
| + | Serial.print(percent); | ||
| + | Serial.print(F(" | ||
| Serial.print(voltage, | Serial.print(voltage, | ||
| Serial.print(F(" | Serial.print(F(" | ||
| 줄 213: | 줄 257: | ||
| </ | </ | ||
| - | === 함수 예제 · ntcReadf() === | + | === 함수 예제 · 4~20mA 범위 환산: IanalogRead2(), |
| - | ILOGICS 내장 | + | **함수 |
| + | |||
| + | <code cpp> | ||
| + | int32_t IanalogRead2(uint8_t | ||
| + | float IanalogRead2f(uint8_t ch, float min, float max); | ||
| + | </ | ||
| + | |||
| + | A2에 연결한 4~20mA 센서 | ||
| <code cpp> | <code cpp> | ||
| 줄 223: | 줄 274: | ||
| void loop() { | void loop() { | ||
| - | const float temperature = ntcReadf(A6); | + | |
| - | Serial.print(F(" | + | const float current = IanalogRead2f(A2, |
| + | if (percent == ANALOG_READ2_ERROR || | ||
| + | current == (float)ANALOG_READ2_ERROR) { | ||
| + | Serial.println(F(" | ||
| + | } else { | ||
| + | Serial.print(F(" | ||
| + | Serial.print(percent); | ||
| + | Serial.print(F(" | ||
| + | Serial.print(current, | ||
| + | Serial.println(F(" | ||
| + | } | ||
| + | delay(500); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | === 함수 예제 · 이동 평균: analogReadAvg(), | ||
| + | |||
| + | **함수 원형** | ||
| + | |||
| + | <code cpp> | ||
| + | int32_t analogReadAvg(uint8_t ch, uint8_t samples); | ||
| + | int32_t analogRead2Avg(uint8_t ch, uint8_t samples); | ||
| + | </ | ||
| + | |||
| + | analogReadAvg(A0, | ||
| + | |||
| + | <code cpp> | ||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | const int32_t voltageAvg = analogReadAvg(A0, | ||
| + | const int32_t currentAvg = analogRead2Avg(A2, | ||
| + | Serial.print(F(" | ||
| + | Serial.print(voltageAvg); | ||
| + | Serial.print(F(", | ||
| + | if (currentAvg == ANALOG_READ2_AVG_ERROR) { | ||
| + | Serial.println(F(" | ||
| + | } else { | ||
| + | Serial.println(currentAvg); | ||
| + | } | ||
| + | delay(500); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== 예제 프로그램 · 온도센서 입력 ==== | ||
| + | |||
| + | analogRead()로 NTC0(A6)·NTC1(A7)의 ADC 원시값(0~1023)을 표시합니다. 섭씨 온도로 변환하려면 아래 ntcRead()·ntcReadf() 예제를 참고합니다. | ||
| + | |||
| + | <code cpp> | ||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | Serial.print(F(" | ||
| + | Serial.print(analogRead(A6)); | ||
| + | Serial.print(F(", | ||
| + | Serial.println(analogRead(A7)); | ||
| + | delay(1000); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | **관련 내장 명령어** | ||
| + | |||
| + | === 함수 예제 · NTC 온도 읽기: ntcRead(), ntcReadf() === | ||
| + | |||
| + | **함수 원형** | ||
| + | |||
| + | <code cpp> | ||
| + | int ntcRead(uint8_t ch); | ||
| + | float ntcReadf(uint8_t ch); | ||
| + | </ | ||
| + | |||
| + | NTC0(A6)에 연결한 NTC 10kΩ(25℃), | ||
| + | |||
| + | <code cpp> | ||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | const int temperature10 = ntcRead(A6); | ||
| + | | ||
| + | Serial.print(F(" | ||
| + | Serial.print(temperature10); | ||
| + | Serial.print(F(" | ||
| Serial.print(temperature, | Serial.print(temperature, | ||
| Serial.println(F(" | Serial.println(F(" | ||
| 줄 241: | 줄 380: | ||
| D18과 D19는 I²C의 SCL·SDA 기능을 공유합니다. I²C 통신을 사용하는 동안에는 해당 핀을 고속 입력으로 동시에 사용할 수 없습니다. | D18과 D19는 I²C의 SCL·SDA 기능을 공유합니다. I²C 통신을 사용하는 동안에는 해당 핀을 고속 입력으로 동시에 사용할 수 없습니다. | ||
| - | ==== 예제 프로그램 · PWM·고속 입력 ==== | + | ==== 예제 프로그램 · PWM 출력 ==== |
| - | + | ||
| - | Arduino IDE에서 보드를 **MPINO-8A4R(T)-S**로 선택합니다. 아래 코드는 각각 별도 스케치로 실행합니다. | + | |
| - | + | ||
| - | **기본 예제** | + | |
| - | + | ||
| - | **PWM 3채널 출력** | + | |
| - | FDPWM(핀, 주파수Hz, | + | analogWrite()의 0~255 값으로 |
| <code cpp> | <code cpp> | ||
| // MPINO-8A4T-S: | // MPINO-8A4T-S: | ||
| void setup() { | void setup() { | ||
| - | | + | |
| - | | + | |
| - | | + | |
| } | } | ||
| 줄 263: | 줄 396: | ||
| </ | </ | ||
| - | **CLK 펄스 카운트** | + | **관련 내장 명령어** |
| - | CLK(D24)의 상승 에지를 누적합니다. 신호는 DC 0~5V이며 신호원의 GND를 보드 GND에 연결합니다. 다른 입력을 쓰려면 CLK를 DIO, SCL 또는 SDA로 바꿀 | + | === 함수 예제 |
| + | |||
| + | **함수 원형** | ||
| <code cpp> | <code cpp> | ||
| - | # | + | void PWM(uint8_t pin, uint16_t val, bool onDutybit16 = false); |
| + | </code> | ||
| - | volatile uint32_t pulseCount = 0; | + | PWM(pin, val, onDutybit16)은 듀티값을 지정합니다. 기본 8비트는 |
| - | void countPulse() { | + | <code cpp> |
| - | | + | void setup() { |
| + | | ||
| + | PWM(21, 32768, true); | ||
| } | } | ||
| + | void loop() { | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | === 함수 예제 · 주파수·듀티 설정: FDPWM() === | ||
| + | |||
| + | **함수 원형** | ||
| + | |||
| + | <code cpp> | ||
| + | void FDPWM(uint8_t pin, int32_t intHz, float Duty); | ||
| + | </ | ||
| + | |||
| + | FDPWM(pin, intHz, Duty)는 주파수(Hz)와 듀티(%)를 지정합니다. 예제는 PWM0(D21)에 1kHz, 50%를 출력합니다. PWM0~2(D21~D23)는 Timer3를 공유하므로 함께 사용할 때 같은 주파수를 지정합니다. 이 Arduino 코어에는 별도 FPWM() 함수가 없으며, 주파수 지정 50% 출력은 FDPWM(pin, hz, 50.0f)으로 설정합니다. | ||
| + | |||
| + | <code cpp> | ||
| void setup() { | void setup() { | ||
| - | | + | |
| - | // | + | |
| - | | + | |
| } | } | ||
| void loop() { | void loop() { | ||
| - | uint32_t snapshot; | ||
| - | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { | ||
| - | snapshot = pulseCount; | ||
| - | } | ||
| - | Serial.print(F(" | ||
| - | Serial.println(snapshot); | ||
| - | delay(500); | ||
| } | } | ||
| </ | </ | ||
| - | **CLK·DIO 엔코더 방향 판별** | + | === 함수 예제 · 지정 개수 펄스 출력: NPWM_BEGIN(), |
| - | A상은 CLK(D24), B상은 DIO(D25)에 연결하며 1배 카운트합니다. 신호는 DC 0~5V이고 GND를 공통으로 연결합니다. 표시 방향이 반대라면 A·B 결선 또는 증감 방향을 바꿉니다. 32비트 값은 인터럽트를 잠시 막고 읽어 깨진 값이 출력되지 않도록 합니다. | + | **함수 원형** |
| <code cpp> | <code cpp> | ||
| - | #include < | + | void NPWM_BEGIN(uint8_t pin, uint32_t intHz, float Duty, uint32_t N); |
| - | # | + | void NPWM(uint8_t pin); |
| + | </code> | ||
| - | volatile int32_t position = 0; | + | NPWM_BEGIN(pin, |
| - | void readEncoder() { | + | <code cpp> |
| - | | + | void setup() { |
| - | if (digitalRead(DIO) == HIGH) { | + | |
| - | if (position < INT32_MAX) position++; | + | |
| - | | + | |
| - | if (position > INT32_MIN) position--; | + | |
| - | } | + | |
| } | } | ||
| + | void loop() { | ||
| + | NPWM(21); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | === 함수 예제 · 채널 출력 정지·재개: | ||
| + | |||
| + | **함수 원형** | ||
| + | |||
| + | <code cpp> | ||
| + | void PWMOFF(uint8_t pin, bool POff); | ||
| + | </ | ||
| + | |||
| + | PWMOFF(pin, true)는 해당 채널의 정지 상태를 설정하고 false는 해제합니다. 이 제품에서는 설정 직후 PWM() 또는 FDPWM()을 다시 호출해야 출력에 반영됩니다. 예제는 PWM0(D21)의 1kHz 출력을 2초 켜고 2초 끕니다. 정지 때 digitalWrite(21, | ||
| + | |||
| + | <code cpp> | ||
| void setup() { | void setup() { | ||
| - | | + | |
| - | // | + | |
| - | attachInterrupt(digitalPinToInterrupt(CLK), | + | |
| } | } | ||
| void loop() { | void loop() { | ||
| - | | + | |
| - | | + | |
| - | snapshot = position; | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | delay(500); | + | digitalWrite(21, LOW); |
| + | delay(2000); | ||
| } | } | ||
| </ | </ | ||
| - | **관련 내장함수 · 기본 함수** | + | === 함수 |
| - | 함수 | + | **함수 |
| - | === 함수 예제 · FDPWM() === | + | <code cpp> |
| + | void PWM_RESET(); | ||
| + | </ | ||
| - | ILOGICS 내장 함수: FDPWM(pin, frequencyHz, | + | PWM_RESET()은 Timer1·Timer3의 제어 레지스터와 카운터를 초기화하여 해당 타이머 출력을 모두 정지합니다. |
| <code cpp> | <code cpp> | ||
| void setup() { | void setup() { | ||
| - | FDPWM(21, 1000, 50.0f); | + | |
| + | | ||
| + | delay(2000); | ||
| + | PWM_RESET(); | ||
| + | digitalWrite(21, | ||
| } | } | ||
| 줄 346: | 줄 510: | ||
| </ | </ | ||
| - | === 함수 예제 · attachInterrupt() === | ||
| - | Arduino 기본 함수: attachInterrupt(digitalPinToInterrupt(pin), | + | ==== 예제 프로그램 · 펄스 카운트 ==== |
| + | |||
| + | CLK(D24)는 풀업되어 | ||
| <code cpp> | <code cpp> | ||
| 줄 355: | 줄 520: | ||
| volatile uint32_t pulseCount = 0; | volatile uint32_t pulseCount = 0; | ||
| - | void onPulse() { | + | void countPulse() { |
| pulseCount++; | pulseCount++; | ||
| } | } | ||
| 줄 361: | 줄 526: | ||
| void setup() { | void setup() { | ||
| Serial.begin(115200); | Serial.begin(115200); | ||
| - | attachInterrupt(digitalPinToInterrupt(CLK), | + | |
| + | | ||
| } | } | ||
| void loop() { | void loop() { | ||
| - | uint32_t | + | uint32_t |
| ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { | ||
| - | | + | |
| } | } | ||
| - | Serial.println(count); | + | |
| + | Serial.println(snapshot); | ||
| + | delay(500); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== 예제 프로그램 · 엔코더 입력 ==== | ||
| + | |||
| + | 풀업된 CLK(D24)에 A상, DIO(D25)에 B상을 연결합니다. CLK 하강 에지(FALLING)에서 DIO가 LOW이면 증가, HIGH이면 감소하는 1배 계수 예제입니다. 실제 회전 방향은 A·B상 연결에 따라 달라집니다. | ||
| + | |||
| + | <code cpp> | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | volatile int32_t position = 0; | ||
| + | |||
| + | void readEncoder() { | ||
| + | // A상 하강 시 B상이 LOW이면 증가 (1배 카운트) | ||
| + | if (digitalRead(DIO) == LOW) { | ||
| + | if (position < INT32_MAX) position++; | ||
| + | } else { | ||
| + | if (position > INT32_MIN) position--; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | // 엔코더 A상 → CLK(D24), B상 → DIO(D25) | ||
| + | attachInterrupt(digitalPinToInterrupt(CLK), | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | int32_t snapshot; | ||
| + | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { | ||
| + | snapshot = position; | ||
| + | } | ||
| + | Serial.print(F(" | ||
| + | | ||
| delay(500); | delay(500); | ||
| } | } | ||
| 줄 382: | 줄 586: | ||
| | I²C | D18(SCL), D19(SDA) | '' | | I²C | D18(SCL), D19(SDA) | '' | ||
| - | ==== 예제 프로그램 · 통신과 다운로드 | + | ==== 예제 프로그램 · 기본 |
| - | Arduino IDE에서 보드를 **MPINO-8A4R(T)-S**로 선택합니다. 아래 코드는 각각 별도 스케치로 실행합니다. | + | Serial(115200bps)로 받은 |
| - | + | ||
| - | **기본 예제** | + | |
| - | + | ||
| - | **시리얼 모니터 ↔ RS-232 문자 전송** | + | |
| - | + | ||
| - | 시리얼 모니터에 입력한 | + | |
| <code cpp> | <code cpp> | ||
| 줄 409: | 줄 607: | ||
| </ | </ | ||
| - | **I²C 장치 주소 확인** | ||
| - | GND·SDA·SCL을 연결한 장치의 7비트 | + | ==== 예제 프로그램 · I²C 통신 ==== |
| + | |||
| + | Wire로 0x08~0x77의 I²C 주소를 검색하고 응답한 | ||
| <code cpp> | <code cpp> | ||
| 줄 440: | 줄 639: | ||
| </ | </ | ||
| - | **관련 내장함수 · 기본 함수** | ||
| - | 함수 이름을 누르면 설명과 독립 실행 | + | ==== 예제 |
| - | === 함수 예제 · Serial.begin() · available() · read() · write() === | + | **관련 내장 명령어** |
| - | Arduino 기본 Serial | + | === 함수 |
| + | |||
| + | **함수 원형** | ||
| <code cpp> | <code cpp> | ||
| + | void ImodbusRTUMem(uint16_t m_size, uint16_t d_size); | ||
| + | void ImodbusRTUAdr(uint16_t m_offset, uint16_t d_offset); | ||
| + | void ImodbusRTUInit(HardwareSerial& | ||
| + | void ImodbusRTU(); | ||
| + | </ | ||
| + | |||
| + | P0 상태를 M[0], A0 원시값(0~1023)을 D[0]에 넣어 상대 기기에서 읽습니다. RS-232(Serial1), | ||
| + | |||
| + | M과 D는 코어가 제공하는 공유 전역 메모리입니다. 이 스케치는 단독 실행하며, | ||
| + | |||
| + | <code cpp> | ||
| + | unsigned long lastPrint = 0; | ||
| + | bool memoryReady = false; | ||
| + | |||
| void setup() { | void setup() { | ||
| Serial.begin(115200); | Serial.begin(115200); | ||
| - | Serial1.begin(9600); | + | |
| + | ImodbusRTUAdr(0, | ||
| + | ImodbusRTUInit(Serial1, 1, 9600); | ||
| + | memoryReady = (M != nullptr && D != nullptr); | ||
| + | if (!memoryReady) Serial.println(F(" | ||
| } | } | ||
| void loop() { | void loop() { | ||
| - | if (Serial.available() && Serial1.availableForWrite()) { | + | if (!memoryReady) return; |
| - | | + | M[0] = digitalRead(0); |
| - | } | + | D[0] = analogRead(A0); |
| - | if (Serial1.available() && | + | ImodbusRTU(); |
| - | Serial.write(Serial1.read()); | + | |
| + | if (millis() - lastPrint >= 1000) { | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | Serial.println(D[0]); | ||
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | === 함수 예제 · Wire.beginTransmission() · endTransmission() === | + | === 함수 예제 · Modbus RTU Master: ImodbusRTUmasterInit(), ImodbusRTUmaster() === |
| - | Arduino 기본 Wire 라이브러리: | + | **함수 |
| <code cpp> | <code cpp> | ||
| - | # | + | void ImodbusRTUmasterInit(HardwareSerial& |
| + | uint8_t ImodbusRTUmaster(HardwareSerial& | ||
| + | </code> | ||
| + | |||
| + | RS-232(Serial1)로 상대 슬레이브의 홀딩 레지스터 1개를 1초마다 읽습니다. 상대 기기는 국번 1, 9600bps, 8N1, FC03·실제 시작 주소 0으로 준비합니다. 응답은 received[0]에 저장하며 성공한 경우에만 표시합니다. 오류 코드는 16진수로 표시합니다. 위 슬레이브 예제와는 별도 스케치이며, | ||
| + | |||
| + | <code cpp> | ||
| + | unsigned long lastRequest = 0; | ||
| + | uint16_t received[1]; | ||
| void setup() { | void setup() { | ||
| Serial.begin(115200); | Serial.begin(115200); | ||
| - | | + | |
| - | Wire.setClock(100000); | + | |
| } | } | ||
| void loop() { | void loop() { | ||
| - | | + | |
| - | | + | |
| - | const uint8_t result = Wire.endTransmission(); | + | const uint8_t result = ImodbusRTUmaster(Serial1, 1, 3, 0, 1, received, 200); // 국번 1의 주소 0에서 1워드 읽기, 제한 200ms |
| - | if (result == 0) { | + | |
| - | Serial.print(F(" | + | |
| - | | + | Serial.print(F(" |
| - | Serial.println(address, HEX); | + | |
| - | } | + | } else { |
| + | | ||
| + | Serial.println(result, HEX); | ||
| } | } | ||
| - | delay(3000); | ||
| } | } | ||
| </ | </ | ||
| + | |||
| + | ==== 예제 프로그램 · LS산전 Cnet 통신 ==== | ||
| + | |||
| + | **관련 내장 명령어** | ||
| + | |||
| + | === 함수 예제 · LS산전 Cnet SLave: ICnetMem(), ICnetAdr(), ICnetInit(), | ||
| + | |||
| + | **함수 원형** | ||
| + | |||
| + | <code cpp> | ||
| + | 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& | ||
| + | void ICnet(); | ||
| + | </ | ||
| + | |||
| + | P0 상태를 M[0], A0 원시값(0~1023)을 D[0]에 넣어 HMI에서 읽습니다. 상대 기기는 LS산전 Cnet, RS-232, 국번 1, 9600bps, 8N1로 설정합니다. 비트는 %MX00000(M[0]), | ||
| + | |||
| + | M·D·R은 코어가 제공하는 공유 전역 메모리이며, | ||
| + | |||
| + | <code cpp> | ||
| + | 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, | ||
| + | memoryReady = (M != nullptr && D != nullptr); | ||
| + | if (!memoryReady) Serial.println(F(" | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | if (!memoryReady) return; | ||
| + | M[0] = digitalRead(0); | ||
| + | D[0] = analogRead(A0); | ||
| + | ICnet(); | ||
| + | |||
| + | if (millis() - lastPrint >= 1000) { | ||
| + | lastPrint = millis(); | ||
| + | Serial.print(F(" | ||
| + | Serial.print(M[0]); | ||
| + | Serial.print(F(", | ||
| + | Serial.println(D[0]); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| [[products: | [[products: | ||
products/mpino_8a4t_s.1788765595.txt.gz · 마지막으로 수정됨: 저자 127.0.0.1
