본문 바로가기

카테고리 없음

(아두이노 우노) PCA9685 16-Channel Servo Driver (서보 모터 16개 다루기)

아두이노 우노로 로봇암의 서보 모터를 돌리다가, 우노의 PWM 설계 한계를 문득 알게 되면서, 외부 서보 드라이버를 쓰면 좋다는 이야기를 듣게 되었다.

 

https://learn.adafruit.com/16-channel-pwm-servo-driver?view=all 

https://dronebotworkshop.com/servo-motors-with-arduino/ 

 

이 기사들을 보면서 공부가 되었다. 아래 드론봇워크샵 영상에 나온 배선대로 처음에는 시도를 해보았는데, 가변저항 포텐션미터가 연결된 아날로그 핀에서 잡음이 끼어드는지 서보 모터의 동작이 정확하지 않고 다소 불안정한 모습을 보였다. 그래서 가변저항을 떼버리고 16개 서보 모터를 달아서 프로그램으로 단순 제어를 해보았다. 

 

16개를 연결해서 한꺼번에 16개를 0~180도를 왕복하도록 하고, 이후에는 한 개씩 왕복 운동을 하도록 했다.

 

https://youtube.com/shorts/GUN48nlY-WY?si=zcesqUT3IVGkNs-z

 

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

#define MIN_PULSE_WIDTH     650
#define MAX_PULSE_WIDTH     2350
#define FREQUENCY           50

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

// Define Potentiometer Inputs

int controlA = A0;
int controlB = A1;
int controlC = A2;
int controlD = A3;

// define motor outputs on PCA9685 board

#define N_MOTORS    16
int motorA = 0;
int motorB = 4;
int motorC = 8;
int motorD = 12;

int motors[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; 

void setup() {
  pwm.begin();
  pwm.setPWMFreq(FREQUENCY);
}

void moveMotor(int controlIn, int motorOut) {
  int pulse_wide, pulse_width, potVal;
  potVal = analogRead(controlIn);
  pulse_wide = map(potVal, 0, 1023, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
  pulse_width = int(float(pulse_wide) / 1000000 * FREQUENCY * 4096);

  pwm.setPWM(motorOut, 0, pulse_width);
}

// move from 0 degree to 180
void smove(int motor, uint8_t degree) {
  int pulse_wide, pulse_width;
  pulse_wide = map(degree, 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
  pulse_width = int(float(pulse_wide) / 1000000 * FREQUENCY * 4096);

  pwm.setPWM(motor, 0, pulse_width);
}

void loop() {
  /*
  moveMotor(controlA, motorA);
  moveMotor(controlB, motorB);
  moveMotor(controlC, motorC);
  moveMotor(controlD, motorD);
  */
  for (int i = 0; i <= 180; i++) {
    for (int j = 0; j < N_MOTORS; j ++) {
      smove(motors[j], i);
      delay(1);
    }
  }
  for (int i = 180; i >= 0; i--) {
    for (int j = 0; j < N_MOTORS; j ++) {
      smove(motors[j], i);
      delay(1);
    }
  }

  for (int i = 0; i < N_MOTORS; i++) {
    for (int j = 0; j <= 180; j++) {
    smove(motors[i], j);
    delay(5);
    }
    for (int j = 180; j>= 0; j--) {
    smove(motors[i], j);
    delay(5);
    }
  }
}

 

가변저항 4개로 모터를 조종한 코드의 흔적이 남아 있는데, 결국 smove(모터번호, 각도)로 0~180도 사이를 오갈 수 있다. 로봇암의 서보 모터 코드를 이 드라이버 라이브러리를 사용해서 수정해봐야겠다.