//==============================================================
// MotorBank SBD-14U 아두이노 RS485(Modbus RTU) 예제 V1.0
// 기능: 정역 연속회전 / 절대좌표 이동 / 운전속도 설정 / 정지(잠김·자유) / 상태 읽기
// 보드: Arduino Uno + RS485 컨버터 모듈(MAX485 등)
// 근거: SBD-14U_protocol 문서 (CRC 예제 15건 전수 검증 일치) — 문서 확정 기능만 구현
//
// [통신 설정] 9600bps, No Parity, 1 Stop (출하 기본) / 출하 기본주소 0x01
// [결선] 모듈 RO->D10, DI->D11, DE+RE->D3, A->드라이버 A, B->B, GND 공통
// (핀 번호는 예제 편의상 지정 - 다른 디지털 핀도 사용 가능)
//
// [시리얼 모니터 사용법] (9600bps, "새 줄" 설정)
// f : 정회전 연속(0x002A<-0x0010, 리미트 비활성) r : 역회전 연속(0x0000)
// g51200 : 원점 기준 +방향 절대좌표 51200스텝으로 이동(0x002B)
// G51200 : -방향 절대좌표로 이동
// v51200 : 운전속도 51200 step/s 설정(0x0028, 전원 차단 시 저장 안 됨)
// s : 정지+축 잠김(0x002D<-0x0000) S : 정지+축 자유(0x0001)
// t : 상태 읽기(0x002E - 정지/과열/실전류/리미트 파싱)
//
// [문서 기재 주의사항 - 그대로 반영]
// - 정지 지령 후 2초 뒤에 다음 지령을 보내야 함(코드에서 안내 출력)
// - 좌표모드는 절대위치라 같은 목표값 재전송 시 모터가 돌지 않는 것이 정상
// - 속도 환산은 1.8도 스텝각 기준(다른 스텝각은 비례 계산)
//
// [상충 플래그 - 실기 확인 대상]
// 프로토콜 문서: 0x0010=정회전(비트표 bit4=1 정방향과 일치 - 본 코드 채택)
// PC툴 문서 요약: 정회전=0x0000 으로 반대 표기 - 실기에서 방향이 반대로 돌면
// f/r의 값(0x0010/0x0000)을 서로 바꾸면 됩니다.
//==============================================================
#include <SoftwareSerial.h>
const int RS485_RX = 10, RS485_TX = 11, RS485_EN = 3;
const byte ADDR = 0x01; // 출하 기본주소
SoftwareSerial rs485(RS485_RX, RS485_TX);
uint16_t crc16(const byte *d, byte n) { // 표준 Modbus CRC16
uint16_t c = 0xFFFF;
for (byte j = 0; j < n; j++) {
c ^= d[j];
for (byte i = 8; i; i--) c = (c & 1) ? (c >> 1) ^ 0xA001 : c >> 1;
}
return c;
}
void txrx(byte *f, byte n) { // 송신 + 응답 HEX 로그
uint16_t c = crc16(f, n);
f[n++] = c & 0xFF; f[n++] = c >> 8; // CRC Low 먼저(문서 예제 검증 순서)
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); }
byte buf[24]; byte m = 0;
unsigned long t0 = millis();
while (millis() - t0 < 300 && m < 24) if (rs485.available()) buf[m++] = rs485.read();
Serial.print(F(" | RX(")); Serial.print(m); Serial.print(F("B):"));
for (byte i = 0; i < m; i++) { Serial.print(' '); if (buf[i]<16) Serial.print('0'); Serial.print(buf[i], HEX); }
Serial.println();
// 상태 읽기 응답 파싱: [ADDR][03][02][H][L][CRC](에코 뒤에 붙을 수 있어 뒤에서 탐색)
for (int i = m - 5; i >= 0; i--) {
if (buf[i] == ADDR && buf[i+1] == 0x03 && buf[i+2] == 0x02) {
uint16_t s = ((uint16_t)buf[i+3] << 8) | buf[i+4];
Serial.print(F(" 상태: ")); Serial.print(s & 0x8000 ? F("정지") : F("운전중"));
if (s & 0x4000) Serial.print(F(" / 과열경고(120C)"));
if (s & 0x2000) Serial.print(F(" / 과열정지(136C)"));
Serial.print(F(" / 전류코드 ")); Serial.print((s >> 4) & 0x1F);
Serial.print(F(" / 우측SW ")); Serial.print((s >> 1) & 1);
Serial.print(F(" / 좌측SW ")); Serial.println(s & 1);
break;
}
}
}
void write06(uint16_t reg, uint16_t val) {
byte f[8] = { ADDR, 0x06, (byte)(reg>>8), (byte)reg, (byte)(val>>8), (byte)val };
txrx(f, 6);
}
void write10_32(uint16_t reg, uint32_t val) { // 32bit: 레지스터 2개, 4바이트
byte f[13] = { ADDR, 0x10, (byte)(reg>>8), (byte)reg, 0x00, 0x02, 0x04,
(byte)(val>>24), (byte)(val>>16), (byte)(val>>8), (byte)val };
txrx(f, 11);
}
void read03(uint16_t reg) {
byte f[8] = { ADDR, 0x03, (byte)(reg>>8), (byte)reg, 0x00, 0x01 };
txrx(f, 6);
}
void setup() {
Serial.begin(9600);
rs485.begin(9600);
pinMode(RS485_EN, OUTPUT); digitalWrite(RS485_EN, LOW);
Serial.println(F("SBD-14U ready. f r g51200 G51200 v51200 s S t"));
}
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 'f': write06(0x002A, 0x0010); Serial.println(F("정회전(리미트 비활성)")); break;
case 'r': write06(0x002A, 0x0000); Serial.println(F("역회전(리미트 비활성)")); break;
case 'g': write10_32(0x002B, (uint32_t)constrain(v, 0, 0xFFFFFF));
Serial.println(F("+좌표 이동(같은 값 재전송 시 무회전이 정상)")); break;
case 'G': write10_32(0x002B, 0x80000000UL | (uint32_t)constrain(v, 0, 0xFFFFFF));
Serial.println(F("-좌표 이동")); break;
case 'v': write10_32(0x0028, (uint32_t)constrain(v, 1, 200000));
Serial.println(F("운전속도 설정(전원 차단 시 미저장)")); break;
case 's': write06(0x002D, 0x0000); Serial.println(F("정지+잠김. 다음 지령은 2초 후!")); break;
case 'S': write06(0x002D, 0x0001); Serial.println(F("정지+축 자유. 다음 지령은 2초 후!")); break;
case 't': read03(0x002E); break;
default: Serial.println(F("? f r g51200 G51200 v51200 s S t"));
}
}
SBD-14U_users_manual 및 protocol 과 PC_tools 사용법




상품이 장바구니에 담겼습니다.
바로 확인하시겠습니까?
상품이 찜 리스트에 담겼습니다.
바로 확인하시겠습니까?