질문게시판 > AVR 자이로센서사용

TODAY926 TOTAL2,160,937
사이트 이용안내
Login▼/회원가입
최신글보기 질문게시판 기술자료 동영상강좌

아두이노 센서 ATMEGA128 PWM LED 초음파 AVR 블루투스 LCD UART 모터 적외선


BASIC4MCU | 질문게시판 | AVR 자이로센서사용

페이지 정보

작성자 하하루다 작성일2018-01-16 19:41 조회20,175회 댓글5건

본문

	

자이로센서를 사용해서 자이로 XY 가속도XY의 값을 CLCD에 나타내는데 목표를 두고 공부하고 있는 학생입니다. MCU는 ATMGEGA128을 사용하려고 합니다.

책과 구글링을 통해 소스를 만들어가는중  타이머를 이용해 CLCD에 값을 뛰워보려는데 어떻게 해야할지 몰라 글을 남깁니다.

#include <util/delay.h>

#include <avr/signal.h>

#include <avr/interrupt.h>      //인터럽트 헤더 파일

#include <math.h>

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

 

#define F_CPU 16000000UL

#define LCD_WDATA PORTA     //LCD데이터 포트 정의

#define LCD_WINST PORTA    //

#define LCD_CTRL PORTE    //LCD 제어 포트 정의

#define LCD_EN 0         //LCD 제어(PING0~2)를 효과적으로 하기위한 정의

#define LCD_RW 1

#define LCD_RS 2

#define Byte unsigned char //자주쓰이는 무부호 문자형 자료형을 Byte로 선언

 

typedef unsigned char byte;

 

/*------MPU------------*/

byte MPU6050_read(byte addr);

void MPU6050_write(byte addr, char data);

void getRawData();

unsigned int gx = 0, gy = 0, gz = 0, ax = 0, ay = 0, az = 0;

volatile long x_aTmp1, y_aTmp1, z_aTmp1;

volatile float x_aTmp2, y_aTmp2, z_aTmp2, x_aResult, y_aResult, z_aResult;

volatile float x_gTmp1, y_gTmp1, x_gResult, y_gResult;

 

byte buffer[12];

    int a=0, b=0;

 

void LCD_Data(Byte ch)

{

   LCD_CTRL |=  (1 << LCD_RS);    //RS=1, R/W=0 으로 데이터 쓰기 싸이클

   LCD_CTRL &= ~(1 << LCD_RW); 

   LCD_CTRL |=  (1 << LCD_EN);    //LCD 사용

   _delay_us(50);

   LCD_WDATA = ch;                //데이터 출력

   _delay_us(50);

   LCD_CTRL &= ~(1 << LCD_EN);    //LCD 사용안함

}

                           //  0         1      

void LCD_Comm(Byte ch)            //PG0-EN , PG1-RW, PG2-RS , PG4-TOSC1핀(사용안함)

{                            //LCD_CTRL = LCD제어부 포트(4핀인데 실질적인 사용3핀)

   LCD_CTRL &= ~(1 << LCD_RS);    // RS=0, RW=0 으로 정의함.

   LCD_CTRL &= ~(1 << LCD_RW);    

   LCD_CTRL |=  (1 << LCD_EN);    //LCD 사용허가

   _delay_us(50);

   LCD_WINST = ch;                //명령어 쓰기

   _delay_us(50);

   LCD_CTRL &= ~(1 << LCD_EN);    //LCD 사용안함

}

 

void LCD_CHAR(Byte c)  //한문자 출력 함수

{

   LCD_Data(c);      //CGROM 문자코드의 0x31 ~ 0xFF 는 아스키코드와 일치함!

   _delay_ms(1);

}

 

void LCD_STR(Byte *str)    //↑문자열을 한문자씩 출력함수로 전달

{  

    while(*str !=0)

   { 

     LCD_CHAR(*str);

      str++; 

   }

}

 

void LCD_pos(unsigned char col, unsigned char row)  //LCD 포지션 설정

{

   LCD_Comm(0x80 | (row+col*0x40));  // row=행 / col=열 ,DDRAM주소설정

}

 

void LCD_Clear(void)  // 화면 클리어

{

   LCD_Comm(0x01);

   _delay_ms(2); //1.6ms이상의 실행시간소요로 딜레이필요 

}

 

void LCD_Init(void)   //LCD 초기화

{

   LCD_Comm(0x38);   //데이터 8비트 사용, 5X7도트 , LCD2열로 사용(6)

   _delay_ms(2);

   LCD_Comm(0x38);   //데이터 8비트 사용, 5X7도트 , LCD2열로 사용(6)

   _delay_ms(2);

   LCD_Comm(0x38);   //데이터 8비트 사용, 5X7도트 , LCD2열로 사용(6)

   _delay_ms(2);

   LCD_Comm(0x0e);   //Display ON/OPFF

   _delay_ms(2);

   LCD_Comm(0x06);   //주소 +1 , 커서를 우측으로 이동 (3)

   _delay_ms(2);

    LCD_Clear();

}

int main()

 int unsigned adc_data;

   float volt, femp;

   char str[50];

 

TIMSK = 0x01;

TCCR0 = 0x07;

TCNT0 = 99;

SREG = 0x80;

 

   DDRA = 0xff; //PORTA(LCD연결포트)를 출력으로 설정

   DDRE = 0x0f; //PORTE(LCD컨트롤)의 하위 4비트를 출력으로설

   LCD_Clear;

   LCD_Init();

    TWSR = 0x00;

    TWBR = 0x12;

    

 MPU6050_write(0x6B, 0x00);

 MPU6050_write(0x6C, 0x00);

    

    getRawData();

    

    while(1)

    {  

        getRawData();

//자이로값 출력

     LCD_pos(0,0); sprintf(str,"GYRO      x=%4d",x_gResult); LCD_STR(str);

     LCD_pos(1,0); sprintf(str,"   y=%4d ", y_gResult); LCD_STR(str);

   _delay_ms(500);

 

    }

}

 

byte MPU6050_read(byte addr)

{

 byte dat;

 

 TWCR = 0xA4;

 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x08)));

 

 TWDR = 0xD0;

 TWCR = 0x84;

 

 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x18)));

 

 TWDR = addr;

 TWCR = 0x84;

 

 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x28)));

 TWCR = 0xA4;

//------------------------------------------------------------- 

 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x10)));

 TWDR = 0xD1;

 TWCR = 0x84;

 

 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x40)));

 TWCR = 0x84;

 

 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x58)));

 

 dat = TWDR;

 TWCR = 0x94;

 

 return dat;

}

void MPU6050_write(byte addr, char data)

 TWCR = 0xA4;

 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x08)));

 

 TWDR = 0xD0;

 TWCR = 0x84;

 

 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x18)));

 

 TWDR = addr; // addr = 0x43

 TWCR = 0x84;

 

 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x28)));

//------------------------------------------------------------- 

 TWDR = data;

 TWCR = 0x84;

 

 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x28)));

 

 TWCR = 0x94;

 _delay_us(50);

}

 

interrupt [TIM0_OVF] void timer_int0(void) { getRawData(); getAcclDegree(); getGyroDegree(); compFilter(); TCNT0 = 99; }

 

void getRawData()

{

    buffer[0] = MPU6050_read(0x3B);

    buffer[1] = MPU6050_read(0x3C);

    buffer[2] = MPU6050_read(0x3D);

    buffer[3] = MPU6050_read(0x3E);

    buffer[4] = MPU6050_read(0x3F);

    buffer[5] = MPU6050_read(0x40);

    

    buffer[6] = MPU6050_read(0x43);

    buffer[7] = MPU6050_read(0x44);

    buffer[8] = MPU6050_read(0x45);

    buffer[9] = MPU6050_read(0x46);

    buffer[10] = MPU6050_read(0x47);

    buffer[11] = MPU6050_read(0x48);

    

    ax = (int)buffer[0] << 8 | (int)buffer[1];

    ay = (int)buffer[2] << 8 | (int)buffer[3];

    az = (int)buffer[4] << 8 | (int)buffer[5];

    gx = (int)buffer[6] << 8 | (int)buffer[7];

    gy = (int)buffer[8] << 8 | (int)buffer[9];

    gz = (int)buffer[10] << 8 | (int)buffer[11];

}

void getAcclDegree(void)

{

    x_aTmp1 = ((long)ay * (long)ay) + ((long)az * (long)az);

    y_aTmp1 = ((long)ax * (long)ax) + ((long)az * (long)az);

    z_aTmp1 = ((long)ay * (long)ay) + ((long)az * (long)az);

    

    x_aTmp2 = sqrt((float)x_aTmp1);

    y_aTmp2 = sqrt((float)y_aTmp1);

    z_aTmp2 = sqrt((float)z_aTmp1);

    

    x_aResult = atan((float)ax / x_aTmp2);

    y_aResult = atan((float)ay / y_aTmp2);

    z_aResult = atan(z_aTmp2 / (float)az);

}

void getGyroDegree(void)

{

    x_gTmp1 = (float)gx / 65536;

    y_gTmp1 = (float)gy / 65536;

    

    x_gTmp1 = x_gTmp1 * 1.8;

    y_gTmp1 = y_gTmp1 * 1.8;

    

    x_gResult = x_gTmp1;

    y_gResult = y_gTmp1;

}

이렇게 옮겨 보았습니다. 조언 부탁드립니다.

  • BASIC4MCU 작성글 SNS에 공유하기
  • 페이스북으로 보내기
  • 트위터로 보내기
  • 구글플러스로 보내기

댓글 5

조회수 20,175

master님의 댓글

master 작성일

현재는 메인의 무한루프 안에서 LCD 출력을 하고 있습니다.
타이머를 이용해서 LCD를 출력하고 싶다고 적었는데
무슨 뜻인지 모르겠습니다.

dhksdlf218님의 댓글

dhksdlf218 댓글의 댓글 작성일

#include <util/delay.h>
#include <avr/signal.h>
#include <avr/interrupt.h>      //인터럽트 헤더 파일
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef unsigned char byte;
 
/*------MPU------------*/
byte MPU6050_read(byte addr);
void MPU6050_write(byte addr, char data);
void getRawData();
unsigned int gx = 0, gy = 0, gz = 0, ax = 0, ay = 0, az = 0;

byte buffer[12];
   
void main(void)
{
    TWSR = 0x00;
    TWBR = 0x12;
   
 MPU6050_write(0x6B, 0x00);
 MPU6050_write(0x6C, 0x00);
   
    getRawData();
   
    while(1)
    { 
        getRawData();
    }
}
 
byte MPU6050_read(byte addr)
{
 byte dat;
 
 TWCR = 0xA4;
 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x08)));
 
 TWDR = 0xD0;
 TWCR = 0x84;
 
 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x18)));
 
 TWDR = addr;
 TWCR = 0x84;
 
 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x28)));
 TWCR = 0xA4;
//-------------------------------------------------------------
 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x10)));
 TWDR = 0xD1;
 TWCR = 0x84;
 
 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x40)));
 TWCR = 0x84;
 
 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x58)));
 
 dat = TWDR;
 TWCR = 0x94;
 
 return dat;
}
void MPU6050_write(byte addr, char data)
{
 TWCR = 0xA4;
 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x08)));
 
 TWDR = 0xD0;
 TWCR = 0x84;
 
 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x18)));
 
 TWDR = addr; // addr = 0x43
 TWCR = 0x84;
 
 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x28)));
//-------------------------------------------------------------
 TWDR = data;
 TWCR = 0x84;

 while(((TWCR & 0x80) == 0x00 || ((TWSR & 0xF8) != 0x28)));
 
 TWCR = 0x94;
 _delay_us(50);
}
void getRawData()
{
    buffer[0] = MPU6050_read(0x3B);
    buffer[1] = MPU6050_read(0x3C);
    buffer[2] = MPU6050_read(0x3D);
    buffer[3] = MPU6050_read(0x3E);
    buffer[4] = MPU6050_read(0x3F);
    buffer[5] = MPU6050_read(0x40);
   
    buffer[6] = MPU6050_read(0x43);
    buffer[7] = MPU6050_read(0x44);
    buffer[8] = MPU6050_read(0x45);
    buffer[9] = MPU6050_read(0x46);
    buffer[10] = MPU6050_read(0x47);
    buffer[11] = MPU6050_read(0x48);
   
    ax = (int)buffer[0] << 8 | (int)buffer[1];
    ay = (int)buffer[2] << 8 | (int)buffer[3];
    az = (int)buffer[4] << 8 | (int)buffer[5];
    gx = (int)buffer[6] << 8 | (int)buffer[7];
    gy = (int)buffer[8] << 8 | (int)buffer[9];
    gz = (int)buffer[10] << 8 | (int)buffer[11];
}
clcd에 뛰오고 싶었지만 master님이 말씀하시는 말이 정확히 이해 못해서 바로 tera term같은 프로그램으로 값을 읽으려고 합니다. 어떤 프로그램을 써야할지 몰겟습니다. 조언 부탁드립니다.

master님의 댓글

master 댓글의 댓글 작성일

테라텀이 아니라도 시리얼 통신 모니터링 프로그램은 널려있습니다.
아두이노 시리얼모니터 창도 상관없고
코드비젼의 터미널창으로도 가능하죠
테라텀으로도 문제 안됩니다.
윈도우의 하이퍼터미널은 가장 기본적인 프로그램인데
높은 버전의 윈도우에서 지원이 안되면 낮은 버전의 하이퍼터미널을 사용 할 수도 있을겁니다.

master님의 댓글

master 작성일

타이머0 인터럽트 주기는 약 10ms로 설정 했지요?

    LCD_pos(0,0); sprintf(str,"GYRO      x=%4d",x_gResult); LCD_STR(str);
    LCD_pos(1,0); sprintf(str,"  y=%4d ", y_gResult); LCD_STR(str);
대략 26문자 정도를 출력하고 있는데
LCD 데이터 출력함수의 딜레이는 1ms이고
컴맨드 출력함수의 딜레이는 2ms입니다.
26개의 데이터와 2개의 컴맨드가 있어야하니
LCD 출력에는 대략 30ms 이상이 걸립니다.
10ms 주기의 인터럽트에서 30ms이상의 코드를 돌리면 메인은 전혀 동작하지 않게 되며
센서를 읽는데에는 정확한 주기로 실행 해야하는데
인터럽트 함수를 실행 하고나서 여유시간이 없어서 측정 주기가 정확하게 맞지 않게 됩니다.

master님의 댓글

master 작성일

현재 질문 소스의 내용 중
LCD 함수의 처리 속도를 빠르게 변경하려면
데이터 출력함수는 50us + 50us로 되어 있는데 -> 1us + 40us로 변경 할 수 있습니다.
LCD_pos() 함수에서 사용하는 컴맨드 출력 함수 경우에도 -> 1us + 40us로 변경 할 수 있습니다.
함수의 실행 시간이 약 50us로 줄어들게 되면 LCD 출력의 전체 시간이 1.5ms로 대폭 줄어들게 됩니다.
물론 LCD 모델에 따라서 약간의 차이가 있을 수 있습니다.
어떤 LCD는 출력하고나서 일정시간의 딜레이를 요구하기도 합니다.

질문게시판HOME > 질문게시판 목록

MCU, AVR, 아두이노 등 전자공학에 관련된 질문을 무료회원가입 후 작성해주시면 전문가가 답변해드립니다.
ATMEGA128PWMLED초음파
아두이노AVR블루투스LCD
UART모터적외선ATMEGA
전체 스위치 센서
질문게시판 목록
제목 작성자 작성일 조회
공지 MCU, AVR, 아두이노 등 전자공학에 관련된 질문은 질문게시판에서만 작성 가능합니다. 스태프 19-01-15 9622
공지 사이트 이용 안내댓글[24] master 17-10-29 29601
질문 atmega128 서보모터와 초음파센서댓글[5] 새글 tmiae 12:53 10
질문 avr compiler 종류 질문입니다!댓글[3] 새글 민준싸 01:16 21
질문 컴퓨터 usb연결시 정상 작동하나 9V건전지 외부전원 연결 시 작동하지 않는 문제댓글[3] 이미지새글첨부파일 보겐을운용 22-05-19 78
질문 아두이노 dac 연결댓글[3] 이미지새글첨부파일 kodory 22-05-19 24
질문 아두이노 millis ->atmega128에서 사용하고 싶습니다. 새글 akmong413 22-05-19 23
답변 답변글 답변 : 아두이노 millis ->atmega128에서 사용하고 싶습니다. 새글 master 22-05-19 26
질문 아트메가 모터드라이브와 초음파 센서 연동 질문입니다댓글[1] 새글 123424135123q 22-05-19 25
질문 스텝모터 드라이버 선정 질문드립니다. 새글 아흐흑 22-05-18 27
답변 답변글 답변 : 스텝모터 드라이버 선정 질문드립니다.댓글[1] 이미지새글 master 22-05-19 22
질문 아두이노로 모터+드라이버 제어댓글[6] 새글 모토 22-05-18 41
질문 온도센서로 서보모터 제어 코딩댓글[1] 새글 진수네1조 22-05-18 44
질문 라즈베리파이 웹캠 데이터 아두이노 전송 (초보)댓글[1] 전자과 22-05-17 46
질문 아두이노 코딩 도와주세요 (초음파센서와 금속감지센서로 서보모터 제어하기) 이현주 22-05-17 72
답변 답변글 답변 : 아두이노 코딩 도와주세요 (초음파센서와 금속감지센서로 서보모터 제어하기) master 22-05-18 121
질문 아두이노 우노 2개와 앱인벤터끼리의 블루투스 통신 방법댓글[3] 이미지첨부파일 pyoleo 22-05-17 92
질문 졸업작품 첨부파일 ejdog 22-05-16 87
질문 PCB의 커넥터 연결관련 이슈같은데.. 원인을 정확히 모르겠습니다.댓글[2] 이미지 설계못해서개털림 22-05-16 74
질문 STM32F767 사용중인데 발열이 발생합니다.댓글[5] 존클라프 22-05-16 69
질문 리니어 레일 거리 조절댓글[1] 면수 22-05-16 59
질문 아두이노 심전도 센서 BPM 계산댓글[3] 쥬쥬 22-05-16 82
질문 아두이노 서로 다른 전압을 가진 부품 제어 이미지 chovo 22-05-16 55
질문 앱인벤터 질문입니다.댓글[2] 이미지 귀끠우유 22-05-16 66
질문 아두이노 우노끼리 블루투스 통신댓글[1] 첨부파일 pyoleo 22-05-16 70
질문 마이크로 받은 입력을 주파수로 변경댓글[3] 생늧판출 22-05-16 44
질문 while문 안 if문 빠져나오는 방법 kyho3855 22-05-15 39
답변 답변글 답변 : while문 안 if문 빠져나오는 방법댓글[1] master 22-05-16 47
질문 초음파센서로 속도구하기(코드 합치는법) 쥰니 22-05-15 70
답변 답변글 답변 : 초음파센서로 속도구하기(코드 합치는법)댓글[1] master 22-05-16 69
게시물 검색

2022년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2021년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2020년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2019년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2018년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
Privacy Policy
MCU BASIC ⓒ 2020
모바일버전으로보기