//==============================================================
// MotorBank 리니어 스테이지(포토센서 리미트 포함) + MSD-224 아두이노 예제 V1.0
// 구조: MSD-224는 리미트 입력이 없으므로, 포토센서를 "아두이노"가 읽고
// 감지 즉시 펄스를 멈추는 소프트웨어 리미트 방식입니다.
// 기능: 원점복귀(호밍) / 위치 이동(리미트 감시) / 연속 이동(리미트 감시) / 센서 상태 확인
// 보드: Arduino Uno
//
// [드라이버 결선] 아두이노 -> MSD-224 (제어신호 3.3~24V)
// D9 -> PUL+ / D6 -> DIR+ / GND -> PUL-, DIR- (ENA 미사용 시 미연결)
// 모터 전원(SMPS)은 드라이버에 별도 공급
//
// [포토센서 결선 - SN04-A/SN04-N 기준(3선식)]
// 갈색 = 센서 전원(+, DC24V 별도 공급) / 파란색 = 전원(-, 아두이노 GND와 공통)
// 검정색(신호): 왼쪽(원점) 센서 -> D7 / 오른쪽 센서 -> D8 (내부 풀업 사용)
// NPN 옵션: 감지 시 신호가 LOW (아두이노 표준 - 기본값)
// PNP 옵션 구매 시에는 아래 값을 0으로 변경
#define SENSOR_ACTIVE_LOW 1 // 1: NPN(감지=LOW) / 0: PNP(감지=HIGH)
//
// [방향 기준] 본 예제는 CW(DIR HIGH)=오른쪽 이동, CCW=왼쪽(원점 방향)으로 가정.
// 실제 이동 방향이 반대면 DIR_CW_LEVEL을 LOW로 변경.
#define DIR_CW_LEVEL HIGH
//
// [이동량 환산] 이동거리(mm) = 스텝 수 x 리드(mm) / 회전당 스텝 수(분주 설정)
//
// [시리얼 모니터 사용법] (9600bps, "새 줄" 설정)
// h : 호밍 - 왼쪽 센서 감지까지 저속 이동 후 그 자리를 원점(0)으로
// m2000 : 오른쪽으로 2000스텝 이동(오른쪽 센서 감지 시 즉시 정지)
// M2000 : 왼쪽으로 2000스텝 이동(왼쪽 센서 감지 시 즉시 정지)
// f / r : 오른쪽/왼쪽 연속 이동(센서 감지 또는 s 입력 시 정지)
// s : 정지
// t : 좌우 센서 현재 상태 표시
//==============================================================
const int PUL_PIN = 9, DIR_PIN = 6;
const int SENS_L = 7, SENS_R = 8; // 왼쪽(원점)/오른쪽 포토센서
const unsigned int HALF_US_RUN = 240; // 일반 이동 약 2kHz
const unsigned int HALF_US_HOME = 600; // 호밍 저속 약 0.8kHz
long position = 0; // 원점 기준 현재 위치(스텝, 오른쪽 +)
bool homed = false;
bool sensL() { return digitalRead(SENS_L) == (SENSOR_ACTIVE_LOW ? LOW : HIGH); }
bool sensR() { return digitalRead(SENS_R) == (SENSOR_ACTIVE_LOW ? LOW : HIGH); }
void setDir(bool right) { digitalWrite(DIR_PIN, right ? DIR_CW_LEVEL : !DIR_CW_LEVEL); delayMicroseconds(10); }
// 리미트 감시하며 스텝 이동. 이동한 스텝 수 반환(센서·s 입력 시 조기 종료)
long moveSteps(bool right, long steps, unsigned int halfUs) {
setDir(right);
long done = 0;
for (; done < steps; done++) {
if (right ? sensR() : sensL()) { Serial.println(F("! 리미트 감지 - 정지")); break; }
if (Serial.available() && Serial.peek() == 's') break;
digitalWrite(PUL_PIN, HIGH); delayMicroseconds(halfUs);
digitalWrite(PUL_PIN, LOW); delayMicroseconds(halfUs);
}
position += right ? done : -done;
return done;
}
void home() {
Serial.println(F("호밍: 왼쪽 센서 방향 저속 이동..."));
if (!sensL()) moveSteps(false, 2000000L, HALF_US_HOME); // 감지까지 이동
if (sensL()) {
position = 0; homed = true;
Serial.println(F("원점 설정 완료 (position = 0)"));
} else Serial.println(F("호밍 실패 - 센서 결선·SENSOR_ACTIVE_LOW 확인"));
}
void setup() {
pinMode(DIR_PIN, OUTPUT); pinMode(PUL_PIN, OUTPUT);
pinMode(SENS_L, INPUT_PULLUP); pinMode(SENS_R, INPUT_PULLUP);
Serial.begin(9600);
Serial.println(F("LSM+MSD-224 ready. h m2000 M2000 f r 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 = constrain(cmd.substring(1).toInt(), 1, 2000000L);
switch (c) {
case 'h': home(); break;
case 'm': { long d = moveSteps(true, v, HALF_US_RUN);
Serial.print(F("+")); Serial.print(d); Serial.print(F(" steps, pos=")); Serial.println(position); } break;
case 'M': { long d = moveSteps(false, v, HALF_US_RUN);
Serial.print(F("-")); Serial.print(d); Serial.print(F(" steps, pos=")); Serial.println(position); } break;
case 'f': Serial.println(F("연속 우측 이동(센서/s로 정지)")); moveSteps(true, 2000000L, HALF_US_RUN);
Serial.print(F("pos=")); Serial.println(position); break;
case 'r': Serial.println(F("연속 좌측 이동(센서/s로 정지)")); moveSteps(false, 2000000L, HALF_US_RUN);
Serial.print(F("pos=")); Serial.println(position); break;
case 's': Serial.println(F("STOP")); break;
case 't': Serial.print(F("왼쪽 센서: ")); Serial.print(sensL() ? F("감지") : F("-"));
Serial.print(F(" / 오른쪽 센서: ")); Serial.print(sensR() ? F("감지") : F("-"));
Serial.print(F(" / pos=")); Serial.print(position);
Serial.println(homed ? F(" (호밍됨)") : F(" (호밍 전)")); break;
default: Serial.println(F("? h m2000 M2000 f r s t"));
}
}

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