로봇팔 각도 초기값 찾기
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVO_FREQ 50
// ── 채널 ──
#define CH_GRIPPER 12
#define CH_WRIST 13
#define CH_MIDDLE 14
#define CH_BASE 15
// ── 각도 범위 ──
#define ANGLE_MIN 0
#define ANGLE_MAX 270
// ── 홈 자세 (수직 곧게 핀 상태) ──
#define HOME_GRIPPER 90
#define HOME_WRIST 210
#define HOME_MIDDLE 220
#define HOME_BASE 100
// ── 현재 각도 ──
int curGripper = HOME_GRIPPER;
int curWrist = HOME_WRIST;
int curMiddle = HOME_MIDDLE;
int curBase = HOME_BASE;
int angleToTicks(int angle) {
int us = map(angle, 0, 180, 500, 2400);
return (int)((long)us * 4096L * SERVO_FREQ / 1000000L);
}
void smoothMove(int ch, int &cur, int target, int delayMs = 20) {
target = constrain(target, ANGLE_MIN, ANGLE_MAX);
int step = (target > cur) ? 1 : -1;
for (int a = cur; a != target; a += step) {
pwm.setPWM(ch, 0, angleToTicks(a));
delay(delayMs);
}
pwm.setPWM(ch, 0, angleToTicks(target));
cur = target;
}
void printMenu() {
Serial.println("\n=== Gripper Test ===");
Serial.println(" G<angle> 집게 각도 (예: G30, G60, G90, G120)");
Serial.println(" Range: 0 ~ 270");
Serial.println("Other joints fixed at home position.");
}
void setup() {
Serial.begin(9600);
pwm.begin();
pwm.setPWMFreq(SERVO_FREQ);
delay(500);
// 다른 관절은 홈 자세 고정
pwm.setPWM(CH_WRIST, 0, angleToTicks(HOME_WRIST));
pwm.setPWM(CH_MIDDLE, 0, angleToTicks(HOME_MIDDLE));
pwm.setPWM(CH_BASE, 0, angleToTicks(HOME_BASE));
// 집게 시작 위치
pwm.setPWM(CH_GRIPPER, 0, angleToTicks(curGripper));
printMenu();
Serial.print("Gripper start angle: ");
Serial.println(curGripper);
}
void loop() {
if (Serial.available()) {
String cmd = Serial.readStringUntil('\n');
cmd.trim();
if (cmd.length() == 0) return;
char c = cmd.charAt(0);
int angle = cmd.substring(1).toInt();
if (c == 'G' || c == 'g') {
smoothMove(CH_GRIPPER, curGripper, angle);
Serial.print("Gripper -> ");
Serial.println(curGripper);
} else {
Serial.println("Use G<angle> only.");
}
}
}
팔 움직임 구현 성공
ㄴ3D 프린팅할 때 팔을 U자로 굽는게 아닌 Z자로 굽게 잘못 설계해서 하드웨어적으로 불가능함
ㄴ코드는 문제가 없으니 된다치고, 나머지 동작 완성하기 + 3D팔 프린팅 설계 다시
완성 코드
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVO_FREQ 50
// ── 채널 ──
#define CH_GRIPPER 12
#define CH_WRIST 13
#define CH_MIDDLE 14
#define CH_BASE 15
// ── 각도 범위 ──
#define ANGLE_MIN 0
#define ANGLE_MAX 270
// ── 집게 위치 ──
#define GRIP_OPEN 270
#define GRIP_CLOSE 190
// ── 홈 자세 ──
// B110 정면, M220 수직, W210 수직, G 열림
#define HOME_GRIPPER GRIP_OPEN
#define HOME_WRIST 210
#define HOME_MIDDLE 220
#define HOME_BASE 110
// ── 피킹 동작 각도 ──
#define PICK_BASE 110 // 정면 유지
#define PICK_MIDDLE_DOWN 150 // 중간관절 숙이기
#define PICK_WRIST_DOWN 150 // 윗관절 추가 숙이기
#define PICK_LIFT_MIDDLE 200 // 들어올림 (홈보다 살짝 숙인 상태)
// ── 현재 각도 ──
int curGripper = HOME_GRIPPER;
int curWrist = HOME_WRIST;
int curMiddle = HOME_MIDDLE;
int curBase = HOME_BASE;
int angleToTicks(int angle) {
int us = map(angle, 0, 180, 500, 2400);
return (int)((long)us * 4096L * SERVO_FREQ / 1000000L);
}
void smoothMove(int ch, int &cur, int target, int delayMs = 20) {
target = constrain(target, ANGLE_MIN, ANGLE_MAX);
int step = (target > cur) ? 1 : -1;
for (int a = cur; a != target; a += step) {
pwm.setPWM(ch, 0, angleToTicks(a));
delay(delayMs);
}
pwm.setPWM(ch, 0, angleToTicks(target));
cur = target;
}
// ── 바닥 피킹 시퀀스 (정면 바닥) ──
void pickFromFloor() {
Serial.println(">> 1. 집게 열기 확인");
smoothMove(CH_GRIPPER, curGripper, GRIP_OPEN);
delay(300);
Serial.println(">> 2. 정면 회전 확인");
smoothMove(CH_BASE, curBase, PICK_BASE);
delay(300);
Serial.println(">> 3. 중간관절 숙이기");
smoothMove(CH_MIDDLE, curMiddle, PICK_MIDDLE_DOWN);
delay(300);
Serial.println(">> 4. 윗관절 미세 조정");
smoothMove(CH_WRIST, curWrist, PICK_WRIST_DOWN);
delay(500);
Serial.println(">> 5. 집게 닫기");
smoothMove(CH_GRIPPER, curGripper, GRIP_CLOSE);
delay(500);
Serial.println(">> 6. 들어올리기");
smoothMove(CH_MIDDLE, curMiddle, PICK_LIFT_MIDDLE);
delay(300);
Serial.println(">> 7. 홈 복귀");
smoothMove(CH_WRIST, curWrist, HOME_WRIST);
smoothMove(CH_MIDDLE, curMiddle, HOME_MIDDLE);
Serial.println(">> 완료 (집게는 닫힌 상태)");
}
void homePose() {
smoothMove(CH_GRIPPER, curGripper, HOME_GRIPPER);
smoothMove(CH_WRIST, curWrist, HOME_WRIST);
smoothMove(CH_MIDDLE, curMiddle, HOME_MIDDLE);
smoothMove(CH_BASE, curBase, HOME_BASE);
Serial.println(">> HOME");
}
void printStatus() {
Serial.print(" G:"); Serial.print(curGripper);
Serial.print(" W:"); Serial.print(curWrist);
Serial.print(" M:"); Serial.print(curMiddle);
Serial.print(" B:"); Serial.println(curBase);
}
void printMenu() {
Serial.println("\n=== Arm Pick Test ===");
Serial.println(" G<angle> 집게 (190 닫힘 ~ 270 벌림)");
Serial.println(" W<angle> CH13 윗관절 (210 수직, 260 숙임, 150 뒤로)");
Serial.println(" M<angle> CH14 중간관절 (220 수직, 150 숙임)");
Serial.println(" B<angle> CH15 아래관절 (110 정면, 50 시계, 150 반시계)");
Serial.println(" H 홈 위치");
Serial.println(" P 바닥 피킹 시퀀스");
}
void setup() {
Serial.begin(9600);
pwm.begin();
pwm.setPWMFreq(SERVO_FREQ);
delay(500);
pwm.setPWM(CH_GRIPPER, 0, angleToTicks(curGripper));
pwm.setPWM(CH_WRIST, 0, angleToTicks(curWrist));
pwm.setPWM(CH_MIDDLE, 0, angleToTicks(curMiddle));
pwm.setPWM(CH_BASE, 0, angleToTicks(curBase));
printMenu();
printStatus();
}
void loop() {
if (Serial.available()) {
String cmd = Serial.readStringUntil('\n');
cmd.trim();
if (cmd.length() == 0) return;
char c = cmd.charAt(0);
int angle = cmd.substring(1).toInt();
switch (c) {
case 'G': case 'g': smoothMove(CH_GRIPPER, curGripper, angle); break;
case 'W': case 'w': smoothMove(CH_WRIST, curWrist, angle); break;
case 'M': case 'm': smoothMove(CH_MIDDLE, curMiddle, angle); break;
case 'B': case 'b': smoothMove(CH_BASE, curBase, angle); break;
case 'H': case 'h': homePose(); break;
case 'P': case 'p': pickFromFloor(); break;
default: Serial.println("?"); return;
}
printStatus();
}
}


나머지 부품 아직 없어서 작업 이어서 불가
'로보테크AI' 카테고리의 다른 글
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/05/26 (0) | 2026.05.26 |
|---|---|
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/05/22 (0) | 2026.05.22 |
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/05/20 (0) | 2026.05.20 |
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/05/19[멘토링] (0) | 2026.05.19 |
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/05/18 (0) | 2026.05.18 |