2014/12/05

BeagleBone Black 커널 컴파일

Host PC 정보
  - OS : ubuntu 14.04 LTS
  프로세서 : Intel® Core™ i7-4610M CPU @ 3.00GHz × 4 
  그래픽 : Intel® Haswell Mobile 
  OS 종류 : 64비트
  메모리 : 3.8 GiB

기본 폴더는 /home/user_id/BBB 에서 작업을 시작하자.

1. ARM Cross Compiler 설치

samba@samba:~/BBB$ wget -c https://releases.linaro.org/14.09/components/toolchain/binaries/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux.tar.xz
samba@samba:~/BBB$ tar xf gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux.tar.xz
samba@samba:~/BBB$ export CC=`pwd`/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-


Linaro GCC 버전은 32비트니까 ia32-libs 설치해야한다.

  - sudo apt-get install ia32-libs

ia32-libs가 설치가 안되면 아래 링크로 직접 다운받아서 설치하라.
https://dl.dropboxusercontent.com/u/54450962/ia32-libs_1.0_all.deb

${CC}gcc --version 을 실행하면 잘 설치된건지 확인할 수 있다.
samba@samba:~/BBB$ ${CC}gcc --version
arm-linux-gnueabihf-gcc (crosstool-NG linaro-1.13.1-4.9-2014.09 - Linaro GCC 4.9-2014.09) 4.9.2 20140904 (prerelease)
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

samba@samba:~/BBB$



2. Bootloader : U-Boot

일단 부트로더 다운로드 하고
samba@samba:~/BBB$ git clone git://git.denx.de/u-boot.git
samba@samba:~/BBB$ cd u-boot/
samba@samba:~/BBB/u-boot$ git checkout v2014.10 -b tmp




패치한 뒤
samba@samba:~/BBB/u-boot$ wget -c https://raw.githubusercontent.com/eewiki/u-boot-patches/master/v2014.10/0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch

samba@samba:~/BBB/u-boot$ patch -p1 < 0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch




빌드
samba@samba:~/BBB/u-boot$ make ARCH=arm CROSS_COMPILE=${CC} distclean
samba@samba:~/BBB/u-boot$ make ARCH=arm CROSS_COMPILE=${CC} am335x_evm_defconfig
samba@samba:~/BBB/u-boot$ make ARCH=arm CROSS_COMPILE=${CC}



3. Upgrade distro "device-tree-compiler" package

samba@samba:~/BBB$ wget -c https://raw.github.com/RobertCNelson/tools/master/pkgs/dtc.sh
samba@samba:~/BBB$ chmod +x dtc.sh
samba@samba:~/BBB$ ./dtc.sh


4. Linux Kernel

다운받고

samba@samba:~/BBB$ git clone https://github.com/RobertCNelson/bb-kernel.git
samba@samba:~/BBB$ cd bb-kernel/


v3.8.x로 쳌아웃

samba@samba:~/BBB$ git checkout origin/am33x-v3.8 -b tmp


TI BSP를 해야되는건지 안해도 되는건지....

v3.8.x로 쳌아웃한 경우에는 TI BSP를 쓰지않고,
v3.18x로 쳌아웃한 경우에 TI BSP를 쓰는거 같긴한데...

모르겠으니 TI BSP는 생략하고 커널 빌드를 해보자.

samba@samba:~/BBB/bb-kernel$ ./build_kernel.sh

혹시 머머머 설치하라고 뜨면 그대로 설치해 주자.
난 이거 깔라고 뜨드라.

  - apt-get install lzma u-boot-tools

5. Root File System

Debian 7, Debian 8, Ubuntu 14.04.01, small flash Debian 7 중에서 선택해서 하나 고르면 되는 모양이다. 난 무난하게 Debian 7...

다운받고...

samba@samba:~/BBB$ wget -c https://rcn-ee.net/deb/barefs/wheezy/debian-7.7-bare-armhf-2014-11-10.tar.xz



확인하고...

samba@samba:~/BBB$ md5sum debian-7.7-minimal-armhf-2014-11-10.tar.xz
edee8eef5fa47ed2427a01ddf2f726c8 debian-7.7-minimal-armhf-2014-11-10.tar.xz



풀기....

samba@samba:~/BBB$ tar xf debian-7.7-minimal-armhf-2014-11-10.tar.xz




이따 SD 카드로 옮기자



2014/12/04

STM32에 MCX314AL을 붙여보자 -- 5. TMC2660 굴려먹기

이젠 Bipolar 스텝모터 드라이버(TMC2660)를 돌려보자.

회로 설계할때 읽어봐서 스펙을 다 까먹었으니까 다시 확인해보자.


Features and Benefits

- Drive Capability up to 4A motor current
- Voltage up to 30V DC
- Highest Resolution up to 256 microsteps per full step
- Compact size 10x10mm QFP-44 package
- Low power dissipation, very low RDSON & synchronous rectification
- EMI-optimizes programmable slope
- Protection & Diagnostics overcurrent, short to GND, overtemperature & undervoltage
- stallGuard2 high precision sensorless motor load detection
- coolStep load dependent current control for energy savings up to 75%
- microPlyer microstep interpolation for increased smoothness with coarse step input
- spreadCycle high-precision chopper for best current sine wave form and zero crossing

요약하자면 4A, 30V 범위내의 바이폴라 모터를 돌릴 수 있고, 256 마이크로스텝을 지원하며, 여러가지 부가기능들이 있다...정도

만들어 놓은 회로도도 보자.































데이터시트의 샘플 회로를 매우 참조하였음.































내가 설계한 회로도의 R31, R32는 Rsense 저항값인데 값이 0.1 ohm 이면 전류값을 3A로 제한한다. 데이터시트의 샘플 회로도 상에서 Rsense 저항은 R3, R4 이다. 0.075 ohm 으로 설정되어 있는데 이건 전류값을 4A로 제한한다는 의미이다.
데이터시트에 이렇게 명시되어 있다.


모터 스펙에 맞춰쓰면 될거다.
그리고 SPI로도 전류를 세팅해 줄 수 있다. Rsense로 최대값을 제한해 두고 SPI로 세밀하게 전류를 설정해서 쓰는 모양이다.

TMC2660의 인터페이스는 아래와 같다.

- ENN
- SG_TST
- DIR
- STEP
- SDO
- SDI
- SCK
- CSN

SPI만으로 모터를 굴릴수 있는건 아닌거같고, 초기값 설정을 SPI로 해주고 Pulse/Dir으로 모터를 제어해 주는거 같다.
Pulse/Dir은 MCX314AL에서 제어해주면 될거고, MCU로 초기값을 SPI로 날려만 주면 되겠군.

TMC2660을 포함한 Trinamic의 모터 드라이버들은 20-bit가 SPI 통신의 기본 사이즈인거 같다.
STM32의 SPI는 8-bit or 16-bit가 기본인데 말이야.

TMC2660의 데이터시트 내용 중 SPI 관련 파트를 읽어보면 이런 내용이 있다.

If more than 20 clocks are driven, the additional bits shifted into SDI are shifted out on SDO after a 20-clock delay through an internal shift register. This can be used for daisy chaining multiple chips.

24 비트를 날려주면 최상위 4바이트는 SDO로 밀려나고 나머지 20 비트만 인식된다는 이야기 같은데...
0001 0002 0003 0004 0005 0006 이렇게 24 비트를 보내면 0001은 인식 안되고 0002 0003 0004 0005 0006 만 인식된다고 일단 생각하자.

그럼 초기화를 어떻게 시켜야 하느냐가 문제인디...
Device Initialization에 대한 내용이 데이터시트에 나온다.

 6.11 Device Initialization

The following sequence of SPI commands is an example of enabling the driver and initializing the chopper:

    SPI = $901B4;    // Hysteresis mode
    or
    SPI = $94557;    // Constant toff mode
    SPI = $D001F;    // Current setting : $d001d (max. current)
    SPI = $E0010;    // low driver strenth, stallGuard2 read, SDOFF = 0
    SPI = $00000;    // 256 microstep setting

First test of coolStep current control:
    SPI = $A8202;    // Enable coolStep with minimum current 1/4 CS

1010 1000 0010 0000 0010

The configuration parameters should be tuned to the motor and application for optimum performance.


TMC2660에는 5개의 write-only register가 존재한다.

- Driver Control Register(DRVCTRL)
- Chopper Configuration Register(CHOPCONF)
- coolStep Configuration Register(SMARTEN)
- stallGuard2 Configuration Register(SGCSCONF)
- Driver Configuration Register(DRVCONF)























DRVCTRL 레지스터는 DRVCONF 레지스터의 SDOFF 비트값에 따라 두가지 포맷을 가진다.
SDOFF 비트를 set 으로 설정하면 SPI로 모터를 컨트롤하고, clear로 설정하면 Step/Dir으로 모터를 컨트롤하게 된다.

으응??? SPI로 어떻게 모터를 돌린다는거지???

CA[7:0], CB[7:0] 레지스터의 값으로 코일 A와 B의 전류값을 세팅한다는데 아마도 이 값을 계속 변경시켜서 모터를 돌린다는 이야기 같긴 하다.


머...그건 그렇고 초기화 코드의 의미를 하나하나 확인해 보자.

그런데 아 안되겠어...타이핑을 다 할 수가 없어...

일단 저 초기화 코드에서 전류 세팅만 내가 사용할 모터에 맞게 바꾸고 나머진 그대로 쓸련다.


















1.4A에 최대한 가깝게 세팅해 주자.

SPI = $D001F; //이부분을
SPI = $D000F; //이렇게 바꾼다

하드웨어 상 3A로 전류 설정을 해놨으니까 15/32로 current scale을 설정하면 될거같다.
계산해 보면

    15/32*3 = 1.40625A

이렇다 이거지.



  //////////////////////////////////////////////////////////////////////////////
//TMC2660 Init
FT800_TxBuffer[0] = 0x09;
FT800_TxBuffer[1] = 0x45;
FT800_TxBuffer[2] = 0x57;
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, FT800_TxBuffer, FT800_RxBuffer, 3, 100);
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_13, GPIO_PIN_SET);

FT800_TxBuffer[0] = 0x0D;
FT800_TxBuffer[1] = 0x00;
FT800_TxBuffer[2] = 0x04;
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, FT800_TxBuffer, FT800_RxBuffer, 3, 100);
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_13, GPIO_PIN_SET);

FT800_TxBuffer[0] = 0x0E;
FT800_TxBuffer[1] = 0x00;
FT800_TxBuffer[2] = 0x10;
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, FT800_TxBuffer, FT800_RxBuffer, 3, 100);
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_13, GPIO_PIN_SET);

FT800_TxBuffer[0] = 0x00;
FT800_TxBuffer[1] = 0x00;
FT800_TxBuffer[2] = 0x00;
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, FT800_TxBuffer, FT800_RxBuffer, 3, 100);
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_13, GPIO_PIN_SET);
//TMC2660 Init
//////////////////////////////////////////////////////////////////////////////


TMC2660 초기화 코드를 이렇게 짜주고...아차 전류세팅은 15/32에서 4/32로 바꿨다.



          outpw(adr+wr0, 0x8000);

osDelay(200);

command(0x3,0xf);
outpw(adr+wr1, 0x0000);
outpw(adr+wr2, 0x0040);
outpw(adr+wr3, 0x0000);
expmode(0x3,0x5d08,0x497f);

accofst(0x3,0);
range(0x3,800000);
acac(0x3,1010);
dcac(0x3,1010);
acc(0x3,100);
dec(0x3,100);
startv(0x3,50);
speed(0x3,40);
pulse(0x3,10);
lp(0x3,0);
ep(0x3,0);

command(0xc,0xf);
outpw(adr+wr1, 0x0000);
outpw(adr+wr2, 0x0040);
outpw(adr+wr3, 0x0000);
expmode(0x4,0x5d08,0x01c4);
expmode(0x8,0x5d08,0x010c);

accofst(0xc,0);
range(0xc,800000);
acac(0xc,1010);
dcac(0xc,1010);
acc(0xc,100);
dec(0xc,100);
startv(0xc,50);
speed(0xc,40);
pulse(0xc,10);
lp(0xc,0);

outpw(adr+wr4, 0x0000);
outpw(adr+wr5, 0x0124);

acc(0x1,200);
speed(0x1,8000);
pulse(0x1,40000);
while(1){
command(0x1,0x20);
wait(0x1);
command(0x1,0x21);
wait(0x1);
}


MCX314AL 구동 루틴은 이렇게 만들어서 돌리보자.





ㅋㅋㅋㅋ 돈다 돌아 ㅋㅋㅋㅋ