//==============================================================
// MotorBank BLC-20 / BLC-30 아두이노 예제 V3.2
// 기능: PWM 20kHz 속도제어 + 방향 + 브레이크 + 가감속(Slope)
// + 시리얼 모니터 명령 제어 (V3.1 대비 추가)
// 보드: Arduino Uno (검증 기준)
//
// [사전 준비] 라이브러리 매니저에서 설치:
// 1) TimerOne 2) MsTimer2
//
// [결선]
// D9 -> PWM(속도) 입력
// D4 -> Direction(방향) 입력
// D2 -> Brake(브레이크) 입력
// GND -> 드라이버 GND (반드시 공통)
//
// [시리얼 모니터 사용법] (9600bps, "새 줄" 설정)
// f80 : 정방향 80% 속도 r50 : 역방향 50% 속도
// s : 감속 정지(속도 0) b1 : 브레이크 ON b0 : 브레이크 OFF
// p3 : 가감속 기울기 1~10 (숫자 클수록 빠르게 가감속)
//==============================================================
#include <TimerOne.h>
#include <MsTimer2.h>
const int PWM_PIN = 9;
const int DIR_PIN = 4;
const int BRAKE_PIN = 2;
volatile int DutyRef = 0; // 목표 듀티 -1024~1024 (-100%~100%)
volatile int Duty = 0; // 현재 듀티(가감속 반영)
int Slope = 5; // 가감속 단계 1~10
void flash() { // 가감속: 목표까지 1스텝씩 접근
if (Duty < DutyRef) Duty++;
else if (Duty > DutyRef) Duty--;
if (Duty > 0) {
Timer1.setPwmDuty(PWM_PIN, 1024 - Duty);
digitalWrite(DIR_PIN, LOW);
} else if (Duty < 0) {
Timer1.setPwmDuty(PWM_PIN, 1024 + Duty);
digitalWrite(DIR_PIN, HIGH);
} else {
Timer1.setPwmDuty(PWM_PIN, 1024); // 속도 0
}
}
void applySlope() {
MsTimer2::stop();
MsTimer2::set(10 / constrain(Slope, 1, 10), flash);
MsTimer2::start();
}
void setup() {
Serial.begin(9600);
Timer1.initialize();
Timer1.pwm(PWM_PIN, 0);
Timer1.setPeriod(50); // 50us -> PWM 20kHz
Timer1.setPwmDuty(PWM_PIN, 1024); // 정지 상태로 시작
pinMode(DIR_PIN, OUTPUT); digitalWrite(DIR_PIN, LOW);
pinMode(BRAKE_PIN, OUTPUT); digitalWrite(BRAKE_PIN, HIGH); // 브레이크 해제 상태
applySlope();
Serial.println(F("BLC-20/30 ready. f80 r50 s b1 b0 p5"));
}
void loop() {
if (!Serial.available()) return;
String cmd = Serial.readStringUntil('\n');
cmd.trim();
if (cmd.length() == 0) return;
char c = cmd.charAt(0);
int v = cmd.substring(1).toInt();
switch (c) {
case 'f': DutyRef = constrain(v, 0, 100) * 1024L / 100; Serial.print(F("FWD ")); Serial.println(v); break;
case 'r': DutyRef = -constrain(v, 0, 100) * 1024L / 100; Serial.print(F("REV ")); Serial.println(v); break;
case 's': DutyRef = 0; Serial.println(F("STOP(slope)")); break;
case 'b': digitalWrite(BRAKE_PIN, v ? LOW : HIGH); Serial.println(v ? F("BRAKE ON") : F("BRAKE OFF")); break;
case 'p': Slope = constrain(v, 1, 10); applySlope(); Serial.print(F("Slope ")); Serial.println(Slope); break;
default: Serial.println(F("? f80 r50 s b1 b0 p5"));
}
}
//==============================================================
// MotorBank BLC-20R4 아두이노 RS485(Modbus RTU) 예제 V1.0
// 기능: RS485 통신으로 기동/속도/방향/브레이크 제어
// 보드: Arduino Uno + RS485 컨버터 모듈(MAX485 등)
// 근거: BLC-20R4 사용설명서 & RS485 Modbus 프로토콜 (CRC 예제 6건 검증 일치)
//
// [드라이버 설정] 제어 스위치를 Int로 설정 (RS485 제어 조건)
// [통신 설정] 9600bps, No Parity, 8 Data, 1 Stop (제품 기본값)
//
// [결선 - MAX485 모듈 기준]
// 모듈 RO -> D10 (아두이노 수신)
// 모듈 DI -> D11 (아두이노 송신)
// 모듈 DE+RE(묶어서) -> D3 (송신 시 HIGH)
// 모듈 A/B -> 드라이버 485 A/B (통신 안 되면 A/B 교차 시도)
// 모듈 VCC -> 5V, GND -> 공통 GND
//
// [시리얼 모니터 사용법] (9600bps, "새 줄" 설정)
// i : RS485 통신모드 기동(0x0023) - 전원 인가 후 최초 1회 필수!
// f80 : CW 방향 + 속도 80% r50 : CCW 방향 + 속도 50%
// s : 속도 0 b1/b0 : 브레이크 High/Low
//
// [주의]
// - 방향값: 상세 예시 기준 0x0000=CCW, 0x0001=CW 적용
// (설명서 요약표의 "1CW/2CCW" 표기와 상이 - 예시 프레임(CRC 검증됨) 기준 채택)
// - RS485 반이중 특성상 자기 송신 에코가 수신될 수 있어 코드에서 버림 처리함
//==============================================================
#include <SoftwareSerial.h>
const int RS485_RX = 10; // <- 모듈 RO
const int RS485_TX = 11; // -> 모듈 DI
const int RS485_EN = 3; // DE+RE
const byte DEV_ADDR = 0x01; // 제어기 주소(출고 기본 0x01)
SoftwareSerial rs485(RS485_RX, RS485_TX);
uint16_t crc16(const byte *data, byte len) { // Modbus CRC16
uint16_t crc = 0xFFFF;
for (byte j = 0; j < len; j++) {
crc ^= data[j];
for (byte i = 8; i != 0; i--) {
if (crc & 0x0001) { crc >>= 1; crc ^= 0xA001; }
else crc >>= 1;
}
}
return crc;
}
// Function 0x06: 레지스터 1개 쓰기 (기동/속도/방향/브레이크 공용)
void write06(uint16_t reg, uint16_t val) {
byte f[8];
f[0] = DEV_ADDR; f[1] = 0x06;
f[2] = reg >> 8; f[3] = reg & 0xFF;
f[4] = val >> 8; f[5] = val & 0xFF;
uint16_t c = crc16(f, 6);
f[6] = c & 0xFF; // CRC Low 먼저 (문서 예제 검증 순서)
f[7] = c >> 8; // CRC High
while (rs485.available()) rs485.read(); // 수신버퍼 비우기
digitalWrite(RS485_EN, HIGH); // 송신 모드
rs485.write(f, 8);
rs485.flush();
digitalWrite(RS485_EN, LOW); // 수신 모드
// 응답 수신(에코가 먼저 들어오면 8바이트 버리고 다음 8바이트가 실제 응답)
byte buf[16]; byte n = 0;
unsigned long t0 = millis();
while (millis() - t0 < 300 && n < 16) {
if (rs485.available()) buf[n++] = rs485.read();
}
Serial.print(F("TX:"));
for (byte i = 0; i < 8; i++) { Serial.print(' '); if (f[i] < 16) Serial.print('0'); Serial.print(f[i], HEX); }
Serial.print(F(" | RX(")); Serial.print(n); Serial.print(F("B):"));
for (byte i = 0; i < n; i++) { Serial.print(' '); if (buf[i] < 16) Serial.print('0'); Serial.print(buf[i], HEX); }
Serial.println();
}
void setup() {
Serial.begin(9600);
rs485.begin(9600); // 9600 N81 (제품 기본)
pinMode(RS485_EN, OUTPUT);
digitalWrite(RS485_EN, LOW);
Serial.println(F("BLC-20R4 RS485 ready."));
Serial.println(F("i(기동,최초1회) f80 r50 s b1 b0"));
}
void loop() {
if (!Serial.available()) return;
String cmd = Serial.readStringUntil('\n');
cmd.trim();
if (cmd.length() == 0) return;
char c = cmd.charAt(0);
int v = constrain(cmd.substring(1).toInt(), 0, 100);
switch (c) {
case 'i': write06(0x0023, 0x0000); Serial.println(F("RS485 mode start")); break; // 기동(필수)
case 'f': write06(0x0025, 0x0001); write06(0x0024, v); break; // CW + 속도
case 'r': write06(0x0025, 0x0000); write06(0x0024, v); break; // CCW + 속도
case 's': write06(0x0024, 0); break; // 속도 0
case 'b': write06(0x0026, v ? 1 : 0); break; // 브레이크
default: Serial.println(F("? i f80 r50 s b1 b0"));
}
}
FG 신호 계수 및 사양 변경 가능
본 제품은 FG 출력 펄스 수를 요구 사양에 맞춰 변경할 수 있습니다. 회로를 자체 사양으로 설계하기 때문에 토크·회전수 등 성능 사양 변경도 함께 가능합니다. 단, 사양 변경 제작 시 최소 주문수량(MOQ)이 발생할 수 있습니다.


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