Project/논문분석2015. 1. 12. 22:09

첨부파일:


-Title-

Modelling, simulation and control of an electric unicycle


A. Kadis, D. Caldecott, A. Edwards, M. Jerbic

R. Madigan, M Haynes, B. Cazzolato and Z. Prime,

The University of Adelaide, Australia



요즘들어 가끔씩 학교를 거닐다 보면 아래와 같은 형태의 vehicle을 볼 때가 있습니다.


위의것을 Solo wheel self balancing unicycle이라고 합니다.


이것도 self balancing unicycle이라고 하죠. 차이는 의자가 있는냐 없느냐 정도이고 바퀴 하나로 자세를 잡는 탈것입니다.


제가 소개할 논문에서 다루는 제품의 이름은 MICYCLE이라고 하며 아래 URL주소를 통해 동영상을 볼 수 있습니다.

URL : http://www.youtube.com/watch?v=kMeH9IQgxLU




오스트레일리아의 Adelaide대학의 연구실에서 만든것으로 SBU의 원형이 되었는지 어떤지는 모르겠습니다만, 실제로 만들고 시연 동영상까지 있기때문에 참고하게 되었습니다.


이번 논문에서 다루는 내용은 아래와 같습니다.

이 시스템의 기계적이고 전자적인 요소를 고려하여 설계되었으며 또한 matlab의 simulink를 통하여 라그랑지안을 이용해 system dynamics를 도출하였다고 합니다. 즉, 동역학식에 의한 시스템 모델링을 근거로 하여 설계되었다는 것입니다.

이 논문에서는 시스템의 pitch방향의 안정화를 위한 선형제어기를 제안합니다.

마지막으로, simulink 시뮬레이션과 실제 실험 결과를 비교합니다.



위 사진은 MICYCLE의 steering 및 전기적 요소들을 포함한 기계적인 설계를 보여주고 있습니다.


MICYCLE의 설계개요는 사용자가 약 한시간정도 타고 배울 수 있는 self-balancing의 외발자동차를 만드는 것입니다. 이를 위해서 제어시스템이 pitch방향의 자세를 잡도록 하고 기계적인 steering linkage가 사용자가 roll방향의 밸런싱을 잡는것을 보조하기 위해서 디자인되었습니다.


위 설계에서 가장 중요한 요소가 steering 메카니즘인데요, fork assembly는 바퀴부근에 장착되어 있는 페달과 조향을 위한 steering 사이의 연결장치 역할을 합니다. 제어시의 발산과 떨림을 제거하기 위해서 steering arm과 rotary damper를 중앙에 맞춰줄 필요가 있으며 이를 위해 steering 메카니즘에 비틀림 스프링을 포함시켰다고 합니다.


또한 위 시스템은 oversteering에 대비하여15도 라는 기계적인 제한을 두고 있습니다.



'Project > 논문분석' 카테고리의 다른 글

이 카테고리는?  (0) 2015.01.12
Posted by 십자성군
Project/논문분석2015. 1. 12. 22:03

방학도중 눈여겨볼만한 논문들을 읽어보고 분석해서 다른 사람들에게 설명한다는 깊~고 좋은 의도로 교수님이 하자고 하셨지만... 정말 귀찮다!


하지만 그냥 자료로 가지고 있는것보다는 넷상에서 영구보관하는게 좋다고 생각하여 이렇게 게시하도록 한다.


저작권 문제가 생길경우 비공개로 돌립니다.

'Project > 논문분석' 카테고리의 다른 글

Modelling, simulation and control of an electric unicycle  (0) 2015.01.12
Posted by 십자성군
Project/Balancing 283352014. 8. 19. 16:06


#include "DSP2833x_device.h"

#include "DSP2833x_GlobalPrototypes.h"

#include "GlobalProtoypesLee.h"


void Init_Timer0()

{

// 정풩프?않은 타머 콘트롤 레지스터를 초기화

InitCpuTimers();

// 타이머 주와 타이머?reload 설정

ConfigCpuTimer(&CpuTimer0, 150, 1000);

// 150MHz CPU Freq, 5 msec Period (in uSeconds)

// 1 msec

StartCpuTimer0();

// Interrupt Enable Register

}


1. InitCpuTimers()


2. ConfigCpuTimer()


3. StartCpuTimer0()

'Project > Balancing 28335' 카테고리의 다른 글

Init_ADC  (0) 2014.08.19
GpioInit  (0) 2014.08.18
Posted by 십자성군
Project/Balancing 283352014. 8. 19. 14:18

#include "DSP2833x_device.h"

#include "DSP2833x_GlobalPrototypes.h"

#include "GlobalProtoypesLee.h"


void Init_ADC()

{


// 현재 ADC_CLK으로

InitAdc();


// ADC 설정

AdcRegs.ADCTRL3.bit.ADCCLKPS = 15;   // 재분주값 = HSPCLK  /(2*ADCCLKPS)

AdcRegs.ADCTRL1.bit.CPS = 1; // ADCCLK = ADCCLKPS / 2 (ADC의 구동 클럭을 결정 : ADCCLK = 1.25MHz)

AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 시퀀스 직렬 모드

AdcRegs.ADCTRL1.bit.ACQ_PS = 7 ; // 샘플링 윈도우 size를 8 ADC_CLK 설정

AdcRegs.ADCMAXCONV.all = 0x0004;

AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0; // Murata [ Gyro ]

AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1; // SA1 [ Tilt ] 4


AdcRegs.ADCTRL1.bit.CONT_RUN = 1;   // Cont. conv. mode

AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1; // 시퀀스 시작


}


Part1

1. 현재 HSPCLK는 75MHz로 설정되어 있기에 분주된 값=2.5MHz로 설정되었다. : HSPCLK/(2*ADCCLKPS)

2. ADCCLK = Fclk/1 or 2로 CPS=1이므로 2분주이다.

3. SEQ_CASC = 1이면 시퀀스 직렬모드, 0이면 병렬모드이다.

4. SOC펄스의 길이는 ADCLK주기의 (ACQ_PS + 1)배이다. 즉, 여기서는 8배


Part2

5. MAXCONV.all = 0x0004로 인해, 최대 변환 채널수는 4개가 된다. 단, 직렬 시퀀서 모드는 두 시퀀서 1,2를 하나의 시퀀서처럼 사용하기 때문에 총 합쳐서 4개일 것이다.

6. ADCCHSELSEQ는 ADC변환의 순서와 관련된 것으로 위에서는 시퀀서1(1,2통합되있음)의 0번인 Gyro를 첫째로, 1번인 Tilt를 두번째 순서로 잡아줬다.

수정이 필요한 사항인것이, 현재 각각의 센서를 어느 핀에 연결했느냐에 따라 CONV0~15사이에서 선택해주어야 한다.

7.CONT_RUN = 1로 인해 Continus run mode로 설정하였다. 한번 변환이 끝나면 자동으로 다음 변환을 한다.

8.SOC_SEQ1에 1을 줌으로써 시퀀서 1에 변환시작신호를 전달하였다.

(굳이 줄 필요가 없다고 생각하는게, 이는 시퀀스에 대한 동작신호라기 보다는 변환강제신호로 볼 수 있다. 신호가 들어가면 0으로 클리어되고 끝나니 말이다.)



'Project > Balancing 28335' 카테고리의 다른 글

Init_Timer  (0) 2014.08.19
GpioInit  (0) 2014.08.18
Posted by 십자성군
Project/Balancing 283352014. 8. 18. 15:26

#include "DSP2833x_device.h"

#include "DSP2833x_GlobalPrototypes.h"

#include "GlobalProtoypesLee.h"


//***Include any other Headers which are necessary



void Init_GPIO()

{

EALLOW ;

// GPIO MUX Set


GpioCtrlRegs.GPAMUX1.all=0x0000;

GpioCtrlRegs.GPAMUX2.all=0x0000;

GpioCtrlRegs.GPBMUX1.all=0x0000;

GpioCtrlRegs.GPBMUX2.all=0x0000;


GpioMuxRegs.GPAMUX.bit.PWM1_GPIOA0 = 1 ;    // PWM //용도불명

GpioMuxRegs.GPBMUX.bit.PWM7_GPIOB0 = 1 ;    // PWM


GpioCtrlRegs.GPAMUX2.bit.GPIO20=1; //QEP

GpioCtrlRegs.GPAMUX2.bit.GPIO21=1; //QEP

GpioCtrlRegs.GPAMUX2.bit.GPIO22=1; //QEP

GpioCtrlRegs.GPAMUX2.bit.GPIO23=1; //QEP


GpioCtrlRegs.GPAMUX1.bit.GPIO9=2; //SCITXDB

GpioCtrlRegs.GPAMUX1.bit.GPIO11=2; //SCIRXDB


GpioCtrlRegs.GPBMUX2.bit.GPIO62=1; //SCIRXDC

GpioCtrlRegs.GPBMUX2.bit.GPIO63=1; //SCITXDC



GpioMuxRegs.GPEMUX.bit.XINT1_XBIO_GPIOE0 = 1 ;

GpioMuxRegs.GPEQUAL.bit.QUALPRD = 0xff ;


GpioMuxRegs.GPFMUX.bit.SPICLKA_GPIOF2 = 1; //SPI_SCLK

GpioMuxRegs.GPFMUX.bit.SPISIMOA_GPIOF0 = 1; //SPI_SIMO

GpioMuxRegs.GPFMUX.bit.SPISOMIA_GPIOF1 = 1; //SPI_SOMI

GpioMuxRegs.GPFMUX.bit.SPISTEA_GPIOF3 = 1; //SPI_SS



// GPIO DIR Set

GpioMuxRegs.GPADIR.bit.GPIOA1 = 1 ;  // output for motor direction

GpioMuxRegs.GPADIR.bit.GPIOA2 = 1 ;  // 컨트롤주기 확인

GpioMuxRegs.GPADIR.bit.GPIOA4 = 0 ; // 시스템 중간값(offset) 시작위한 스위치. I/O로 설정

GpioMuxRegs.GPBDIR.bit.GPIOB1 = 1 ;  // output for motor direction

GpioMuxRegs.GPBDIR.bit.GPIOB2 = 1 ;  // output for motor break

// GpioMuxRegs.GPFDIR.bit.GPIOF3 = 1 ; // output for SS break

GpioMuxRegs.GPGDIR.bit.GPIOG4 = 1 ; // SCIB TX

GpioMuxRegs.GPGDIR.bit.GPIOG5 = 1 ; // SCIB RX


GpioMuxRegs.GPAQUAL.all = 0x05 ;


// GpioMuxRegs.


EDIS ;

GpioDataRegs.GPFDAT.bit.GPIOF5 = 0 ;

GpioDataRegs.GPADAT.bit.GPIOA1 = 1 ;

GpioDataRegs.GPADAT.bit.GPIOA2 = 1 ;

GpioDataRegs.GPADAT.bit.GPIOA4 = 0 ; // 시스템 중간값.. 해당포트를 입력으로 사용 스위치 켜면 3.3v 전압 인가해서 HIGH가 됨

GpioDataRegs.GPGDAT.bit.GPIOG4 = 1 ;

GpioDataRegs.GPGDAT.bit.GPIOG5 = 1 ;

// GpioDataRegs.GPFDAT.bit.GPIOF3 = 1 ;

}



'Project > Balancing 28335' 카테고리의 다른 글

Init_Timer  (0) 2014.08.19
Init_ADC  (0) 2014.08.19
Posted by 십자성군
Project/Balancing Robot2014. 7. 27. 23:13

엔코더를 사용할 때, 풀업을 해주어야 한다. 이와 관련해서 설명하고자 한다.

 

 

 

위의 그림을 보면 A와 B상의 output이 저항을 건너 MCU의 Input에 연결되어 있다.

아래는 이에 대한 설명이다(맞는지 모르겠다. 틀린곳이 있다면 설명 바랍니다. 회로쪽은 잘 몰라서...)

 

 

내가 이해를 잘 못했을지도 모르겠고 나중에 다시 물어봐서 수정해야 겠다.

 

 

일단, 엔코더를 사용할 때는, 엔코더에 넣어주는 전원은 MCU와는 따로 사용해 준다.

엔고더의 센서에서 나오는 전류값은 낮다. 저항을 통해 센서와 입력부 사이에 DC 5V전원을 연결해 주었을 때, 센서가 High 상태이면 전원부의 전류는 입력으로 흐를것이고 OFF상태이면 센서로 흐를것이다.




 

 

'Project > Balancing Robot' 카테고리의 다른 글

실습코드 해석. 순서  (0) 2014.07.23
[초기화6] Init_ADC()  (0) 2014.07.23
[초기화5] Init_SPI()  (0) 2014.07.23
[초기화4] Init_SCIA(), Init_SCIB()  (0) 2014.07.23
[초기화3] Init_EVA(), Init_EVB()  (0) 2014.07.23
Posted by 십자성군
Project/Balancing Robot2014. 7. 23. 19:15

 

 

 

'Project > Balancing Robot' 카테고리의 다른 글

엔코더와 풀업, 전압분배  (0) 2014.07.27
[초기화6] Init_ADC()  (0) 2014.07.23
[초기화5] Init_SPI()  (0) 2014.07.23
[초기화4] Init_SCIA(), Init_SCIB()  (0) 2014.07.23
[초기화3] Init_EVA(), Init_EVB()  (0) 2014.07.23
Posted by 십자성군
Project/Balancing Robot2014. 7. 23. 14:53

void Init_ADC()
{


// AdcRegs.ADCTRL1.bit.RESET = 1 ;  // Adc module Reset
// asm(" RPT #12 || nop ") ;   // Reset는 3 ADC_CLK 지연이 발생한다.
          // 현재 ADC_CLK으로
 InitAdc();

 // ADC 설정
 AdcRegs.ADCTRL3.bit.ADCCLKPS = 15;     // ADCCLKPS = HSPCLK / 30 (ADCCLKPS = 2.5MHz)
 AdcRegs.ADCTRL1.bit.CPS = 1;   // ADCCLK = ADCCLKPS / 2 (ADC의 구동 클럭을 결정 : ADCCLK = 1.25MHz)
 AdcRegs.ADCTRL1.bit.SEQ_CASC = 1;  // 시퀀스 직렬 모드
 AdcRegs.ADCTRL1.bit.ACQ_PS = 7 ;  // 샘플링 윈도우 size를 8 ADC_CLK 설정
// AdcRegs.ADCMAXCONV.all = 0x0002;       // ADC??개수 설정 : 모두 2개 ADC를 변환
 AdcRegs.ADCMAXCONV.all = 0x0004;
 AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0;  // Murata [ Gyro ]
 AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1; // SA1 [ Tilt ] 4
// AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 2; // Z [ Accelerometer ]
// AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 3; // Y [ Accelerometer ]
// AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 8; // X [ Accelerometer ]
// AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 5; // SCA10T [ Tilt ] 5

// AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 2;
 AdcRegs.ADCTRL1.bit.CONT_RUN = 1;    // Cont. conv. mode
 AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;  // 시퀀스 시작


}

'Project > Balancing Robot' 카테고리의 다른 글

엔코더와 풀업, 전압분배  (0) 2014.07.27
실습코드 해석. 순서  (0) 2014.07.23
[초기화5] Init_SPI()  (0) 2014.07.23
[초기화4] Init_SCIA(), Init_SCIB()  (0) 2014.07.23
[초기화3] Init_EVA(), Init_EVB()  (0) 2014.07.23
Posted by 십자성군
Project/Balancing Robot2014. 7. 23. 14:52

void Init_SPI()
{


 SpiaRegs.SPICCR.bit.CLKPOLARITY =0;
 SpiaRegs.SPICTL.bit.CLK_PHASE =0;

 SpiaRegs.SPICCR.bit.SPISWRESET =0;
 asm(" RPT #10 || nop ") ;
 SpiaRegs.SPICCR.bit.CLKPOLARITY =0;
 SpiaRegs.SPICCR.bit.SPILBK =0;
 SpiaRegs.SPICCR.bit.SPICHAR = 0xff;
 SpiaRegs.SPICCR.bit.SPISWRESET =1;

 SpiaRegs.SPICTL.bit.SPIINTENA =0;   //master,slave 선택
 SpiaRegs.SPICTL.bit.TALK =1;    //spi활성화
 SpiaRegs.SPICTL.bit.MASTER_SLAVE =1;
 SpiaRegs.SPICTL.bit.CLK_PHASE =0;
 SpiaRegs.SPICTL.bit.OVERRUNINTENA=0;
 SpiaRegs.SPICTL.bit.SPIINTENA =0;

 SpiaRegs.SPIPRI.bit.FREE = 1;
 SpiaRegs.SPIBRR = 7 ;

 

}

 

'Project > Balancing Robot' 카테고리의 다른 글

실습코드 해석. 순서  (0) 2014.07.23
[초기화6] Init_ADC()  (0) 2014.07.23
[초기화4] Init_SCIA(), Init_SCIB()  (0) 2014.07.23
[초기화3] Init_EVA(), Init_EVB()  (0) 2014.07.23
[초기화2] Init_GPIO()  (0) 2014.07.23
Posted by 십자성군
Project/Balancing Robot2014. 7. 23. 14:51

void Init_SCIA()
{


 SciaRegs.SCICCR.bit.STOPBITS = 0 ;  // One Stop bit
 SciaRegs.SCICCR.bit.PARITY = 0 ;  // Odd parity(ignored)
 SciaRegs.SCICCR.bit.PARITYENA = 0 ;  // Parity disable
 SciaRegs.SCICCR.bit.LOOPBKENA = 0 ;  // loop back mode disable
 SciaRegs.SCICCR.bit.ADDRIDLE_MODE = 0 ; // Idle-line mode (normal)
 SciaRegs.SCICCR.bit.SCICHAR = 0x07 ; // SCI char-length 8 bit

 SciaRegs.SCICTL1.bit.RXERRINTENA = 1 ; // SCI receive error interrupt disable
 SciaRegs.SCICTL1.bit.SWRESET = 0 ;  // SCI module reset
 asm(" RPT #10 || nop ") ;
 SciaRegs.SCICTL1.bit.SWRESET = 1 ;  // SCI mdoule reset release
 SciaRegs.SCICTL1.bit.TXWAKE = 0 ;  // SCI transmitter wake-up method (non use)
 SciaRegs.SCICTL1.bit.SLEEP = 0 ;  // SCI sleep mode non use
 SciaRegs.SCICTL1.bit.TXENA = 1 ;  // SCI transmitter enable
 SciaRegs.SCICTL1.bit.RXENA = 1 ;  // SCI receiver enable

// SciaRegs.SCIHBAUD = 0x01 ;    // ( 37.5M / (9600 * 8) ) - 1 = 0x01e7
// SciaRegs.SCILBAUD = 0xe7 ;
 SciaRegs.SCIHBAUD = 0x00 ;    // ( 37.5M / (38400 * 8 ) - 1 = 0x0079
 SciaRegs.SCILBAUD = 0x79 ;
// SciaRegs.SCIHBAUD = 0x00 ;    // ( 37.5M / (57600 * 8) ) - 1 = 0x0050
// SciaRegs.SCILBAUD = 0x50 ;

 SciaRegs.SCICTL2.bit.RXBKINTENA = 1 ; // Receive buffer or break interrup enable
 SciaRegs.SCICTL2.bit.TXINTENA = 1 ;  // SCITXBUF-register interrupt enable

 SciaRegs.SCIFFTX.bit.SCIRST = 1 ;  // SCI FIFO can resume transmit or receive
 SciaRegs.SCIFFTX.bit.SCIFFENA = 0 ;  // SCI FIFO enhancements are enable
 SciaRegs.SCIFFTX.bit.TXFIFOXRESET = 0 ; // Transmitter FIFO Re-Enable (FIFO Point to zero reset)
 SciaRegs.SCIFFTX.bit.TXFFIENA = 0 ;  // Transmitter FIFO Interrupt enable
 SciaRegs.SCIFFTX.bit.TXFFILIL = 0 ;  // Transmitter FIFO deep level (5)

 SciaRegs.SCIFFRX.bit.RXFIFORESET = 0 ; // Receive FIFO Re-Enable
 SciaRegs.SCIFFRX.bit.RXFFIENA = 0 ;  // Receive FIFO Interrupt Enable
 SciaRegs.SCIFFRX.bit.RXFIFST = 4;       // RX FIFO 4개로 함
 SciaRegs.SCIFFRX.bit.RXFFIL = 0 ;  // Receive FIFO deep level (5)

 

}

 

void Init_SCIB()
{


 ScibRegs.SCICCR.bit.STOPBITS = 0 ;  // One Stop bit
 ScibRegs.SCICCR.bit.PARITY = 0 ;  // Odd parity(ignored)
 ScibRegs.SCICCR.bit.PARITYENA = 0 ;  // Parity disable
 ScibRegs.SCICCR.bit.LOOPBKENA = 0 ;  // loop back mode disable
 ScibRegs.SCICCR.bit.ADDRIDLE_MODE = 0 ; // Idle-line mode (normal)
 ScibRegs.SCICCR.bit.SCICHAR = 0x07 ; // SCI char-length 8 bit

 ScibRegs.SCICTL1.bit.RXERRINTENA = 1 ; // SCI receive error interrupt disable
 ScibRegs.SCICTL1.bit.SWRESET = 0 ;  // SCI module reset
 asm(" RPT #10 || nop ") ;
 ScibRegs.SCICTL1.bit.SWRESET = 1 ;  // SCI mdoule reset release
 ScibRegs.SCICTL1.bit.TXWAKE = 0 ;  // SCI transmitter wake-up method (non use)
 ScibRegs.SCICTL1.bit.SLEEP = 0 ;  // SCI sleep mode non use
 ScibRegs.SCICTL1.bit.TXENA = 1 ;  // SCI transmitter enable
 ScibRegs.SCICTL1.bit.RXENA = 1 ;  // SCI receiver enable

// ScibRegs.SCIHBAUD = 0x01 ;    // ( 37.5M / (9600 * 8) ) - 1 = 0x01e7
// ScibRegs.SCILBAUD = 0xe7 ;
 ScibRegs.SCIHBAUD = 0x00 ;    // ( 37.5M / (38400 * 8 ) - 1 = 0x0079
 ScibRegs.SCILBAUD = 0x79 ;
// ScibRegs.SCIHBAUD = 0x00 ;    // ( 37.5M / (57600 * 8) ) - 1 = 0x0050
// ScibRegs.SCILBAUD = 0x50 ;

 ScibRegs.SCICTL2.bit.RXBKINTENA = 1 ; // Receive buffer or break interrup enable
 ScibRegs.SCICTL2.bit.TXINTENA = 1 ;  // SCITXBUF-register interrupt enable

 ScibRegs.SCIFFTX.bit.SCIRST = 1 ;  // SCI FIFO can resume transmit or receive
 ScibRegs.SCIFFTX.bit.SCIFFENA = 0 ;  // SCI FIFO enhancements are enable
 ScibRegs.SCIFFTX.bit.TXFIFOXRESET = 0 ; // Transmitter FIFO Re-Enable (FIFO Point to zero reset)
 ScibRegs.SCIFFTX.bit.TXFFIENA = 0 ;  // Transmitter FIFO Interrupt enable
 ScibRegs.SCIFFTX.bit.TXFFILIL = 0 ;  // Transmitter FIFO deep level (5)

 ScibRegs.SCIFFRX.bit.RXFIFORESET = 0 ; // Receive FIFO Re-Enable
 ScibRegs.SCIFFRX.bit.RXFFIENA = 0;  // Receive FIFO Interrupt Enable
 ScibRegs.SCIFFRX.bit.RXFFIL = 0 ;  // Receive FIFO deep level (5)


}

 

'Project > Balancing Robot' 카테고리의 다른 글

[초기화6] Init_ADC()  (0) 2014.07.23
[초기화5] Init_SPI()  (0) 2014.07.23
[초기화3] Init_EVA(), Init_EVB()  (0) 2014.07.23
[초기화2] Init_GPIO()  (0) 2014.07.23
[초기화1] DSP_Init()  (0) 2014.07.23
Posted by 십자성군