POV : Persistence Of Vision

빛의 잔상 효과를 이용해 디스플레이를 만드는 기술

Youtube에 POV를 검색하면 수도 없이 많은 영상이 쏟아지니 그것을 참고함

Spoke POV를 보고 계획을 세움. 순도 90% 자작 프로젝트

참고한 내용은 제작에 필요한 재료(적당히 비슷하거나 같게)

https://learn.adafruit.com/spokepov/

할 일 : 알고리즘 만들기, 소스 코드 작성, 하드웨어 조립 제작

 

실험 준비

MCU (ATtiny2313V) - 2EA

Hall sensor (WSH135-XPAN2) - 10EA

ISP (MAI-ISP-MK2-B) - 1EA

브레드보드 (EIC-108) - 1EA

LED(R) - 40EA

LED(G) - 40EA

LED(B) - 40EA

LED(W) - 40EA

Shift Register (74HC595) - 16EA

멀티미터 (UT10A) - 1EA

이외 소모품으로 납, 핀헤더, 점퍼킷 구매

외부 메모리가 있어야 하지만 이번 달은 테스트만 진행해볼 예정이기에 구매하지 않음

이후 Ambilight 프로젝트 진행할 때 견적이 적절하면

 

2015. 06. 11 배송완료

Atmel Studio 6.2 설치

ISP 드라이버는 Atmel Studio 설치 파일에 포함되어 있음

 

개발환경 정리

OS : Windows 8.1 64bit

IDE : Atmel Studio 6.2 SP2

Language : C

Programmer : AVRISP MK2

Tab Size : 4 space

 

개발환경 테스트

간단하게 LED 하나 깜박이는 코드 작성

 

#define F_CPU 12000000
#include <avr/io.h>
#include <util/delay.h>
 
void main()
{
    int endCount = 0;
    DDRB = 0xFF;
 
    while(1)
    {
        PORTB = 0xFF;
        _delay_ms(100);
        PORTB = 0x00;
        _delay_ms(100);
        if(endCount > 10)
        {
            break;
        }
        endCount++;
    }
}

'Programming > Embedded' 카테고리의 다른 글

Bike POV DIY (Spoke POV)  (0) 2015.06.04
ATmega128 MPU6050  (18) 2014.03.18
Getting Start STM32F103 Dev  (0) 2014.02.28
STM32F103 - QuadCopter 참고 소스  (0) 2014.02.19
STM32F103 - PWM 소스  (0) 2014.02.19
FB155BC 설정 with USB2UART Downloader  (0) 2014.02.19
ATmega128 에서 MPU6050 의 가속도 자이로 값을 읽어오는 방법 100Hz로 샘플링을 하기 위해
타이머 오버플로우로 0.01초마다 인터럽트가 걸리게 설정함
TIMSK = 0x01;
TCCR0 = 0x07;
TCNT0 = 99;
SREG = 0x80;

그리고 인터럽트 소스를 작성

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

가속도 센서와 자이로 센서 값을 읽어오는건 이전에 올린 소스가 있음
MPU6050_read() 함수는 지난 포스팅 참조 -Click-
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;
}

volatile 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;
기본적으로 위의 모든 변수들은 float 혹은 double형으로 선언해두고
가속도 부분의 x_aTmp1, y_aTmp1, z_aTmp1 이 세개만 long형으로 선언
gx gy gz ax ay az는 raw data를 최초로 저장하는 변수임
참고로 gy-521의 MPU-6050모듈은 16bit ADC이고 레지스터 당 8비트니까
High bit / Low bit를 나눠서 읽어온 다음 쉬프트 연산과 OR 연산을 적절히 사용해 합쳐주는 방법을 사용했음.
마지막으로 필터부분
void compFilter(void)
{
    xTmp1 = (-y_aResult) + (float)xFilterAngle;
    xIntTmp1 = (float)xIntTmp1 + (xTmp1 * 0.01);
    xTmp2 = (-kp * xTmp1) + (-ki * (float)xIntTmp1) + x_gResult;
    xFilterAngle = xFilterAngle + (xTmp2 * 0.01);
    pitch = (int)(xFilterAngle * 180 / PI);
    
    yTmp1 = (-x_aResult) + (float)yFilterAngle;
    yIntTmp1 = (float)yIntTmp1 + (yTmp1 * 0.01);
    yTmp2 = (-kp * yTmp1) + (-ki * (float)yIntTmp1) + y_gResult;
    yFilterAngle = yFilterAngle + (yTmp2 * 0.01);
    roll = (int)(yFilterAngle * 180 / PI);
}
변수 선언은
float kp = 12.0f, ki = 1.0f;
volatile float xTmp1, yTmp1, xTmp2, yTmp2, xIntTmp1, yIntTmp1;
volatile float xFilterAngle = 0.0f, yFilterAngle = 0.0f;
volatile int pitch = 0, roll = 0;
위와 같이 하였다
지금까지 선언한 변수들은 쓰기 편하게 전역변수로 선언하고 그냥 가져다 쓰는 방식

2014 / 03 / 18 - 20:04 최초 작성


'Programming > Embedded' 카테고리의 다른 글

Bike POV DIY (Spoke POV)  (0) 2015.06.04
ATmega128 MPU6050  (18) 2014.03.18
Getting Start STM32F103 Dev  (0) 2014.02.28
STM32F103 - QuadCopter 참고 소스  (0) 2014.02.19
STM32F103 - PWM 소스  (0) 2014.02.19
FB155BC 설정 with USB2UART Downloader  (0) 2014.02.19
  1. 김현정 2014.10.10 14:29

    안녕하세요 주인장님 제가 atmega128로 mpu6050값을 받는걸 공부하고있는데요
    실례되는 말이지만 위에 쓰신 소스 전문을 받으수있을까요??

    • Favicon of https://blog.komastar.kr BlogIcon Lord Komastar.Dev 2014.10.12 22:07 신고

      제가 학생때 공부했던 내용이라 자료 관리에 소홀하여
      현재 전체 소스를 가지고 있지 않습니다.
      블로그 내용에 MPU6050 읽기 소스 등을 참고하여 소스를 재작성 해야 될겁니다

  2. 공대생 2014.12.07 14:41

    이코드 현재 분석중인데
    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;
    }

    에서 1.8 은 무엇을 의미 하는 거에요 ??

    • Favicon of https://blog.komastar.kr BlogIcon Lord Komastar.Dev 2014.12.08 11:04 신고

      MPU 6050 자이로 모듈 동작 전압입니다
      당시 제가 찾던 자료들에서 확인한 공식에 의해 작성되었습니다
      기초가 부족했던 때라 레퍼런스 남기는걸 잊었습니다

  3. 공돌이 2016.03.12 00:39

    getGyroDegree함수에서 gx, gy와 달리 gz는 왜 하지않는건가요?

  4. 공돌이 2016.03.12 14:58

    답변 감사합니다.
    그럼 roll값과 pitch값이 가속도와 각속도가 합쳐진 값인거죠??

  5. 공돌이 2016.03.14 18:20

    자료 감사히 잘봤구요, 답변 감사합니다. 도움 많이 됬습니다.^^

  6. 2016.04.18 21:44

    비밀댓글입니다

    • Favicon of https://blog.komastar.kr BlogIcon Lord Komastar.Dev 2016.04.18 22:38 신고

      타이머 0,1동시 사용은 저도 정확히 모르겠네요
      Dt는 100헤르츠면 0.01맞습니다

    • 2016.04.20 02:08

      비밀댓글입니다

  7. 2016.04.24 16:40

    비밀댓글입니다

    • Favicon of https://blog.komastar.kr BlogIcon Lord Komastar.Dev 2016.04.24 21:34 신고

      인터럽트를 사용해서 일정 주기마다 실행을 해야 샘플링이 되는거라
      그냥 반복문에 무작정 돌리면 문제가 될 수 있어요
      이 코드를 보시는건 CodeVision 사용하는 중이신가요?
      가능하면 AtmelStudio로 넘어가시는걸 추천드립니다

      그리고 타이머0 인터럽트는 정상적으로 발생하는지요?

    • 2016.04.25 21:49

      비밀댓글입니다

  8. 최진혁 2016.05.11 17:00

    이런 질문 드려도 될런지....
    혹시 식에서 0.01이라고 적힌 것 위에 댓글 보니깐 dt 값인거 같은데
    그 값은 어떻게 정하는 건가요...? 저도 사용하려는데 dt 값을 어떻게 해야 할지 몰라서 며칠 째 공부 중인데 답이 안나오네요...

    • Favicon of https://blog.komastar.kr BlogIcon Lord Komastar.Dev 2016.05.12 10:07 신고

      dt 값은 임의로 정하는 것입니다
      초당 100회 이상 샘플링을 하는 것이 일반적인것 같습니다

  9. Lee 2017.10.01 21:59

    덕분에 좋은 정보 알아갑니다.

stm32f103 / iar embedded workbench / iar ewarm / iar 프로젝트 생성 / iar 프로젝트 설정


<Get Flash Downloader>






<Get Library>












<Create Project>



















2014 / 02 / 28 - 23:40 초안 작성

'Programming > Embedded' 카테고리의 다른 글

Bike POV DIY (Spoke POV)  (0) 2015.06.04
ATmega128 MPU6050  (18) 2014.03.18
Getting Start STM32F103 Dev  (0) 2014.02.28
STM32F103 - QuadCopter 참고 소스  (0) 2014.02.19
STM32F103 - PWM 소스  (0) 2014.02.19
FB155BC 설정 with USB2UART Downloader  (0) 2014.02.19




첨부 파일 참조


첨부 파일에 IAR EWARM 용 프로젝트 전체가 들어있음


QuadCopter.zip



2014 / 02 / 19 - 22:42 최초 작성

2014 / 02 / 20 - 01:43 태그 정리

2014 / 02 / 20 - 03:33 첨부 파일 재등록

'Programming > Embedded' 카테고리의 다른 글

ATmega128 MPU6050  (18) 2014.03.18
Getting Start STM32F103 Dev  (0) 2014.02.28
STM32F103 - QuadCopter 참고 소스  (0) 2014.02.19
STM32F103 - PWM 소스  (0) 2014.02.19
FB155BC 설정 with USB2UART Downloader  (0) 2014.02.19
STM32F103 - Flash Downloader 에러  (0) 2014.02.19

STM32F103 / PWM / Cortex M3


STM32F103 에서 PWM 을 생성하는 소스임 Timer 3의 CH 1 / CH 2 / CH 3 / CH 4 에서 PWM 생성

전체 소스에서 PWM 부분만 잘라서 올림

헤더 파일 포함 시키는 것이 맞는지 잘 기억이 안남 소스 내용 자체는 정확하니 참고용으로 쓰시길

#include <STM32F103_PWM.H>
#include <STM32F103_TIM.H>
#include <STM32F103_RCC.H>

u16     PrescalerValue = 0;
double   i_motor1 = 0;
double   i_motor2 = 800;
double   i_motor3 = 800;
double   i_motor4 = 0;

void    PWM_Init(void);
void    RCC_Configuration(void);
void    GPIO_Configuration(void);

TIM_TimeBaseInitTypeDef		TIM_TimeBaseStructure;
TIM_OCInitTypeDef			TIM_OCInitStructure;

int main()
{
	PWM_Init();
	while(1)
	{
	}
}

void PWM_Init()
{
    RCC_Configuration();
    GPIO_Configuration();
    
    PrescalerValue = (u16)(SystemCoreClock / 1000000) - 1;     	//	1000000 for 10us
    
    TIM_TimeBaseStructure.TIM_Period = 20000;        			// 	2000 	for 10us
    TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    
    //CH1 setting start
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 0;
    
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);
    
    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
    //CH1 setting end
    
    //CH2 setting start
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = (int)i_motor2;
    
    TIM_OC2Init(TIM3, &TIM_OCInitStructure);
    
    TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
    //CH2 setting end
    
    //CH3 setting start
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = (int)i_motor3;
    
    TIM_OC3Init(TIM3, &TIM_OCInitStructure);
    
    TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
    //CH3 setting end
    
    //CH4 setting start
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 0;
    
    TIM_OC4Init(TIM3, &TIM_OCInitStructure);
    
    TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
    //CH4 setting end
    
    TIM_ARRPreloadConfig(TIM3, ENABLE);	
    TIM_Cmd(TIM3, ENABLE);
    
    delay_ms(1000);
}

/*	Name : RCC_Configuration
 *	Function : Ready For PWM */
void RCC_Configuration()
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
}

/*	Name : GPIO_Configuration
 *	Function : Ready For PWM */
void GPIO_Configuration()
{
    GPIO_InitTypeDef	GPIO_InitStructurePWM;
    
    GPIO_InitStructurePWM.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_InitStructurePWM.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructurePWM.GPIO_Speed = GPIO_Speed_50MHz;
    
    GPIO_Init(GPIOA, &GPIO_InitStructurePWM);
    
    GPIO_InitStructurePWM.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_Init(GPIOB, &GPIO_InitStructurePWM);
}


2014 / 02 / 19 - 22:28 최초 작성

2014 / 02 / 20 - 01:41 태그 정리

2015 / 06 / 12 - 16:03 모바일에서 #include문 표시 문제 수정(모바일 티스토리에서 Syntax Highlight 동작 안함)

'Programming > Embedded' 카테고리의 다른 글

Getting Start STM32F103 Dev  (0) 2014.02.28
STM32F103 - QuadCopter 참고 소스  (0) 2014.02.19
STM32F103 - PWM 소스  (0) 2014.02.19
FB155BC 설정 with USB2UART Downloader  (0) 2014.02.19
STM32F103 - Flash Downloader 에러  (0) 2014.02.19
ATmega128 - PWM Mode 14 소스  (0) 2014.02.19

usb2usart / fb155bc / btconfig




블루투스 모듈의 설정을 바꾸기 위해선 다양한 방법이 존재하는데 보통 동글을 사용하여 설정을 변경한다.

 

한번 사용할 모듈인데 설정 한번 하려고 추가 장비를 구매를 한다면 사치라 생각 될 수 있다.

우리가 사용하는 모듈인 FB155BC는 3.3V 에서 동작하며 TTL 신호로 통신을 한다.

사용된 MCU 는 STM32F103 이며 3.3V 에서 동작한다.

 


STM32를 사용하기 위해 USB2UART 다운로더를 구매해야 했는데

이 녀석이 3.3V 를 공급해줄거란 생각과 PC와 Serial 통신을 할 수 있게 해준다.

동글의 원리를 잘 모르지만 어쨋든 PC와 통신을 하면 될 거란 생각이 들었다.

USB2UART의 VCC GND 를 FB155BC의 각 VCC GND에 결선하고 Rx Tx를 크로스 연결을 한다.

참고로 위 사진의 모듈은 Rx Tx 가 이미 크로스 되어 있는 상태로 핀 이름이 새겨져 있다.

따라서 USB2UART 모듈의 Rx 는 FB155BC의 Rx 에 연결하고 USB2UART의 Tx 는 FB155BC 의 Tx 에 연결한다.



필자는 위와 같이 보드에 FB155BC를 고정했기 때문에 선을 다시 따내기 귀찮았고 자주 사용할 일도 없으니 자유롭게 결선만 할 수 있는 케이블을 제작했다.

흰색 박스 쳐져 있는 부분이 FB155BC에 연결된 소켓인데 다음 사진으로 어떤 핀과 연결되는지 알 수 있다.




우측 상단의 흰 박스는 VCC / GND 순서로 배치되어 있고

좌측 하단 박스 중 첫번째 박스친 부분은 PA2 즉 USART2 TX Pin에 연결되고

두번째 박스친 부분은 PA3 즉 USART2 RX Pin에 연결된다.

STM32F103 모듈을 제거하고 핀 헤더 소켓에 미리 만들어놓은 케이블을 연결한다.

 



위와 같이 연결을 한 상태로 이제 FB155BC의 설정을 위한 BTCONFIG 를 실행한다.

사진을 찍고 보니 VCC와 GND가 반대로 연결되어 있는데 실제 테스트에선 올바르게 연결하고 테스트함.

케이블은 적당한 전선 4가닥 양 단에 핀헤더를 납땜하고 수축튜브로 마무리 했다.



 


BTCONFIG를 최초 실행 했을 때의 화면이다

좌측 상단의 SERIAL OPEN이라는 아이콘을 클릭하여 시리얼 연결을 시작한다.



 


SERIAL OPEN 아이콘을 클릭하면 위와 같은 창이 새로 뜬다

연결된 USBtoUSART가 어떤 COM포트를 사용하는지 COM PORT 설정을 바꿔주고 BAUDRATE 설정을 바꿔준다.

기본적으로 9600으로 설정되어 있으나 필자는 이전에 57600으로 바꿔두고 사용을 해서 57600으로 설정하고 통신을 시작한다.



 


연결이 완료되면 위와 같이 SERIAL CLOSE 버튼과 READ 버튼 그리고 INIT 버튼이 활성화 된다.

이제 READ 버튼을 눌러 내부 정보를 읽어오자

SERIAL CLOSE는 말 그대로 시리얼 통신 포트를 닫는 것이고 INIT은 공장 초기화 값으로 재설정 한다.


 




블루투스 모듈의 내부 정보를 잘 읽어오는 것을 확인 할 수 있다.

좌측 메뉴에 대한 설명을 간단히 하겠다.

첫번째 메뉴인 OVERVIEW에선 블루투스 모듈에 설정된 전체 파라미터들을 볼 수 있다.

 






BLUETOOTH PARAMETERS에선 디바이스 이름과 어떤 역할을 수행할지 등을 설정 할 수 있다.

 





SECURITY PARAMETERS에선 보안 설정을 할 수 있는데 기본적인 PIN CODE만 입력해주고 넘어가자




 



우리는 ATCOMMAND를 사용하지 않을 것이기 때문에 블루투스의 모드를 MODE 3으로 설정한다.






BAUDRATE와 PARITY BIT, STOP BIT, FLOW CONTROL 등 블루투스가 시리얼 통신 할 때 쓸 설정 값들을 입력해준다. 

입력한 값으로 설정이 잘 되었는지 확인.



 


상단에 있는 WRITE 버튼을 누르면 위와 같은 창이 새로 뜨는데 WRITE PARAMETERS를 클릭하여 설정한 값들을 입력시킨다.






값들을 입력하는 중 프로세스 진행 바


 

이제 설정한 값을 기반으로 블루투스 통신을 할 수 있다.

 

참고로 공장 초기화를 할 경우 MODE4로 설정되어 있어 ATCOMMAND로 설정의 내용을 바꿔줄 수 있다.

이 방법을 사용하면 MCU내부에서 설정을 바꿀 수 도 있지만 한번 설정한 값들을 계속 사용할 것이기 때문에 그리고 MODE 3으로 페어링이 편하기 때문이기도 하다.

 

2014 / 02 / 19 - 20:55 최초 작성

2014 / 02 / 20 - 01:40 태그 정리

'Programming > Embedded' 카테고리의 다른 글

STM32F103 - QuadCopter 참고 소스  (0) 2014.02.19
STM32F103 - PWM 소스  (0) 2014.02.19
FB155BC 설정 with USB2UART Downloader  (0) 2014.02.19
STM32F103 - Flash Downloader 에러  (0) 2014.02.19
ATmega128 - PWM Mode 14 소스  (0) 2014.02.19
ATmega128 - MPU6050 레지스터 읽기  (5) 2014.02.19



ST에서 배포한 Flash Downloader 에러 이슈

성공한 사용 환경 : Komastar-PC ( Intel i5-3570 / RAM 16GB / AMD Radeon HD7860 / Samsung SSD 830 128GB / Windows 7 64bit )

문제의 사용 환경 : Macbook Pro 13" Standard 2011 / Windows 7 64bit

이슈 내용 : 시리얼 통신 설정 후 통신을 하려고 하면 에러 발생

Komastar-PC 환경에선 정상적으로 다운로드가 진행 되었음

다른 환경을 찾기 위해 학교 전산실의 PC에서 다운로드를 실행하니 마찬가지로 안됨.

맥북만의 문제가 아님을 알고 안도했으나 일단 안되는 것에는 변함이 없었다.

----이슈 해결----

안정적인 다운로드를 위해 낮은 BaudRate 설정이 문제였음

Baudrate를 9600으로 잡고 시도 했을 때는 에러가 발생하다가 14400으로 올리니 정상적으로 다운로드 진행이 된다

지금 알고 있는 지식의 수준으로는 이해가 안되는 동작이다.

안정적으로 데이터를 주고 받기 위해 낮은 BaudRate를 쓰는 것이라 배웠건만...

9600에선 동작하지 않는데 14400에선 동작을 하다니

어쨋든 BaudRate를 변경하여 동작이 제대로 되는 것을 확인.

교훈 : 상식적으로 이해가 안되는 상황이 닥쳐도 내 상식이 절대적인게 아니니 열린 생각을 가지면 해결 할 수 있다.

19200bps 에선 동작하지 않지만 38400 혹은 그 이후 전송 속도를 사용하면 다운로더가 잘 동작함.

소스가 커짐에 따라 단순히 빠르게 다운로드하고 싶다는 욕구에 속도를 올려봤더니 최고 속도에서도 잘 동작함.


2014 / 02 / 19 - 20:52 최초 작성

2014 / 02 / 20 - 01:39 태그 정리

'Programming > Embedded' 카테고리의 다른 글

STM32F103 - PWM 소스  (0) 2014.02.19
FB155BC 설정 with USB2UART Downloader  (0) 2014.02.19
STM32F103 - Flash Downloader 에러  (0) 2014.02.19
ATmega128 - PWM Mode 14 소스  (0) 2014.02.19
ATmega128 - MPU6050 레지스터 읽기  (5) 2014.02.19
STM32F103 - USART Interrupt 소스  (2) 2014.02.19

atmega128 / pwm / pwm mode 14 / atmega128 pwm


#include 
void main(void)
{
    DDRB  = 0xFF;
    DDRE  = 0xFF;
    PORTB = 0xFF;
    PORTE = 0xFF;
    
 /* FastPWM 14 mode setting */
    TCCR1A |= (1<<1) | (0<<0);  //WGM 1, 0
    TCCR1B |= (1<<4) | (1<<3);  //WGM 3, 2   
    TCCR3A |= (1<<1) | (0<<0);
    TCCR3B |= (1<<4) | (1<<3);
 
    TCCR1A |= (1<<7) | (0<<6) | (1<<5) | (0<<4) | (1 << 3) | (0 << 2);
    TCCR3A |= (1<<7) | (0<<6) | (1<<5) | (0<<4) | (1 << 3) | (0 << 2);
 
 /* 1024 prescaler */
    TCCR1B |= (1<<2) | (0<<1) | (1<<0);
    TCCR3B |= (1<<2) | (0<<1) | (1<<0);
    TCNT1H = 0x00; 
    TCNT1L = 0x00;
    TCNT3H = 0x00;
    TCNT3L = 0x00;
    
    ICR1H = 0x01;
    ICR1L = 0x36;
    ICR3H = 0x01;
    ICR3L = 0x36;
 
    OCR1AH = 0x00;            
    //OCR1AL = 0x0A;
    OCR1AL = 10; 
    OCR1BH = 0x00;          
    //OCR1BL = 0x28;
    OCR1BL = 40;
    
    OCR1CH = 0x00;           
    OCR1CL = 0x20;
    
    OCR3BH = 0x00;          
    OCR3BL = 0x08;
    
    SREG = 0x80;
 
    while(1);
}
Fast PWM Mode 14 구현 1024 프리스케일러에 ICR 값을 320가량을 줘서 20ms 주기의 PWM 신호를 만들었다.
출력되는 핀은 OC1A, OC1B, OC1C, OC3B 원래는 OC3B대신 OC3A로 출력하려고 했으나
나머지 핀은 출력이 잘되는데 이 녀석만 출력이 안나왔다.
모듈 불량으로 판단된다
4개의 PWM만 있으면 되니 상관은 없다.

2014 / 02 / 19 - 20:36 최초 작성

2014 / 02 / 20 - 01:38 태그 정리

'Programming > Embedded' 카테고리의 다른 글

STM32F103 - PWM 소스  (0) 2014.02.19
FB155BC 설정 with USB2UART Downloader  (0) 2014.02.19
STM32F103 - Flash Downloader 에러  (0) 2014.02.19
ATmega128 - PWM Mode 14 소스  (0) 2014.02.19
ATmega128 - MPU6050 레지스터 읽기  (5) 2014.02.19
STM32F103 - USART Interrupt 소스  (2) 2014.02.19

atmega128 / mpu6050 / gy-521 / 자이로 / 가속도 / 센서




TWI 통신으로 레지스터 0x3B부터 0x40, 0x43부터 0x48까지

그러니까 가속도 XYZ 출력과 자이로 XYZ 출력 레지스터를 읽기까지 성공함.

읽어들인 RAW 데이터를 정제하는데 머리가 아픔

MPU는 ATmega128을 사용했고

GY-521의 SCL -> PD0 / SDA -> PD1에 연결

사용된 센서는 MPU-6050 3축 가속도 / 3축 자이로 / 온도를 감지

오프셋을 설정 / 필터로 안정적인 값을 추출하는 작업을 해야 하는 것 같은데

아직 완벽히 이해하지 못함.

아래의 소스에서 getRawData();는 레지스터에서 읽은 단순한 값을 각 변수에 저장함.

변수의 내용을 확인 하기 위해선 텍스트 LCD로 확인하거나 시리얼 통신으로 값을 읽어서 확인해야 함.

#include <stdlib.h>
#include <delay.h>
#include <mega128.h>
#include <math.h>
#include <stdio.h>
#include <string.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];
}
2014 / 02 / 19 - 20:23 최초 작성

2014 / 02 / 20 - 01:36 태그 정리


'Programming > Embedded' 카테고리의 다른 글

STM32F103 - PWM 소스  (0) 2014.02.19
FB155BC 설정 with USB2UART Downloader  (0) 2014.02.19
STM32F103 - Flash Downloader 에러  (0) 2014.02.19
ATmega128 - PWM Mode 14 소스  (0) 2014.02.19
ATmega128 - MPU6050 레지스터 읽기  (5) 2014.02.19
STM32F103 - USART Interrupt 소스  (2) 2014.02.19
  1. hyeonseung 2014.07.02 23:02

    ax,ay,az,gy,gx,gz값을 unsigned int 로 잡으셨는데 signed가 맞지 않나요??

    버퍼값을 8비트로 잡고 각도값은 16비트로 잡는거 아닌가요?

    • Favicon of https://blog.komastar.kr BlogIcon Lord Komastar.Dev 2014.07.03 22:56 신고

      signed로 했어야 했네요
      그리고 버퍼값은 8비트로 했구요
      byte 배열로 선언했으니까요
      각도값은 16비트로 했습니다
      위 소스에선 각도값이 나오진 않지만요

  2. kkk 2015.07.25 00:55

    시리얼 통신으로 값을 확인하는 부분은 하이퍼 터미널을 사용하면 되는건가요?

  3. subin 2016.08.03 15:11

    헤더파일에 공백으로 여섯개 처리해놓으셨는데
    codevision이면 atmega128,delay 그리고 나머지 네개 좀 알려주시면 안될까요 ㅠㅠ

stm32f103 / usart / usart interrupt



USART Polling 방식은 이전의 포스팅에서 구현을 했으니

이번엔 Interrupt 방식을 구현 할 차례이다.

쿼드콥터의 제어 코드가 돌아가는 중에 조종 데이터를 전송 받아야 하니

Polling 방식은 부적절 하다고 볼 수 있다.

그래서 Interrupt 방식의 USART 통신을 구현해야 한다.

#include "stm32f10x_conf.h"
//stm32f10x_conf.h 파일에는 필요한 각종 헤더를 포함시키는 코드를 삽입
//stm32f10x_gpio.h    ~_usart.h       ~_rcc.h
//misc.h

void USART2_IRQHandler(void);

int putchar(int ch);
u16 tmp;
 
int main()
{   
    SystemInit();
    
    NVIC_InitTypeDef NVIC_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
 
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    /* Configure USARTx_Rx as input floating */
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    USART_InitStructure.USART_BaudRate  = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits  = USART_StopBits_1;
    USART_InitStructure.USART_Parity  = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode  = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART2, &USART_InitStructure);
    
    USART_Cmd(USART2, ENABLE);
    
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
    
    /* Main While Loop */
    while(1)
    {
        while(!USART_GetFlagStatus(USART2, USART_FLAG_TXE));
        USART_SendData(USART2, 'A');
    }
}
 
void USART2_IRQHandler(void)
{
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
    {
        USART_SendData(USART2, 'B');
        USART_ClearITPendingBit(USART2, USART_IT_RXNE);
    }
}

테스트 할 당시 USART2에 연결한 블루투스로 테스트하고 구현한 소스

USART2 채널을 통해 A라는 글자가 무한히 출력되다가 USART2에 아무 input을 주게 되면 순간 B라는 글자가 출력됨

USARTx_IRQHandler 안의 구현하는 내용에 따라 다양하게 응용이 가능

다른 USART채널을 사용하려면 USART2라고 되어 있는 부분을 사용하고 싶은 USART 채널로 고치고 몇 부분만 더 고치면 사용 가능함

첨부 파일 : 구현한 프로젝트와 개인적으로 사용하려고 편집한 USART 헤더 파일

수정 및 배포 가능


2014 / 02 / 19 - 20:04 최초 작성

2014 / 02 / 19 - 20:14 SyntaxHighlighter 적용

2014 / 02 / 20 - 01:36 태그 정리

'Programming > Embedded' 카테고리의 다른 글

STM32F103 - PWM 소스  (0) 2014.02.19
FB155BC 설정 with USB2UART Downloader  (0) 2014.02.19
STM32F103 - Flash Downloader 에러  (0) 2014.02.19
ATmega128 - PWM Mode 14 소스  (0) 2014.02.19
ATmega128 - MPU6050 레지스터 읽기  (5) 2014.02.19
STM32F103 - USART Interrupt 소스  (2) 2014.02.19
  1. 이진구 2017.08.25 16:24

    안녕하세요? 혹시 UART 동작시킬때 사용자가 원하는 핀으로도 UART를 동작시킬수 있나요? 만약 가능 하다면 어떻게 하는지 설명을 부탁드려도 될까요?

    • Favicon of https://blog.komastar.kr BlogIcon Lord Komastar.Dev 2017.08.25 22:39 신고

      동작시킬 USART 번호의 레지스터에 마스킹 넣고 해당 USART의 TX RX핀에 데이터를 쏘고 읽고 하면 됩니다

+ Recent posts