속도 및 방향 제어가 정상적으로 동작하지 않을 경우 아래 내용을 확인해 주세요.
BLDC 모터는 Hall 센서(H1/H2/H3) 신호 순서와 모터 상(U/V/W)의 조합에 따라 정상적인 구동 여부가 달라질 수 있습니다.
Hall 신호 또는 모터 상 결선이 맞지 않거나 회전 방향 설정이 올바르지 않은 경우, 모터가 정상적으로 회전하지 않거나 속도 및 방향 제어가 불안정할 수 있습니다.
소프트웨어 최초 설정 시 아래 값을 기본값으로 설정한 후 테스트해 주세요.
| 항목 | 권장 초기 설정 |
|---|---|
| Kp | 30 |
| Ki | 1 |
| Kd | 0 |
| 정격전류 | 모터 정격전류 |
모터가 정상적으로 동작하는 것을 확인한 후 Kp / Ki / Kd 값을 변경하여 원하는 응답 특성에 맞게 조정할 수 있습니다.
Kp 값을 높이면 모터의 응답성이 향상될 수 있으나, 설정값이 과도하게 높을 경우 진동 또는 떨림 현상이 발생할 수 있습니다.
사용하는 모터의 종류에 따라 소프트웨어의 분해능 입력값을 다르게 설정해야 합니다.
| 모터 종류 | 분해능 입력값 |
|---|---|
| Hall 센서 BLDC + 엔코더 장착 | 엔코더 PPR 값 |
| 일반 Hall 센서 BLDC | 모터 Pole(극수) |
※ 제품 사양에 따라 입력 기준이 다를 수 있으므로 해당 모터의 사양을 확인해 주세요.
위치제어 모드에 따라 정지(Stop) 명령의 동작 여부가 달라집니다.
| 제어 모드 | 정지 명령 |
|---|---|
| 상대 위치제어 모드 | 정상작동불가 |
| 절대 위치제어 모드 | 사용 가능 |
BLC-400R4E 통신 프로토콜 다운로드 클릭


| RS485 모듈 | 연결 |
|---|---|
| RO (수신 출력) | 아두이노 D10 |
| DI (송신 입력) | 아두이노 D11 |
| DE + RE (묶어서) | 아두이노 D3 |
| A / B (통신선) | BLC-400R4E의 485 단자 (통신이 안 되면 A/B 교차) |
| VCC / GND | 5V / GND (드라이버와 GND 공통) |
//==============================================================// PG42BL42100E1K + BLC-400R4E 아두이노 RS485 제어 예제 V1.2// (MC-RS485 프로토콜 V1.0.2 문서 전수 대조 완료)// 보드: Arduino Uno + RS485 컨버터 모듈(MAX485 등)//// [통신 설정] 9600bps(제품 초기값), 8 Data, No Parity, 1 Stop// [프레임 구조] FF FE | ID | Data크기 | Checksum | Mode | Data...// Checksum = ~(ID + Data크기 + Mode + Data바이트 합)의 하위 1바이트//// [결선 - MAX485 모듈 기준] ※ 반드시 BLC-400R4E 상세페이지 결선도 기준// 모듈 RO -> D10 / DI -> D11 / DE+RE(묶음) -> D3// 모듈 A/B -> 드라이버 485 A/B (통신 안 되면 A/B 교차)// 모듈 VCC -> 5V, GND -> 아두이노·드라이버 공통//// [이 모터 전용 초기 설정] 반드시 제어 Off(E) 상태에서, 명령 간 0.3초 이상 간격:// c : 분해능 등록 - 1000CPR 모터는 CPR/4 규칙에 따라 250이 입력됩니다// d14 : 감속비 등록 (★구매 옵션 값 - 예: 1/14 -> d14. 0.1비 단위로 자동 환산)// 설정은 EEPROM에 기록되므로 최초 1회만 하면 되고, 등록 후에는// 위치(도)·속도(RPM)가 감속기 출력축 기준으로 동작합니다.//// [시리얼 모니터 사용법] (9600bps, "새 줄" 설정)// e / E : 제어 On / Off (Off 상태에서는 제어 명령이 무시됩니다)// f1000 : CW 100.0RPM (0.1RPM 단위, 도달시간 1초 가감속)// r500 : CCW 50.0RPM// s : 감속 정지// g9000 : CW 90.00도 위치 이동 (0.01도 단위, 절대위치 0~655.33도)// G9000 : CCW 90.00도 위치 이동// z : 현재 위치를 0으로 초기화 (제어 Off 상태에서 권장)// p / v : 위치 / 속도 피드백 요청//==============================================================#include <SoftwareSerial.h>const int RS485_RX = 10, RS485_TX = 11, RS485_EN = 3; const byte MOTOR_ID = 0x00; // 제품 초기 ID 0x00 (변경했다면 수정) const unsigned int ENC_PPR = 250; // 1000CPR / 4 (프로토콜 규칙: CPR은 4로 나눠 입력) SoftwareSerial rs485(RS485_RX, RS485_TX); // 프레임 송신: mode + data -> 헤더/크기/체크섬 자동 구성 void sendFrame(byte mode, const byte *data, byte dlen) { byte size = dlen + 2; // Mode + Data + Checksum int sum = MOTOR_ID + size + mode; for (byte i = 0; i < dlen; i++) sum += data[i]; byte chk = (~sum) & 0xFF; byte f[16]; byte n = 0; f[n++] = 0xFF; f[n++] = 0xFE; f[n++] = MOTOR_ID; f[n++] = size; f[n++] = chk; f[n++] = mode; for (byte i = 0; i < dlen; i++) f[n++] = data[i]; while (rs485.available()) rs485.read(); // 수신버퍼 비우기 digitalWrite(RS485_EN, HIGH); rs485.write(f, n); rs485.flush(); digitalWrite(RS485_EN, LOW); Serial.print(F("TX:")); for (byte i = 0; i < n; i++) { Serial.print(' '); if (f[i]<16) Serial.print('0'); Serial.print(f[i], HEX); } Serial.println(); } // 수신 프레임 읽기 + 위치/속도 피드백(0xD1/0xD2) 해석 void readFeedback() { byte buf[24]; byte n = 0; unsigned long t0 = millis(); while (millis() - t0 < 300 && n < 24) { if (rs485.available()) buf[n++] = rs485.read(); } if (n == 0) { Serial.println(F("RX: (응답 없음 - 결선/ID/전원 확인)")); return; } Serial.print(F("RX:")); for (byte i = 0; i < n; i++) { Serial.print(' '); if (buf[i]<16) Serial.print('0'); Serial.print(buf[i], HEX); } Serial.println(); for (int i = n - 4; i >= 0; i--) { if (buf[i] == 0xFF && buf[i+1] == 0xFE) { byte mode = buf[i+5]; if ((mode == 0xD1 || mode == 0xD2) && i + 11 < (int)n + 1) { byte dir = buf[i+6]; unsigned int a = ((unsigned int)buf[i+7] << 8) | buf[i+8]; unsigned int b = ((unsigned int)buf[i+9] << 8) | buf[i+10]; byte cur = buf[i+11]; if (mode == 0xD1) { // 위치 피드백: 위치[0.01도] 속도[0.1RPM] 전류[100mA] Serial.print(F("위치: ")); Serial.print(dir ? F("CW ") : F("CCW ")); Serial.print(a / 100.0); Serial.print(F("도, 속도 ")); Serial.print(b / 10.0); Serial.print(F("RPM, 전류 ")); Serial.print(cur * 0.1); Serial.println(F("A")); } else { // 속도 피드백: 속도[0.1RPM] 위치[0.1도] 전류[100mA] Serial.print(F("속도: ")); Serial.print(dir ? F("CW ") : F("CCW ")); Serial.print(a / 10.0); Serial.print(F("RPM, 위치 ")); Serial.print(b / 10.0); Serial.print(F("도, 전류 ")); Serial.print(cur * 0.1); Serial.println(F("A")); } } break; } } } void speedMove(byte dir, unsigned int spd01rpm, byte time01s) { // 가감속 속도제어 0x03 byte d[4] = { dir, (byte)(spd01rpm >> 8), (byte)(spd01rpm & 0xFF), time01s }; sendFrame(0x03, d, 4); } void posMove(byte dir, unsigned int pos001deg, byte time01s) { // 가감속 위치제어 0x02 byte d[4] = { dir, (byte)(pos001deg >> 8), (byte)(pos001deg & 0xFF), time01s }; sendFrame(0x02, d, 4); } void setU16(byte mode, unsigned int v) { // 2바이트 설정값 송신 byte d[2] = { (byte)(v >> 8), (byte)(v & 0xFF) }; sendFrame(mode, d, 2); } void ctrlOnOff(bool on) { // 제어 On/Off 0x0C byte d[1] = { on ? (byte)0x00 : (byte)0x01 }; sendFrame(0x0C, d, 1); } void setup() { Serial.begin(9600); rs485.begin(9600); // 제품 초기값 9600bps pinMode(RS485_EN, OUTPUT); digitalWrite(RS485_EN, LOW); Serial.println(F("PG42BL42100E1K + BLC-400R4E ready. (V1.2)")); Serial.println(F("초기 1회(제어 Off 상태에서): c(분해능) d<감속비> | e/E f1000 r500 s g9000 G9000 z p v")); } void loop() { if (!Serial.available()) return; String cmd = Serial.readStringUntil('\n'); cmd.trim(); if (cmd.length() == 0) return; char c = cmd.charAt(0); long v = cmd.substring(1).toInt(); switch (c) { case 'e': ctrlOnOff(true); Serial.println(F("제어 On")); break; case 'E': ctrlOnOff(false); Serial.println(F("제어 Off")); break; case 'f': speedMove(0x01, constrain(v, 1, 65533), 10); break; // CW, 도달 1.0s case 'r': speedMove(0x00, constrain(v, 1, 65533), 10); break; // CCW case 's': speedMove(0x01, 1, 5); delay(600); speedMove(0x01, 1, 1); Serial.println(F("감속 정지")); break; case 'g': posMove(0x01, constrain(v, 0, 65533), 10); break; // CW 위치 case 'G': posMove(0x00, constrain(v, 0, 65533), 10); break; // CCW 위치 case 'c': setU16(0x0A, ENC_PPR); // 분해능 설정(10번) - EEPROM 기록, 제어 Off에서 Serial.println(F("분해능 등록: 1000CPR -> 250 입력 (CPR/4 규칙)")); break; case 'd': if (v < 1) { Serial.println(F("감속비를 입력하세요 (예 d14)")); return; } setU16(0x0B, (unsigned int)(v * 10)); // 감속비 설정(11번) - 0.1비 단위 Serial.print(F("감속비 1/")); Serial.print(v); Serial.print(F(" 등록 (전송값 ")); Serial.print(v * 10); Serial.println(F(")")); break; case 'z': sendFrame(0x0F, nullptr, 0); Serial.println(F("위치 0 초기화 (15번 명령)")); break; case 'p': sendFrame(0xA1, nullptr, 0); readFeedback(); return; case 'v': sendFrame(0xA2, nullptr, 0); readFeedback(); return; default: Serial.println(F("? e/E c d14 f1000 r500 s g9000 G9000 z p v")); return; } readFeedback(); // 명령 후 응답/에코 로그 표시}
상품이 장바구니에 담겼습니다.
바로 확인하시겠습니까?
상품이 찜 리스트에 담겼습니다.
바로 확인하시겠습니까?