ADXL345 Digital Accelerometer Lab

References

  • ADXL345.pdf
  • GY-291-schematic.jpg
  • MySpiMasterSlave

Programming Library for ADXL345

  • ADXL345를 사용하는 함수들을 설계하고 구현한다.
  • 이것들을 모아서 Library를 만든다.

  • Data

int16_t AccelX;   /* -2g ~ +2g : -512 ~ 511 */
int16_t AccelY;
int16_t AccelZ;
  • Methods
void ADXL345_WriteRegister(uint8_t reg, uint8_t value);
uint8_t ADXL345_ReadRegister(uint8_t reg);
bool ADXL345_Begin(void);
void ADXL345_GetXYZ_Polling(void);

Basic: ReadRegister() WriteRegister()

  • ADXL345_WriteRegister( )는 다음과 같이 만들 수 있다.
void ADXL345_WriteRegister(uint8_t reg, uint8_t value){
    MasterDataTx[0] = 0x00 | reg;
    MasterDataTx[1] = value;
    while(SPI_MASTER_IsTxBusy(&dhSPI_MASTER))  {  }
    SPI_MASTER_Transfer(&dhSPI_MASTER, MasterDataTx, MasterDataRx, FrameByte);
}
  • Full Duplex mode로 동작해야 하므로 SPI_MASTER_Trasnfer method를 사용하여 2byte의 MasterDataTx를 전송하고 MasterDataRx의 자료를 받는다.
  • 전송이 완료되기 전에 다시 이 함수가 호출되어 Over-run 이 발생되는 상황을 방지하기 위하여 SPI_MASTER_IsTxBusy( )Method를 사용하여 Busy-wait 한다.

[Activity] ADXL345_ReadRegister( ) 함수를 완성하여 보아라

  • Read Cycle을 수행하기 위해서는 MasterDataTx[0] 에 어떤 값을 넣어 주어야 하는가?

  • 유효한 데이터는 어디에 존재하는가?

  • SPI_MASTER_Trasnfer( ) Method 동작이 모두 완료되어야 MasterDataRx에 Data 가 들어오게 된다. 어떻게 그때까지 Busy-wait 시킬 수 있나?

uint8_t ADXL345_ReadRegister(uint8_t reg){




    return(         );
}

Set-Up: Begin()

  • ReadRegister(), WriteRegister() 함수를 사용하여 기본정보를 확인하고, 설정할 수 있다.

    • DEVID: Device ID를 읽어서 그 값이 0xE5 인지 확인한다.
    • BW_RATE: 현재 1000KHz 의 전송속도를 고려하여 800Hz로 Conversion Rate를 설정한다.
    • POWER_CTL: Measurement bit를 Set 하여 Conversion을 시작한다.
bool ADXL345_Begin(void){
    uint8_t device_id;
    /* Get & Check DEVID */
    device_id = ADXL345_ReadRegister(ADXL345_DEVID);
    if(device_id != 0xE5){
        return false;
    }

    ADXL345_WriteRegister(ADXL345_POWER_CTL, 0x08); /* Enable measurements */
    ADXL345_WriteRegister(ADXL345_BW_RATE, 0x0D); /* Set Conversion Rate 800Hz */
    return(true);
}

Read Acceleration X, Y, Z

  • DATAX0 와 DATAX1 레지스터를 읽어들여서 가속도 정보의 Lower byte와 Upper byte를 얻는다.

[Activity] Lower byte와 Upper byte 정보를 조합하여 AccelX 정보를 만들어 낸다.

void ADXL345_GetXYZ_Polling(void){
    uint16_t upper, lower;
    lower = ADXL345_ReadRegister(ADXL345_DATAX0);
    upper = ADXL345_ReadRegister(ADXL345_DATAX1);
    // Calculate AccelX using lower & upper
    AccelX = 

    /* 이하 생략 */
}

Test

  • TestAdxl345() 함수는 10msec 마다 실행하도록 설정되어 있다.
  • 이 함수 내부에서 AccelX의 값에 따라서 LED1, LED2 의 밝기가 변화하도록 프로그래밍 되어 있다.
  • 프로그램을 실행하고 ADXL345 센서를 X축 방향으로 기울여 가면서 LED1과 LED2의 변화를 관찰한다.
  • 정확한 값의 변화를 확인하기 위하여 Debugger, 혹은 uC/Probe를 사용하여 AccelY와 AccelZ의 값을 살펴본다.

Optimization

  • 현재 프로그램은 X, Y, Z 축의 Data를 읽어들이기 위하여 총 96bit (8bit X 12)의 시간동안 Polling 방식으로 통신을 하고 있다. 1000KHz의 통신 속도로 전송하므로 1usec X 96 의 시간동안 통신을 위한 대기 상태를 유지하게 된다. 약 0.1 msec의 시간을 낭비하게 되는 것이다.
  • 현재와 같이 단순한 작업을 진행하는 상황이라면 크게 문제되지 않지만, 해야하는 테스크가 늘어나거나, 신호처리의 주기가 짧아지는 상황이라면 최적화를 해야할 필요가 있다.
  • Interrupt를 사용하는 전송방식으로 프로그램을 개선한다면 이 대기 시간을 대폭적으로 줄일 수 있게 된다.

[Activity] Interrupt를 사용하여 ADXL345_GetXYZ(void) Method를 새롭게 만들고, Data의 수신이 완료되면 ISR_SpiMasterRx( )에서 AccelX, AccelY, AccelZ 값을 Update 하도록 개선해 보아라.