일단 지난글 방식대로 해서

AD0로 MPU6050 주소를 2가지만 선택이 가능하지만

여러개로부터 값을 가져올수 있도록 정리했었다.

 

이번엔 아예 3개를 연결해서 가져와지나 테스트

 

 

 

 

가져와지는건 좋지만 여전히 데이터가 몇개 빠져서 들어올때가 있다.

 

 

 

 

데이터 송수신시 다른 조건문으로 들어가서라 생각되는데

 

void SendData(int pinNum)
{
    for (int i = 0; i < 2; i++)
    {
      if (mpuPinNums[i] == pinNum)
        digitalWrite(mpuPinNums[i], LOW);  //set selected mpu6050 addr 0x68
      else
        digitalWrite(mpuPinNums[i], HIGH);  //set other mpu6050 addr 0x69
    }

    // if programming failed, don't try to do anything
    if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize) {
    }

    // reset interrupt flag and get INT_STATUS byte
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();

    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {
        // wait for correct available data length, should be a VERY short wait
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

        // read a packet from FIFO
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        
        // track FIFO count here in case there is > 1 packet available
        // (this lets us immediately read more without waiting for an interrupt)
        fifoCount -= packetSize;

        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            BTSerial.print(pinNum);
            BTSerial.print(":");
            BTSerial.print(int(ypr[0] * 180/M_PI));
            BTSerial.print(",");
            BTSerial.print(int(ypr[1] * 180/M_PI));
            BTSerial.print(",");
            BTSerial.print(int(ypr[2] * 180/M_PI));
            BTSerial.print("/");
        #endif
    }
}

 

 

 

 

 

mpu 상태가져오기전에 사용되는 값들 출력시켜봣는데

    Serial.println("");
    Serial.print(pinNum);
    Serial.print("pin dmpReady : ");
    Serial.print(dmpReady);
    Serial.print(", before mpuInterrupt : ");
    Serial.print(mpuInterrupt);
    Serial.print(", fifocount : ");
    Serial.println(fifoCount);

    // if programming failed, don't try to do anything
    if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize) {
    }

 

이것만으로 어쩔때 나오고 어쩔때 안나오는지 판단할수가 없엇음.

 

 

 

 

 

이번에는

상태랑 피포카운트 출력하도록 수정

 

    // reset interrupt flag and get INT_STATUS byte
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();
    Serial.print(", after mpuIntStatus : ");
    Serial.print(mpuIntStatus);
    Serial.print(", fifocount : ");
    Serial.println(fifoCount);

    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {
        // wait for correct available data length, should be a VERY short wait
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

        // read a packet from FIFO
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        
        // track FIFO count here in case there is > 1 packet available
        // (this lets us immediately read more without waiting for an interrupt)
        fifoCount -= packetSize;

        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            Serial.print(pinNum);
            Serial.print(":");

 

 

위 코드 대로 mpuIntStatus 가 2일때만 진입해서 출력하는걸 확인

2 외에

1, 3, 4, 19가 자주 발생한다.

 

 

 

 

 

잠깐 지금 보니 6, 7때 같은값을 가져오고있었네

 

mpu3개 연결했는데

루프문을 몇군대 잘못하기도하고

세번째 mpu를 반대로 놓거나

핀아웃을 안해놔서 안떳다.

거기다가 블루투스때문에 보드레이트를 9600 해놨었는데

 

115200으로 했을때 더 잘나온다.

 

 

//RXD3, TXD4
SoftwareSerial BTSerial(4, 3);
int mpuPinNums[] = {5, 6, 7};
int mpuNum = sizeof(mpuPinNums) / sizeof(int);


void InitMPU(int pinNum);
void SendData(int pinNum);

void setup() {
  for (int i = 0; i < mpuNum;i++)
    pinMode(mpuPinNums[i], OUTPUT);

  Serial.begin(115200);

  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
      Wire.begin();
      TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
      Fastwire::setup(400, true);
  #endif

  while (!Serial); // wait for Leonardo enumeration, others continue immediately

  for (int i = 0; i < mpuNum;i++)
    InitMPU(mpuPinNums[i]);
}


void loop() {

  for (int i = 0; i < mpuNum;i++)
    SendData(mpuPinNums[i]);

  Serial.println("");
}


void InitMPU(int pinNum)
{
  for (int i = 0; i < mpuNum; i++)
  {
    if (mpuPinNums[i] == pinNum)
      digitalWrite(pinNum, LOW);  //set selected mpu6050 addr 0x68
    else
      digitalWrite(mpuPinNums[i], HIGH);  //set other mpu6050 addr 0x69
  }
  Serial.print("start init pin ");
  Serial.println(pinNum);


  // initialize device
  mpu.initialize();

  // verify connection
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  // load and configure the DMP
  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();

  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(220);
  mpu.setYGyroOffset(76);
  mpu.setZGyroOffset(-85);
  mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

  // make sure it worked (returns 0 if so)
  if (devStatus == 0) {
      // turn on the DMP, now that it's ready
      Serial.println(F("Enabling DMP..."));
      mpu.setDMPEnabled(true);

      // enable Arduino interrupt detection
      Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
      attachInterrupt(0, dmpDataReady, RISING);
      //attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);

      mpuIntStatus = mpu.getIntStatus();

      // set our DMP Ready flag so the main loop() function knows it's okay to use it
      Serial.println(F("DMP ready! Waiting for first interrupt..."));
      dmpReady = true;

      // get expected DMP packet size for later comparison
      packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
      Serial.print(F("DMP Initialization failed (code "));
      Serial.print(devStatus);
      Serial.println(F(")"));
  }
}

void SendData(int pinNum)
{
  for (int i = 0; i < mpuNum; i++)
  {
    if (mpuPinNums[i] == pinNum)
      digitalWrite(mpuPinNums[i], LOW);  //set selected mpu6050 addr 0x68
    else
      digitalWrite(mpuPinNums[i], HIGH);  //set other mpu6050 addr 0x69
  }


  Serial.println("");

  Serial.print(pinNum);
  Serial.print("pin dmpReady : ");

  // if programming failed, don't try to do anything
  if (!dmpReady) return;

  // wait for MPU interrupt or extra packet(s) available
  while (!mpuInterrupt && fifoCount < packetSize) {
  }

  // reset interrupt flag and get INT_STATUS byte
  mpuInterrupt = false;
  mpuIntStatus = mpu.getIntStatus();

  // get current FIFO count
  fifoCount = mpu.getFIFOCount();
  Serial.print(", after mpuIntStatus : ");
  Serial.print(mpuIntStatus);
  Serial.print(", fifocount : ");
  Serial.println(fifoCount);

  // check for overflow (this should never happen unless our code is too inefficient)
  if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
      // reset so we can continue cleanly
      mpu.resetFIFO();

  // otherwise, check for DMP data ready interrupt (this should happen frequently)
  } else if (mpuIntStatus & 0x02) {
      // wait for correct available data length, should be a VERY short wait
      while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

      // read a packet from FIFO
      mpu.getFIFOBytes(fifoBuffer, packetSize);
      
      // track FIFO count here in case there is > 1 packet available
      // (this lets us immediately read more without waiting for an interrupt)
      fifoCount -= packetSize;

      #ifdef OUTPUT_READABLE_YAWPITCHROLL
          // display Euler angles in degrees
          mpu.dmpGetQuaternion(&q, fifoBuffer);
          mpu.dmpGetGravity(&gravity, &q);
          mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
          Serial.print(pinNum);
          Serial.print(":");
          Serial.print(int(ypr[0] * 180/M_PI));
          Serial.print(",");
          Serial.print(int(ypr[1] * 180/M_PI));
          Serial.print(",");
          Serial.print(int(ypr[2] * 180/M_PI));
          Serial.print("/");
      #endif
  }
}

 

 

 

 

 

블루투스로 확인하기전에

잠깐 mpu intstatus의미부터 확인해보면

 

 

깃헙에서 찾은걸보면

이게 인터럽트 레지스터 값 가져오는거같다

각 값별 의미는 없어서 데이터시트 봐야할듯

 

https://github.com/jrowberg/i2cdevlib/blob/master/Arduino/MPU6050/MPU6050.cpp

 

 

 

데이터시트에서 말하길

레지스터맵 레지스터 설명 다큐먼트보랜다.

 

 

 

 

레지스터 다큐먼트에서 인터럽트 상태 레지스터 족 찾긴했는데

좀이해는 안간다.

 

비트1이 없으면 왜 2, 3같은 값이 나오는걸까?

내가 잘못 찾거나 잘못이해한거라 생각되는데

 

 

 

 

 

뭔가 이상하다 싶어서

구글링하다가

우리나라에서도 이것때문에 해맨 분글을 찾았다.

 

https://blog.naver.com/heennavi1004/10183570269

 

 

 

 

진짜 눈물난다.

해외에서도 이렇게 잘 설명해준게 흔치않는데

우리나라 분이 10년전이 정리해서 올려놨다니 ㅜㅜ

 

정리하면 데이터시트에서 제대로 작성안한 히든레지스터가 있어서 그렇다고한다.

 

https://blog.naver.com/heennavi1004/10183570269

 

 

 

 

다시돌아와 지금은 115200 보드레이트를 쓰면서 잘 출력이 됬었지만

블루투스에서 9600 보드레이트를 쓰다보니

9600보드레이트로 낮출때

인터럽트스테이트가 19가 나왔따.

 

다시 보면

인터럽트 스테이터스가 19일때는 피포 오버플로우로 출력이 안됬꼬

나머지 출력이 안된 상황인 1, 4의 경우 피포 오버플로가 안됬지만

1번비트가 하이가 아니여서 조건문에거 걸린것으로 보인다.

  } else if (mpuIntStatus & 0x02) {
 

 

어쨋거나 mpu동작속도 생각하면

115200쓰는게 좋아보이긴한데

배터리 블루투스로하면 왜 못받아오는지 찾질못했었지만

 

이제 상태값도 조금 찾아봣겟다

블루투스 설정을 115200으로해서 다시봐도 될듯하다.

 

이전에 보드레이트변경 코드를 가져와서 사용

 

 

AT로 동작확인

AT+BUAD8로 115200로 변경

 

 

 

 

 

노트북 USB전원으로 동작시킬때는

블루투스 115200으로도 잘 동작한다.

시리얼 115200때보다 인터럽트 상태가 19되는경우가 잦은느낌이긴한데

베터리 전원을 줄때 인터럽트 코드확인

 

 

 

 

 

 

역시나 115200 hc-05를 보조베터리 전원을줄때 안된다.

내가 갖고있는 보조베터리 출력이 5V승압없이 3.7V 2A 라 그런것같기도하고 

그냥 원래 생각했던데로 esp32나 쓸까부다--

 

원래 주말에 해야지 생각만하고 계속 질질 미루다

오늘 아침이 되서야 MPU6050 나머지 땜질 다했다.

 

11개가 준비됬는데

일단 2개만 어떻게하면 동시에 가져올수 있을까 정리

 

 

 

 

 

 

이건 내가 기존에 사용하던 코드인데

MPU6050 mpu;를 여러개 만들어서 일단 정리해야할듯

#include "I2Cdev.h"
#include <SoftwareSerial.h> 

#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu;
//MPU6050 mpu(0x69); // <-- use for AD0 high

#define OUTPUT_READABLE_YAWPITCHROLL


#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };


volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}



//RXD3, TXD4
SoftwareSerial BTSerial(4, 3);

void setup() {
    BTSerial.begin(9600);

    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
        TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif

    while (!BTSerial); // wait for Leonardo enumeration, others continue immediately

    // initialize device
    BTSerial.println(F("Initializing I2C devices..."));
    mpu.initialize();
    //pinMode(INTERRUPT_PIN, INPUT);

    // verify connection
    BTSerial.println(F("Testing device connections..."));
    BTSerial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

    // load and configure the DMP
    BTSerial.println(F("Initializing DMP..."));
    devStatus = mpu.dmpInitialize();

    // supply your own gyro offsets here, scaled for min sensitivity
    mpu.setXGyroOffset(220);
    mpu.setYGyroOffset(76);
    mpu.setZGyroOffset(-85);
    mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

    // make sure it worked (returns 0 if so)
    if (devStatus == 0) {
        // turn on the DMP, now that it's ready
        BTSerial.println(F("Enabling DMP..."));
        mpu.setDMPEnabled(true);

        // enable Arduino interrupt detection
        BTSerial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
        attachInterrupt(0, dmpDataReady, RISING);
        //attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);

        mpuIntStatus = mpu.getIntStatus();

        // set our DMP Ready flag so the main loop() function knows it's okay to use it
        BTSerial.println(F("DMP ready! Waiting for first interrupt..."));
        dmpReady = true;

        // get expected DMP packet size for later comparison
        packetSize = mpu.dmpGetFIFOPacketSize();
    } else {
        BTSerial.print(F("DMP Initialization failed (code "));
        BTSerial.print(devStatus);
        BTSerial.println(F(")"));
    }
}


void loop() {
    // if programming failed, don't try to do anything
    if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize) {
    }

    // reset interrupt flag and get INT_STATUS byte
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();

    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();
        //BTSerial.println(F("FIFO overflow!"));

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {
        // wait for correct available data length, should be a VERY short wait
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

        // read a packet from FIFO
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        
        // track FIFO count here in case there is > 1 packet available
        // (this lets us immediately read more without waiting for an interrupt)
        fifoCount -= packetSize;

        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            BTSerial.print(int(ypr[0] * 180/M_PI));
            BTSerial.print(",");
            BTSerial.print(int(ypr[1] * 180/M_PI));
            BTSerial.print(",");
            BTSerial.print(int(ypr[2] * 180/M_PI));
            BTSerial.print("/");
        #endif
    }
    //delay(30);
    delay(100);

}

 

 

하려다가 mpu 기본주소가 0x68인데

ad0핀으로 어떻게 조정하는지부터 찾아봐야겟다.

 

 

이제 이해한게 mpu6050은 ad0로 주소를 2가지 경우로만 설정못한다고 한다.

 

https://forum.arduino.cc/t/how-to-connnect-3-mpu6050-to-arduino-uno/338636/3

 

 

 

저 내용 밑에보면

jremington이란 사람이

mpu6050 여러개 연결해서 

가져올것만 ad0 핀일 low하고 나머지는 high로 설정해주면 된다고 설명한다.

https://forum.arduino.cc/t/how-to-connnect-3-mpu6050-to-arduino-uno/338636/3

 

 

이게 괜찬은 방법인진 모르겟지만 일단 대충해보자

 

 

 

 

일단 지레밍턴? 말대로 해서 한번 만들어봤다.

 

프리징 같은걸로 우노보드랑 모듈들 배선 정리해서 올리고싶긴한데

유료화되서 쓰기도 힘들고

다른 적당한걸 못찾아서 그냥 만들기만함.

 

#include "I2Cdev.h"
#include <SoftwareSerial.h> 

#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu;
//MPU6050 mpu(0x69); // <-- use for AD0 high

#define OUTPUT_READABLE_YAWPITCHROLL


#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };


volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}



//RXD3, TXD4
SoftwareSerial BTSerial(4, 3);
int mpuPinNums[] = {5, 6};


void InitMPU(int pinNum);
void SendData(int pinNum);

void setup() {
  pinMode(5, OUTPUT);//MPU #1
  pinMode(6, OUTPUT);//MPU #2

  Serial.begin(115200);

  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
      Wire.begin();
      TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
      Fastwire::setup(400, true);
  #endif

  while (!Serial); // wait for Leonardo enumeration, others continue immediately

  for (int i = 0; i<2; i++)
    InitMPU(mpuPinNums[i]);
}


void loop() {
  for (int i = 0; i<2; i++)
    SendData(mpuPinNums[i]);

  Serial.println("");
  delay(100);
}


void InitMPU(int pinNum)
{
  for (int i = 0; i < 2; i++)
  {
    if (mpuPinNums[i] == pinNum)
      digitalWrite(pinNum, LOW);  //set selected mpu6050 addr 0x68
    else
      digitalWrite(mpuPinNums[i], HIGH);  //set other mpu6050 addr 0x69
  }
  Serial.print("start init pin ");
  Serial.println(pinNum);


  // initialize device
  mpu.initialize();

  // verify connection
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  // load and configure the DMP
  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();

  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(220);
  mpu.setYGyroOffset(76);
  mpu.setZGyroOffset(-85);
  mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

  // make sure it worked (returns 0 if so)
  if (devStatus == 0) {
      // turn on the DMP, now that it's ready
      Serial.println(F("Enabling DMP..."));
      mpu.setDMPEnabled(true);

      // enable Arduino interrupt detection
      Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
      attachInterrupt(0, dmpDataReady, RISING);
      //attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);

      mpuIntStatus = mpu.getIntStatus();

      // set our DMP Ready flag so the main loop() function knows it's okay to use it
      Serial.println(F("DMP ready! Waiting for first interrupt..."));
      dmpReady = true;

      // get expected DMP packet size for later comparison
      packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
      Serial.print(F("DMP Initialization failed (code "));
      Serial.print(devStatus);
      Serial.println(F(")"));
  }
}

void SendData(int pinNum)
{
    for (int i = 0; i < 2; i++)
    {
      if (mpuPinNums[i] == pinNum)
        digitalWrite(mpuPinNums[i], LOW);  //set selected mpu6050 addr 0x68
      else
        digitalWrite(mpuPinNums[i], HIGH);  //set other mpu6050 addr 0x69
    }

    // if programming failed, don't try to do anything
    if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize) {
    }

    // reset interrupt flag and get INT_STATUS byte
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();

    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {
        // wait for correct available data length, should be a VERY short wait
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

        // read a packet from FIFO
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        
        // track FIFO count here in case there is > 1 packet available
        // (this lets us immediately read more without waiting for an interrupt)
        fifoCount -= packetSize;

        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            Serial.print(pinNum);
            Serial.print(":");
            Serial.print(int(ypr[0] * 180/M_PI));
            Serial.print(",");
            Serial.print(int(ypr[1] * 180/M_PI));
            Serial.print(",");
            Serial.print(int(ypr[2] * 180/M_PI));
            Serial.print("/");
        #endif
    }
}

 

 

 

 

 

 

 

 

 

기존의 초기화, 각 가져오는 코드는 따로빼고

AD0 핀들 output 설정

 

int mpuPinNums[] = {5, 6};

void InitMPU(int pinNum);
void SendData(int pinNum);

void setup() {
  pinMode(5, OUTPUT);//MPU #1
  pinMode(6, OUTPUT);//MPU #2

  Serial.begin(115200);

  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
      Wire.begin();
      TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
      Fastwire::setup(400, true);
  #endif

  while (!Serial); // wait for Leonardo enumeration, others continue immediately

  for (int i = 0; i<2; i++)
    InitMPU(mpuPinNums[i]);
}

 

 

초기화 코드에서는

모든 mpu를 돌아가면서 초기화하는데

선택된 mpu만 주소를 0x68로 설정하고 수행

나머지는 초기화전 0x69로 설정

void InitMPU(int pinNum)
{
  for (int i = 0; i < 2; i++)
  {
    if (mpuPinNums[i] == pinNum)
      digitalWrite(pinNum, LOW);  //set selected mpu6050 addr 0x68
    else
      digitalWrite(mpuPinNums[i], HIGH);  //set other mpu6050 addr 0x69
  }
  Serial.print("start init pin ");
  Serial.println(pinNum);


  // initialize device
  mpu.initialize();

  // verify connection
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  // load and configure the DMP
  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();

  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(220);
  mpu.setYGyroOffset(76);
  mpu.setZGyroOffset(-85);
  mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

  // make sure it worked (returns 0 if so)
  if (devStatus == 0) {
      // turn on the DMP, now that it's ready
      Serial.println(F("Enabling DMP..."));
      mpu.setDMPEnabled(true);

      // enable Arduino interrupt detection
      Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
      attachInterrupt(0, dmpDataReady, RISING);
      //attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);

      mpuIntStatus = mpu.getIntStatus();

      // set our DMP Ready flag so the main loop() function knows it's okay to use it
      Serial.println(F("DMP ready! Waiting for first interrupt..."));
      dmpReady = true;

      // get expected DMP packet size for later comparison
      packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
      Serial.print(F("DMP Initialization failed (code "));
      Serial.print(devStatus);
      Serial.println(F(")"));
  }
}

 

 

루프의 경우 각 mpu 돌아가면서 각 출력하고 딜레이 주는식으로 정리

 

void loop() {
  for (int i = 0; i<2; i++)
    SendData(mpuPinNums[i]);

  Serial.println("");
  delay(50);
}

 

senddata의 경우

초기화때와 마찬가지로 선택된 mpu만 가져오도록 설정

void SendData(int pinNum)
{
    for (int i = 0; i < 2; i++)
    {
      if (mpuPinNums[i] == pinNum)
        digitalWrite(mpuPinNums[i], LOW);  //set selected mpu6050 addr 0x68
      else
        digitalWrite(mpuPinNums[i], HIGH);  //set other mpu6050 addr 0x69
    }

    // if programming failed, don't try to do anything
    if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize) {
    }

    // reset interrupt flag and get INT_STATUS byte
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();

    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {
        // wait for correct available data length, should be a VERY short wait
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

        // read a packet from FIFO
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        
        // track FIFO count here in case there is > 1 packet available
        // (this lets us immediately read more without waiting for an interrupt)
        fifoCount -= packetSize;

        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            Serial.print(pinNum);
            Serial.print(":");
            Serial.print(int(ypr[0] * 180/M_PI));
            Serial.print(",");
            Serial.print(int(ypr[1] * 180/M_PI));
            Serial.print(",");
            Serial.print(int(ypr[2] * 180/M_PI));
            Serial.print("/");
        #endif
    }
}

 

 

 

 

 

 

 

이 코드는 배터리가 아닌 PC전원으로 쓰면서

115200 시리얼 통신으로 가져와 쓰드록 정리

#include "I2Cdev.h"
#include <SoftwareSerial.h> 

#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu;
//MPU6050 mpu(0x69); // <-- use for AD0 high

#define OUTPUT_READABLE_YAWPITCHROLL


#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };


volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}


//RXD3, TXD4
SoftwareSerial BTSerial(4, 3);
int mpuPinNums[] = {5, 6};

void InitMPU(int pinNum);
void SendData(int pinNum);

void setup() {
  pinMode(5, OUTPUT);//MPU #1
  pinMode(6, OUTPUT);//MPU #2

  Serial.begin(115200);

  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
      Wire.begin();
      TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
      Fastwire::setup(400, true);
  #endif

  while (!Serial); // wait for Leonardo enumeration, others continue immediately

  for (int i = 0; i<2; i++)
    InitMPU(mpuPinNums[i]);
}


void loop() {
  for (int i = 0; i<2; i++)
    SendData(mpuPinNums[i]);

  Serial.println("");
  delay(50);
}


void InitMPU(int pinNum)
{
  for (int i = 0; i < 2; i++)
  {
    if (mpuPinNums[i] == pinNum)
      digitalWrite(pinNum, LOW);  //set selected mpu6050 addr 0x68
    else
      digitalWrite(mpuPinNums[i], HIGH);  //set other mpu6050 addr 0x69
  }
  Serial.print("start init pin ");
  Serial.println(pinNum);


  // initialize device
  mpu.initialize();

  // verify connection
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  // load and configure the DMP
  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();

  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(220);
  mpu.setYGyroOffset(76);
  mpu.setZGyroOffset(-85);
  mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

  // make sure it worked (returns 0 if so)
  if (devStatus == 0) {
      // turn on the DMP, now that it's ready
      Serial.println(F("Enabling DMP..."));
      mpu.setDMPEnabled(true);

      // enable Arduino interrupt detection
      Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
      attachInterrupt(0, dmpDataReady, RISING);
      //attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);

      mpuIntStatus = mpu.getIntStatus();

      // set our DMP Ready flag so the main loop() function knows it's okay to use it
      Serial.println(F("DMP ready! Waiting for first interrupt..."));
      dmpReady = true;

      // get expected DMP packet size for later comparison
      packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
      Serial.print(F("DMP Initialization failed (code "));
      Serial.print(devStatus);
      Serial.println(F(")"));
  }
}

void SendData(int pinNum)
{
    for (int i = 0; i < 2; i++)
    {
      if (mpuPinNums[i] == pinNum)
        digitalWrite(mpuPinNums[i], LOW);  //set selected mpu6050 addr 0x68
      else
        digitalWrite(mpuPinNums[i], HIGH);  //set other mpu6050 addr 0x69
    }

    // if programming failed, don't try to do anything
    if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize) {
    }

    // reset interrupt flag and get INT_STATUS byte
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();

    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {
        // wait for correct available data length, should be a VERY short wait
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

        // read a packet from FIFO
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        
        // track FIFO count here in case there is > 1 packet available
        // (this lets us immediately read more without waiting for an interrupt)
        fifoCount -= packetSize;

        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            Serial.print(pinNum);
            Serial.print(":");
            Serial.print(int(ypr[0] * 180/M_PI));
            Serial.print(",");
            Serial.print(int(ypr[1] * 180/M_PI));
            Serial.print(",");
            Serial.print(int(ypr[2] * 180/M_PI));
            Serial.print("/");
        #endif
    }
}

 

 

 

 

이번엔 블루투스로 변경

 

딜레이 100주면 115200 써도 되나모르겟다.

안되서 9600으로 다시진행

 

#include "I2Cdev.h"
#include <SoftwareSerial.h> 

#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu;
//MPU6050 mpu(0x69); // <-- use for AD0 high

#define OUTPUT_READABLE_YAWPITCHROLL


#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };


volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}



//RXD3, TXD4
SoftwareSerial BTSerial(4, 3);
int mpuPinNums[] = {5, 6};


void InitMPU(int pinNum);
void SendData(int pinNum);

void setup() {
  pinMode(5, OUTPUT);//MPU #1
  pinMode(6, OUTPUT);//MPU #2

  BTSerial.begin(9600);

  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
      Wire.begin();
      TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
      Fastwire::setup(400, true);
  #endif

  while (!Serial); // wait for Leonardo enumeration, others continue immediately

  InitMPU(5);
  InitMPU(6);
}


void loop() {


  SendData(5);
  SendData(6);
  BTSerial.println("");
  delay(100);
}


void InitMPU(int pinNum)
{
  for (int i = 0; i < 2; i++)
  {
    if (mpuPinNums[i] == pinNum)
      digitalWrite(pinNum, LOW);  //set selected mpu6050 addr 0x68
    else
      digitalWrite(mpuPinNums[i], HIGH);  //set other mpu6050 addr 0x69
  }
  BTSerial.print("start init pin ");
  BTSerial.println(pinNum);


  // initialize device
  mpu.initialize();

  // verify connection
  BTSerial.println(F("Testing device connections..."));
  BTSerial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  // load and configure the DMP
  BTSerial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();

  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(220);
  mpu.setYGyroOffset(76);
  mpu.setZGyroOffset(-85);
  mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

  // make sure it worked (returns 0 if so)
  if (devStatus == 0) {
      // turn on the DMP, now that it's ready
      BTSerial.println(F("Enabling DMP..."));
      mpu.setDMPEnabled(true);

      // enable Arduino interrupt detection
      BTSerial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
      attachInterrupt(0, dmpDataReady, RISING);
      //attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);

      mpuIntStatus = mpu.getIntStatus();

      // set our DMP Ready flag so the main loop() function knows it's okay to use it
      BTSerial.println(F("DMP ready! Waiting for first interrupt..."));
      dmpReady = true;

      // get expected DMP packet size for later comparison
      packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
      BTSerial.print(F("DMP Initialization failed (code "));
      BTSerial.print(devStatus);
      BTSerial.println(F(")"));
  }
}

void SendData(int pinNum)
{
    for (int i = 0; i < 2; i++)
    {
      if (mpuPinNums[i] == pinNum)
        digitalWrite(mpuPinNums[i], LOW);  //set selected mpu6050 addr 0x68
      else
        digitalWrite(mpuPinNums[i], HIGH);  //set other mpu6050 addr 0x69
    }

    // if programming failed, don't try to do anything
    if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize) {
    }

    // reset interrupt flag and get INT_STATUS byte
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();

    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {
        // wait for correct available data length, should be a VERY short wait
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

        // read a packet from FIFO
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        
        // track FIFO count here in case there is > 1 packet available
        // (this lets us immediately read more without waiting for an interrupt)
        fifoCount -= packetSize;

        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            BTSerial.print(pinNum);
            BTSerial.print(":");
            BTSerial.print(int(ypr[0] * 180/M_PI));
            BTSerial.print(",");
            BTSerial.print(int(ypr[1] * 180/M_PI));
            BTSerial.print(",");
            BTSerial.print(int(ypr[2] * 180/M_PI));
            BTSerial.print("/");
        #endif
    }
}

 

 

아까 유선으로 할때도 그랬지만

종종 데이터가 2개다 출력되지 않고 1개만 출력되는 경우가 생긴다.

 

조건문에서 생긴 문제같은데

따로 확인해봐야할듯

9600 보드레이트, 100 딜레이줫을때 잘 나온다.

 

이런식으로 10개까지 늘려도 될것같은데

esp32는 언제쓸까 .

 

 

 

 

 

 

이번 주말에 대충 MPU6050 하나가지고 블루투스 통해서

언리얼에서 액터 회전까지 돌리는건 잘 하긴했는데

 

이 다음은 MPU6050 여러개 준비해서 시험해볼 차례였지만

나머지 땜질해야되서 시작을 못함

 

땜질은 내일하고 일단 블렌더 시작하려했는데

가지고 있는 책 몇개 보니까

 

좀 책 내용이 이상하다는 생각이 든다.

블렌더에서 제공하는 기능이 많은건 알지만

정말 기초적인것 조차 연습이 안되있는 상태에서 따라가기 힘든?

 

 

국내 블렌더 기초 책 몇권을 보면서

앞에서 툴 설명 요약 몇개 해주다가

뭔가 만드는걸로 넘어가는식이다.

 

블랜더에서 선택하나만 해도 점, 선, 면이 있는데

책에서 설명해주든 설명을 안하던

따라가려고하면 놓치는 부분이 조금씩 생기면서 최종 결과물이 책에서 설명해준것과 뭔가 다르다!

 

특히 따라하기 힘든게 인셋페이스 하는 기능인가 

내가할때는 책에서 나오는 식으로 잘 따라가지지가 않더라.

 

퓨전 360 다룰때는 이렇게 하기 힘들다는 느낌을 받은적이 없는데

 

 

 

프로그래밍 언어 기초 서적같은 경우

초반에는 + 1, + 1, + 1 조금씩 살을 붙여나가면서 익숙해진다는 느낌이지만

 

 

국내 블랜더 서적은

초반부터 제대로 연습한적 없는 기능을 다루다보니 + 10, +10, + 10 해야하는 느낌?

 

 

 

칼질한번 해본적 없는 사람에게

칼 종류, 써는 방법 대충 설명해주고

감자도 안썰어본 상태에

연습이랍시고 산 생선을 회뜨게 만들라고 하는 느낌일까..

 

 

 

 

도저히 책으로 공부하기는 힘들겠다 싶어서

구글링하다보니

블렌더 구루인가 강의 추천하는데 

 

이사람걸 보는게 나아보인다.

 

전에 크러시코스 컴퓨터 사이언스 영상을 정말 감탄하면서 봤었는데

어중간한 자료보는것보단 강의력 좋은게 나은듯

 

역시 경력이 많다고 강의력 설명력이 좋은건 아닌것같다.

 

 

 

 

 

 

https://arca.live/b/3d3d/27469566

 

블랜더 공부하실때 자료는 어디서 찾으시나요? - 3DCG 채널

블랜더가 굉장히 편하고 좋아보여서 공부하려고 자료를 찾아보는데 막막해서요따로 학원을 다니시거나 책 같은걸 사시나요? 아니면 그냥 유튜브로 공부하시나요?

arca.live

 

https://gall.dcinside.com/mgallery/board/view/?id=blender&no=10074

 

 

 

 

블랜더를 어떻게 공부하는게 좋을까 구글링하다 찾은글인데 꽤 설명을 잘한듯하다.

 

https://gall.dcinside.com/mgallery/board/view/?id=blender&no=30801&exception_mode=recommend&s_type=search_subject_memo&s_keyword=%EA%B3%B5%EB%B6%80&page=2

 

 

 

 

 

대충 블랜더갤 사람들 말로는

 

블렌더 구루의 도넛 한뒤

https://www.youtube.com/watch?v=B0J27sf9N1Y

 

 

30일 챌린지 하면 기본기를 꽤 채울수 있나보다.

여윽시 따거..

https://www.youtube.com/playlist?list=PLybXPPxX5z_EtuNPf_k00XPnsX79lbypr

 

30 Days Modeling Challenge in Blender with Wenbo Zhao

How about learning Blender by doing small modeling practice every day for 30 days straight? Why not? Join me NOW!

www.youtube.com

 

 

+ Recent posts