728x90

통계를 배워야 하는 이유

- 무엇이 최선의 선택인가?

=> 데이터 주도 의사결정

 

통계학

- 실험으로 발견된 차이가 우연으로 예측된 차이보다 큰 것을 증명

- 통계 분석 : 그 결과가 우연인지 아닌지, 의미잇는 것은지 아닌지 분석하는 과정

 

통계학 배워서 할것들

- 데이터 시각화

- 통계적 시험

- 통계 개념 이해

- 여러 방법론 사용

 

 

 

고전과 현대 통계학

- 고전 통계학 : 수식과 알고리즘으로 소통

- 현대 통계학 : 데이터 기반

 

 

빅데이터 정의

- 4v도 있지만.

- 타임 스탬프(이 데이터가 언재)와 로케이션(어디서 생성되었는가)을 갖는 데이터

 

 

데이터 분석시 고려사항들

- 보정 adjust 

- 쪼개기 faceting

- 아웃라이어

- 결측치 

 

보정

- 해당 변수의 영향을 고려하는 것

ex) 폐암과 연관성이 높은 요소라고해서 무조건 암의 원인이라고 판단할수는 없음

 

보정의 예시

- 교회가 많아지면 범죄율도 증가한다

 => 인구가 늘면 교회도 늘고 범죄율도 증가

- 냉장고 보급률과 위암 환자에는 큰 관계가 있다

 => 사실 소득이 늘면서 냉장고 보급과 의료 서비스가 좋아짐. 위암 환자수가 증가

 

 

심슨의 역설

- 쪼개서 보아야 함. => 하위 그룹 분석

 

아웃라이어의 문제점

- 이상치로 인해 추정 값이 너무 심하게 변함

=> 평균, 회귀계수

 

 

결측치 NA Not Available

- 데이터에 결측치가 있는경우 분석되지 않을수도 있다.

- 데이터에 결측치가 포함된 경우 모든 통계값은 NA를 리턴하게되어 없애주도록 해야함

 

 

 

 

 

 

 

 

 

통계 분류

- 기술 통계 descriptive statistics : 수집한 데이터를 요약, 묘사

- 추론 통계 inference statistics : 모집단(알려고하는집단, 전체 집단)을 대표할수 있는 표본집합(모집단을 샘플링)으로 추론

 

기술 통계

- 수집된 데이터를 요약, 묘사(수치적, 시각화 등)

- 수치적 묘사 : centering 지표 ( 평균, 중앙값, 최빈값), spread 지표(분산, 표준편차), 웨도, 첨도 등

 

centering 지표

- 평균mean : 데이터의 합/ 데이터 갯수

- 중앙값 median : 데이터 정렬 후 가운데 값

- 절삭 평균 truncated mean : 양끝값을 제거 후 평균

=> 자료의 중심 측도 만으로 내용을 설명하기에는 부족함. spread 지표로 묘사

 

 

spread 지표

- 분산 variance : 평균에서 얼마나 멀어지는지. 데이터가 퍼진 정도

 

그 외 지표

- 왜도 skewness : 자료의 치우친 정도. 자료 대칭성 측도.

- 첨도 kurtosis : 얼마나 뾰족한가. 봉오리 높이 측도

 

 

 

 

 

추론 통계 inference statistics

- 수집 데이터로 추론, 예측하는 기법

- 전체 집단을 알수없기 때문 ->제한된 데이터 표본

- 모집단 population : 알고자 하는 전체 집단

- 표본집합 sampling : 모집단으로부터 추출한 집단

 

 

 

다양한 표본 추출 방법

- SRS Simple Random Sampling : 단순 랜덤 샘플링

- 층화

- 집락

- 계통

- PPS Proportional to Population Size : 모집단 크기에 비례하도록 추출

 

구간 추정

- 신뢰 구간

 

 

 

 

300x250

'수학 > 통계' 카테고리의 다른 글

데이터분석 - 6. R 시각화  (0) 2020.10.20
데이터분석 - 5. 확률기초  (0) 2020.10.19
데이터분석 - 4. R그래프들  (0) 2020.10.19
데이터분석 - 3. R기초 2  (0) 2020.10.19
데이터분석 - 2.R 기초  (0) 2020.10.19
728x90

 

 

 

300x250
728x90

300x250
728x90

300x250
728x90

300x250
728x90

 

 

컴퓨터 개론 introduction to computer science

- 컴퓨터 과학 전반에 대해 소개

-> 자료 구조, 알고리즘, 컴퓨터구조, 운영체제, 네트워크, 프로그래밍 언어 등

 

 

자료 처리기data processor로서의 컴퓨터

- 자료 data를 입력받아 처리 process 후 결과result를 출력

- ex. 계산기

=> 자료를 처리하는 기계만으로 이해하기는 불충분

 

 

프로그램이 가능한 자료 처리기로서의 컴퓨터

- 입력 -> 자료 처리 + 프로그램 -> 출력

 

 

프로그램 program

- 자료를 어떻게 처리할지 정의한 명령 집합

- 프로그래밍 과정의 결과물

-> 기계어 파일, 실행 파일 exe

 

 

 프로그래밍 과정

- 간단하게 코딩이라 부름

- 문제 해결을 위한 흐름(알고리즘)을 정의함

 

 

처리 속도 단위

- ms : 밀리 세컨드 $10^{-3}$초

- $\mu$s : 마이크로 세컨드 $10^{-6}$초

- ns : 나노 세컨드 $10^{-9}$초

- ps : 피코 세컨드 $10^{-12}$초

 

 

 

 

 

 

 

 

컴퓨터 발전 과정

- ~ 1930년 : 기계식 계산기

- 1930 ~ 1950 : 전자식 컴퓨터

 -> 1942, ABC : 선형 방정식 푸는 컴퓨터

 -> 1944, Colossus : 앨런 튜링, 독일 암호 해독

  ****************** 위는 특수 목적용 ************

 -> 1946, ENIAC : 최초 완전 전자식 범용 컴퓨터

                       (외부에서 프로그램이 저장 => 실행 프로그램이 컴퓨터 외부에 존재, 데이터만 내부 저장)

 -> 1950, EDVAC : 내장 프로그램 방식 최초 컴퓨터

                       (컴퓨터 내부에 프로그램이 저장됨)

 

 

 

 

 

 

* 앨런 튜링 : 현대 컴퓨터 고안(튜링 머신),

튜링 머신

- 태잎과 헤드가 존재

- 태잎에 데이터 읽기 쓰기

- 해드를 이동시켜 읽고쓸 태잎을 변경

 

http://www.aistudy.co.kr/computer/turing_machine.htm

 

 

 

 

 

 

 

세대별 컴퓨터 분류

1세대 1950 ~ 1959

- 진공관

 

2세대 1959 ~ 1965

- 트랜지스터

- 포트란, 코볼

 

3세대 1965 ~ 1975

- 집적회로

- SW 등작

 

4세대 1975 ~ 1985

- 초고밀도집적회로

- 마이크로 컴퓨터 등장 8800

- 네트워크 

 

5세대 1985 ~

- 현재

 

 

 

 

 

 

 

 

 

 

컴퓨터 분류

1. 컴퓨터 사용 목적에 따른 분류

- 범용 컴퓨터

- 전용 컴퓨터

 

2. 자료 표현 방식

- 디지털 컴퓨터 : 이산적인 값을 처리

- 아날로그 컴퓨터 : 연속적인 입력양을 그대로 사용

 

3. 성능에 따른 분류

- 슈퍼 컴퓨터

- 대형 컴퓨터

- 미니 컴퓨터

- 워크 스테이션

- 마이크로 컴퓨터

 

 

 

 

 

 

 

컴퓨터 과학이란? 

- 컴퓨터 제작하는 학문 ..?

- 프로그램 개발하는 학문 ..?

=> 컴퓨터를 이용하여 데이터를 통해 다양한 문제와 방법들을 다루는 학문

 

 

프로그램과 알고리즘

- 컴퓨터는 자료를 처리해서 결과(정보)를 얻는 기계

-> 문제를 해결하기 위한 명령어 집합인 프로그램을 사용

-> 알고리즘 : 문제 해결을 위한 흐름 -> 프로그램

 

 

 

관련 학문

- 자료 : 자료구조, 파일처리, 데이터베이스

- 정보 : 컴퓨터 시스템, 디지털 논리구조, 컴퓨터 구조

- 프로그램 : 운영체제, 컴파일러, 프로그래밍언어 ,정보통신, 컴퓨터그래픽스

- 알고리즘 : 이산구조, 계산이론, 인공지능, 알고리즘, 오토마타

=> 전반적인 분야를 파악해야함

 

 

 

 

 

 

컴퓨터 공학 computer engineering과 컴퓨터 과학computer science의 차이

- 컴퓨터 공학 engineering : 가성비 좋은 제품을 만들기 위해 HW와 SW 조합에 초점

- 컴퓨터 과학 science : 문제 해결의 효율성과 실현 가능성에 초점

 

 

 

 

시스템 system

- 원하는 목적을 달성하기 위해 여러가지 요소들이 모여 연결된 체계

 

HW 하드웨어 : 눈으로 볼수있는 장치로 물리적 기계 및 전자장치

 

 

폰 노이만 구조와 하버드 구조

- 컴퓨터 내부 구조, 처리 과정을 정의한 것

- 컴퓨터 구조는 대표적으로 폰노이만 구조와 하버드 구조가 있음

- 대부분은 폰 노이만 구조를 채택

- 데이터 버스와 명령어 버스가 통합 -> 폰노이만 구조

- 데이터 버스와 명령어 버스가 분리됨 -> 하버드 구조

 

 

 

 

 

4개의 서브시스템

기억 장치

- 데이터와 명령어(프로그램)을 저장하는 곳

-> 주기억 장치(RAM, ROM), 보조기억장치(HDD, SSD)

 

산술논리연산장치 ALU

- 데이터 산술(+-*/), 논리(and, or)연산하는 장치

 

제어 장치 Control Unit

- 기억장치, ALU, 입출력 장치 등 동작 제어

=> CPU = ALU + CU + Register

 

 

입출력 장치 I/O Device

- 입력 : 키보드, 마우스, 마이크

- 출력 : 모니터, 프린터, 스피커 

 

 

 

 

내장 프로그램 stored program

- 실행될 프로그램은 메모리에 저장 stored or 적재 load 되어야 함

- 프로그램과 데이터는 비트 패턴으로 메모리 상에 표현

 

 

자료와 정보

- I = P(D)

- I는 정보

- P는 처리

- D는 자료

- 자료D를 처리P하여 정보 I를 취득

 

 

 

자료의 형태

- 문자, 숫자, 이미지, 오디오, 비디오 등

=> 다 비트로 표현

 

 

 

 

 

 

 

 

 

 

 

 

 

 

자료 단위

- 비트 binary digit : 0과 1을 표현

- 바이트 byte : 비트 8개

- 킬로 바이트 KB kilo byte : 바이트 $2^10$

- MB 메가바이트, GB기가바이트, TB테라바이트, PB페타바이트

- 워드 word : 컴퓨터 연산의 기본 단위가 되는 정보 양 -> 32비트, 64비트

 

 

 

진법 number system

- 수를 세는 단위

- 2, 8, 10, 16진법

- 2진법은 읽거나 오류 찾기 힘듬

-> 8진법, 16진법 사용

- 010 : 8진법으로 2

 * 앞에 0이 붙으면 8진법 수

- 0x0a : 16진법으로 10

 * 앞에 0x가 붙으면 16진법수

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

300x250

'컴퓨터과학 > 컴퓨터, OS' 카테고리의 다른 글

HWSW - 2. 컴파일  (0) 2020.08.06
HWSW - 1. MCU  (0) 2020.08.05
os만들기 - 25. GDT와 IDT 다루기  (0) 2020.08.04
os만들기 - 24. 변수 표시하고, 마우스 띄우기  (0) 2020.08.03
os만들기 - 23. 문자(열) 처리  (0) 2020.08.03
728x90

밸런싱 예제를 살펴봤으니

 

 

모터를 사용해보려고 한다.

 

그런데 모터를 사용하려면 모터 드라이버를 써줘야 한다고 하더라

 

 

 

 

이전에는 모터를 정밀하게 제어하려면 필요하다고만 알았지

 

정확하게 왜 필요한지는 잘 몰랐다.

 

잠깐 검색한 자료

 

다음 링크에서 모터 드라이버의 역활에 대해서 설명해주고 있다.

 

ref : https://blog.naver.com/ycpiglet/222050336319

 

 

 

 

 

 

그래도 모터드라이버 준비하기전에 한번 돌아가는지 궁금해서

 

아래 처럼 준비해보고 돌려봤다.

 

 

 

 

 

 

 

잘 돌아간다.

 

 

 

 

 

아까 본 글에서는

 

아두이노 출력 핀에서는 20~30mA밖에 못내서 안된다고 하던데

 

왜그런가 찾아보았다.

 

 

 

 

 

 

다음 링크에 따르면

 

ref : https://electronics.stackexchange.com/questions/67092/how-much-current-can-i-draw-from-the-arduinos-pins

 

아두이노 uno보드의 atmega328p는

 

일반 핀에서 40mA가 나오는게 맞지만

 

내가 사용한 Vcc핀에서는 200mA가 나와서 모터가 동작한듯 하다.

 

 

 

그러면 정말 일반 입출력핀에서 안되는지 보자

 

 

5번 핀으로 출력하는 예제

int output = 5; 

void setup() {
  pinMode(output, OUTPUT);
}

void loop() {
  analogWrite(output, 100);
}

 

 

진짜 5번 핀으로 연결시켰더니 동작되질 않는다....

 

 

 

 

 

오실로스코프 상에서는 제대로 나오고 있는걸 봐선

 

정말 전류가 부족해서 그런것같다.

 

 

 

 

 

 

 

 

 

나중에는 아래 링크 처럼

 

모터 드라이버랑 연결해서 돌려봐야겠다.

 

ref : https://codingrun.com/111

 

 

 

 

 

 

 

 

 

 

 

300x250
728x90

일단 mpu6050 의 dmp 기능으로 roll, pitch, yaw 출력되는 예제를 돌려보고

 

이번에는 밸런싱 로봇 예제를 살펴보았다.

 

ref : https://maker.pro/arduino/projects/build-arduino-self-balancing-robot

 

 

 

 

 

 

 

이 예제에서는 아두이노 나노를 기반으로 L298N 모터 드라이버와 mpu6050 등이 연결되어잇다.

 

 

잠시 L298N 모터 드라이버를 다시 살펴보면

 

 

다음 링크에서 L298N 모터 드라이버의 핀에 대해서 잘 설명해주고 있다.

 

ref :https://m.blog.naver.com/PostView.nhn?blogId=eduino&logNo=221030701469&proxyReferer=https:%2F%2Fwww.google.com%2F

 

 

나노(나는 우노보드를 사용할거지만)와 연결하는 핀이 ENA/ENB, IN1, IN2, IN3, IN4가 있는데

 

ENA와 ENB는 PWM 신호로 각 모터의 속도 제어용

 

중간에 4개의 IN1 ~ 4는 방향 지정용이라 한다.

 

 

 

 

모터 드라이버는 잠깐 나두고

 

일단 아두이노 소스를 보면 다음과 같다.

 

 

 

PID, 모터 제어, MPU6050 내용들이 섞여있다보니 다소 길어보인다.

 

 

#include <PID_v1.h>
#include <LMotorController.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"

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

#define MIN_ABS_SPEED 20

MPU6050 mpu;

// 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
VectorFloat gravity; // [x, y, z] gravity vector
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector

//PID
double originalSetpoint = 173;
double setpoint = originalSetpoint;
double movingAngleOffset = 0.1;
double input, output;

//adjust these values to fit your own design
double Kp = 50;   
double Kd = 1.4;
double Ki = 60;
PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

double motorSpeedFactorLeft = 0.6;
double motorSpeedFactorRight = 0.5;
//MOTOR CONTROLLER
int ENA = 5;
int IN1 = 6;
int IN2 = 7;
int IN3 = 8;
int IN4 = 9;
int ENB = 10;
LMotorController motorController(ENA, IN1, IN2, ENB, IN3, IN4, motorSpeedFactorLeft, motorSpeedFactorRight);

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


void setup()
{
// join I2C bus (I2Cdev library doesn't do this automatically)
#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

mpu.initialize();

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
mpu.setDMPEnabled(true);

// enable Arduino interrupt detection
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();

// set our DMP Ready flag so the main loop() function knows it's okay to use it
dmpReady = true;

// get expected DMP packet size for later comparison
packetSize = mpu.dmpGetFIFOPacketSize();

//setup PID
pid.SetMode(AUTOMATIC);
pid.SetSampleTime(10);
pid.SetOutputLimits(-255, 255); 
}
else
{
// ERROR!
// 1 = initial memory load failed
// 2 = DMP configuration updates failed
// (if it's going to break, usually the code will be 1)
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.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)
{
//no mpu data - performing PID calculations and output to motors 
pid.Compute();
motorController.move(output, MIN_ABS_SPEED);

}

// 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();
Serial.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;

mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
input = ypr[1] * 180/M_PI + 180;
}
}

 

 

 

처음에는 사용하는 라이브러리들 인클루드, 정의할것들 정의해주고

 

 

 

 

 

 

 

mpu 6050 관련 변수 선언

 

 

쿼터니언, 오일러각, 중력 벡터 변수 선언

 

 

 

PID 관련 변수들도 선언하여

pid 인스턴스 생성

 

 

 

 

모터 제어기 변수 선언,

인스턴스도 초기화

타이머와 인터럽트 관련 내용

 

 

 

이제 셋업문으로 들어와보자

 

"I2Cdev.h" 내부를 보면 I2CDEV_IMPLEMENTATION이 정의되어 있으므로

 

Wire.begin()과 TWBR = 24;이 수행된다.

 

이후 시리얼 통신 시작

 

 

 

 

이후는 mpu6050 초기화과정

 

이전에 봤던 mpu6050 예제와 동일

 

 

 

 

 

mpu6050이 잘 초기화되면

 

DMP 사용할 준비와

pid 변수들이 설정된다.

 

초기화 실패시 에러 출력

 

 

 

135 : dmp 데이터가 준비안되면 시간이 조금 지난뒤 다시수행

 

138 ~ 145 : mpu 인터럽트가 발생안하고 fifo데이터가 패킷 사이즈보다 작은 경우

        => PID 계산, 모터 이동

 

나머지는 인터럽트 플래그 리셋, 인터럽트 상태와 fifocount 취득

 

 

오버플로 체크

- 피포 데이터가 너무 쌓이거나 인터럽트 상태가 0x10인 경우 mpu 리셋

 

 

dmp 데이터가 준비되면,

1. fifo 관련 읽고, 카운팅 루틴

2. fifo 데이터로 쿼터니언 계산 -> 중력 가속도 계산 -> 오일러각 계산

3. 오일러각 출력+

 

 

 

 

 

대강 코드는 이정도로 정리하고

 

Pid와 LmotorController는 조금봐야될거같다.

 

 

일단 PID부터

 

 

 

 

 

 

PID  헤더는 대충 pass

 

 

 

 

 

PID 클래스

 

pid 게인, 제어 방향, 시간, 포인터 변수 등을 지정

 

 

 

 

1. now 처음 시간 취득

2. timechange : 시간 변화 취득

3. 샘플링 타임보다 같거나 크면 -> 시간이 충분히 지나면 pid 로직 수행

4. ino 파일에서 전달받은 myInput을 input으로 초기화

* myInput은 ypr에서 피치각

5. setPoint - input으로 오차 구함. setPoint는 균형 상태에서의 피치각

6. 적분항 Iterm, 미분항 DTerm 계산

7. pid 출력 계산 

 

 

 

ino 파일에서 pid.compute()를 호출하여 pid 출력이 계산되면

 

이대로 모터 컨트롤러가 이동시킨다.

 

 

 

 

우선 모터 컨트롤러 클래스

 

우선 모터 A, B 상수와 핀 번호들이 지정된다.

 

 

 

 

ino 파일에서 호출한 move 함수

 

pid의 output이 여기서는 speed로 사용된다.

 

속도가 음수면 -1 방향으로 

 

음수 시

 speed가 minAbsSpeed보다 크면 minAbsSpeed

 speed가 -255보다 크면 speed 사용

 => - minAbsSpeed(= -20) > speed  > -255

  -> speed가 -20보다 크면 -20 사용

  -> speed가 -255보다 작으면 -255사용

 

속도의 범위 20 ~ 255, -20 ~ -255

 

 

ena, enb로 realSpeed * 모터 상수로 pwm 신호가 전달

 

 

 

대강 소스 흐름은 이정도만 보면 될거같다.

 

구현이 문제지만..

300x250
728x90

상보필터 complementary filter

- 각 센서 데이터에 alpha 만큼의 가중치를 줘서 서로 보완하는 필터

- 예시 : 각 변화율 자이로 x에 가속도 x 값을 같이 반영해서 롤 각을 구함

 

 

 

 

raw mpu데이터로 roll, pitch, yaw를 출력하도록

 

상보 필터 예제를 찾다가

 

ref : https://blog.naver.com/PostView.nhn?blogId=ysahn2k&logNo=221385063966&categoryNo=0&parentCategoryNo=0&viewDate=¤tPage=1&postListTopCurrentPage=1&from=postView

 

위 링크에서 예제와 잘 설명이 되어있더라

 

 

 

원본 소스에서 주석 처리되거나 필요없는 부분을 제거해서 돌려봤

 

 

으나..

 

생각보다 롤, 피치, 요가 잘 나오지 않는다.

 

 

 

#include <Wire.h>
#define MPU6050_AXOFFSET 158
#define MPU6050_AYOFFSET 9
#define MPU6050_AZOFFSET -91
#define MPU6050_GXOFFSET 19
#define MPU6050_GYOFFSET -42
#define MPU6050_GZOFFSET -26

long sampling_timer;
const int MPU_addr=0x68;  // I2C address of the MPU-6050

int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; // Raw data of MPU6050
float GAcX, GAcY, GAcZ; // Convert accelerometer to gravity value
float Cal_GyX,Cal_GyY,Cal_GyZ; // Pitch, Roll & Yaw of Gyroscope applied time factor
float acc_pitch, acc_roll, acc_yaw; // Pitch, Roll & Yaw from Accelerometer
float angle_pitch, angle_roll, angle_yaw; // Angle of Pitch, Roll, & Yaw
float alpha = 0.96; // Complementary constant

void setup(){
  Wire.begin();
  init_MPU6050();
  Serial.begin(9600);
}

void loop(){

  // Read raw data of MPU6050
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,14,true);  // request a total of 14 registers
  AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)     
  AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

  // Raw data of accelerometer corrected by offset value
//  AcX -= MPU6050_AXOFFSET;
//  AcY -= MPU6050_AYOFFSET;
//  AcZ -= MPU6050_AZOFFSET;

  // Convert accelerometer to gravity value
  GAcX = (float) AcX / 4096.0;
  GAcY = (float) AcY / 4096.0;
  GAcZ = (float) AcZ / 4096.0;

  // Calculate Pitch, Roll & Yaw from Accelerometer value
  // Reference are 
  // https://engineering.stackexchange.com/questions/3348/calculating-pitch-yaw-and-roll-from-mag-acc-and-gyro-data
  // https://www.dfrobot.com/wiki/index.php/How_to_Use_a_Three-Axis_Accelerometer_for_Tilt_Sensing
  acc_pitch = atan ((GAcY - (float)MPU6050_AYOFFSET/4096.0) / sqrt(GAcX * GAcX + GAcZ * GAcZ)) * 57.29577951; // 180 / PI = 57.29577951
  acc_roll = - atan ((GAcX - (float)MPU6050_AXOFFSET/4096.0) / sqrt(GAcY * GAcY + GAcZ * GAcZ)) * 57.29577951; 
  acc_yaw = atan (sqrt(GAcX * GAcX + GAcZ * GAcZ) / (GAcZ - (float)MPU6050_AZOFFSET/4096.0)) * 57.29577951; 



  // Calculate Pitch, Roll & Yaw by Complementary Filter
  // Reference is http://www.geekmomprojects.com/gyroscopes-and-accelerometers-on-a-chip/
  // Filtered Angle = α × (Gyroscope Angle) + (1 − α) × (Accelerometer Angle)     
  // where α = τ/(τ + Δt)   and   (Gyroscope Angle) = (Last Measured Filtered Angle) + ω×Δt
  // Δt = sampling rate, τ = time constant greater than timescale of typical accelerometer noise
  angle_pitch = alpha * (((float)(GyX - MPU6050_GXOFFSET) * 0.000244140625) + angle_pitch) + (1 - alpha) * acc_pitch;
  angle_roll = alpha * (((float)(GyY - MPU6050_GYOFFSET) * 0.000244140625) + angle_roll) + (1 - alpha) * acc_roll;
  angle_yaw += (float)(GyZ - MPU6050_GZOFFSET) * 0.000244140625; // Accelerometer doesn't have yaw value
  


  // Print value of Pitch, Roll & Yaw reflected Complementary Filter
  Serial.print(" | angle_pitch = "); Serial.print(angle_pitch);
  Serial.print(" | angle_roll = "); Serial.print(angle_roll);
  Serial.print(" | angle_yaw = "); Serial.println(angle_yaw);



  // Sampling Timer
  while(micros() - sampling_timer < 4000);
  sampling_timer = micros(); //Reset the sampling timer  
}

void init_MPU6050(){
  //MPU6050 Initializing & Reset
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);

  //MPU6050 Clock Type
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0x03);     // Selection Clock 'PLL with Z axis gyroscope reference'
  Wire.endTransmission(true);

  //MPU6050 Gyroscope Configuration Setting
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x1B);  // Gyroscope Configuration register
  Wire.write(0x18);     // FS_SEL=3, Full Scale Range = +/- 2000 [degree/sec]
  Wire.endTransmission(true);

  //MPU6050 Accelerometer Configuration Setting
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x1C);  // Accelerometer Configuration register
  Wire.write(0x10);     // AFS_SEL=2, Full Scale Range = +/- 8 [g]
  Wire.endTransmission(true);

  //MPU6050 DLPF(Digital Low Pass Filter)
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x1A);  // DLPF_CFG register
  Wire.write(0x00);     // Accel BW 260Hz, Delay 0ms / Gyro BW 256Hz, Delay 0.98ms, Fs 8KHz 
  Wire.endTransmission(true);
}



//https://blog.naver.com/PostView.nhn?blogId=ysahn2k&logNo=221385063966&categoryNo=0&parentCategoryNo=0&viewDate=&currentPage=1&postListTopCurrentPage=1&from=postView

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

생각해보니 mpu6050에서 dmp 기능으로 

 

오일러 각을 잘 출력해주는데 잊고있었다.

 

ref : https://www.teachmemicro.com/orientation-arduino-mpu6050/

 

 

 

그동안 써왔던 핀 연결에다가 인터럽트 핀도 D2에 연결하자

 

 

 

 

electrocats의 mpu6050 라이브러리를 다운받고

 

 

 

 

 

DMP 기능으로 오일러각 출력하는 예제가 있다.

 

 

 

 

중간에 이 줄을 남겨두면 키 입력받을때까지 동작을 안하니 지워주고

 

업로드하자

 

 

 

 

 

 

 

 

 

 

 

 

값은 yaw pitch roll 순으로 나온다

 

1. yaw

 

 

2. pitch

 

 

 

 

3. roll

 

 

 

 

 

 

 

 

 

 

 

300x250
728x90

 

 

gyro xyz : 각 축 방향에 대한 각 변화량

acc xyz : 각 축 방향의 가속도

 

 

 

mpu 6050의 각 축에 대해서 잘 나온 그림이 있어 가져왔다.

 

https://www.electronicwings.com/sensors-modules/mpu6050-gyroscope-accelerometer-temperature-sensor-module

 

 

 

평행이동과 회전 운동의 관계

ref : https://m.blog.naver.com/PostView.nhn?blogId=kb986213&logNo=70190081308&targetKeyword=&targetRecommendationCode=1

 

 

 

 

1. 센서를 가만히 나둔 경우

 

기본적으로 gyro xyz는 각 변화량으로 축 방향으로 변화가 있을때만 값의 변화가 크게 일어난다.

-> 가만히 있으면 g xyz는 큰 변화는 없음

 

acc xyz는 각 축 방향에 대한 가속도를 출력하고 있으나 센서가 움직이지 않는 상태에서는 중력가속도의 영향으로

-> acc z축값만 크고 다른 값들은 크게 변하지 않는다.

 

=> 센서에 동작이 없으므로 ax, ay/ gxyz는 큰 변화없이  az만 15000정도로 유지

 

 

 

 

 

2. 회전 시킨 경우

2.1 gyro

회전하는 순간의 각 속도가 gx, gy, gz로 출력

-> 회전하는 동안만  속도가 0이 아니나 회전을 멈춘 순간 원상태로 돌아옴

2.2 acc

가속도계는 중력 가속도의 영향으로 x/y축 방향으로 양방향 음방향 회전에 따라 값이 유지

 

 

 

 

 

 

 

3. 선운동의 경우

 

3.1 x, y 선운동

 

 

 

 

 

3.2 z축 선운동

 

15000 정도 되던 acc z값이

내려가는 순간 -32768 까지 떨어짐

이후 돌아옴

 

 

 

 

 

 

300x250

+ Recent posts