# Acceleration Magnitude

## Lab 2: คำนวณ Acceleration Magnitude

### วัตถุประสงค์

* **Motion Detection**: ขนาดของ acceleration บอกระดับการเคลื่อนไหว
* **Gravity Reference**: วางนิ่ง = 1g (9.81 m/s²)
* **Impact Detection**: ตกกระแทก = magnitude spike

#### จะได้เรียนรู้อะไร

1. **Vector Magnitude**: √(x² + y² + z²)
2. **Math Functions**: sqrtf()
3. **Physical Meaning**: ความหมายของ magnitude

### 2.1 Concept: Vector Magnitude

$$
\text{magnitude} = \sqrt{x^2 + y^2 + z^2}
$$

{% hint style="info" %}
**เมื่อวางราบ:**

* x ≈ 0, y ≈ 0, z ≈ 9.81
* Magnitude ≈ 9.81 m/s² (1g)

**เมื่อเคลื่อนไหว:**

* Magnitude > 9.81 หรือ < 9.81
* สามารถใช้ตรวจจับการเคลื่อนไหว!

**เมื่อตกอิสระ:**&#x20;

* Magnitude ≈ 0 (weightlessness)
  {% endhint %}

### <mark style="color:green;">โหลด Project Code จาก AIC Github Repo เพื่อเปิดบน VSCode IDE</mark>

{% embed url="<https://github.com/Advance-Innovation-Centre-AIC/aic-psoc-edge-epc2-imu-magnitude>" %}

{% embed url="<https://youtu.be/ad2l0MAGdII>" fullWidth="true" %}

### 2.2 เปิดโปรเจกต์ aic-psoc-edge-epc2-imu-magnitude-master

เปิดไฟล์ `proj_cm33_ns/sensor_hub_daq_task.c` และศึกษาโครงสร้าง:

```shellscript
aic-psoc-edge-epc2-imu-magnitude-master/
├── proj_cm33_s/              # Secure Project
├── proj_cm33_ns/             
│   ├── main.c
│   ├── sensor_hub_daq_task.c 
│   └── sensor_hub_daq_task.h
└── proj_cm55/                # CM55 Project
```

#### เพิ่ม Include

```c
#include <math.h>  /* sqrtf */
```

#### **Important Macros and Variables**

```c
/*******************************************************************************
* Macros
*******************************************************************************/
#define GRAVITY_EARTH                       (9.80665f)
#define DEG_TO_RAD                          (0.01745f)
#define GYR_RANGE_DPS                       (2000.0f)
#define ACC_RANGE_2G                        (2.0f)

/* Custom app module ID to avoid collisions */
#define APP_RSLT_MODULE_ID                  (1U)

/* App error for task creation failure */
#define APP_RSLT_ACQ_TASK_CREATE_FAILED     CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR,\
                                                        APP_RSLT_MODULE_ID,\
                                                        1U)

/*******************************************************************************
* Global Variables
*******************************************************************************/
static mtb_hal_i2c_t CYBSP_I2C_CONTROLLER_hal_obj;
static cy_stc_scb_i2c_context_t CYBSP_I2C_CONTROLLER_context;

static mtb_bmi270_data_t bmi270_data;
static mtb_bmi270_t bmi270;

static cy_en_scb_i2c_status_t initStatus;
static cy_rslt_t result;
```

#### สร้างฟังก์ชัน Raw accelerometer Conversion ชื่อ `lsb_to_mp2()`

```c
/*******************************************************************************
 * Function Name: lsb_to_mps2
 *******************************************************************************
 * Summary:
 *   Converts raw accelerometer value to m/s²
 *
 * Parameters:
 *   val       - raw value from sensor (-32768 to +32767)
 *   g_range   - accelerometer range in g (2 = ±2g)
 *   bit_width - data width in bits (16)
 *
 * Return:
 *   float - acceleration in m/s²
 ******************************************************************************/
static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width)
{
    float half_scale = (float)(1u << (bit_width - 1u));
    return ((GRAVITY_EARTH) * val * g_range) / half_scale;
}
```

#### **สร้างฟังก์ชัน Magnitude Calcuation ชื่อ `calculate_magnitude()`**

```c
/*******************************************************************************
 * Function Name: calculate_magnitude
 *******************************************************************************
 * Summary:
 *   Calculates the magnitude of acceleration vector: |acc| = sqrt(x² + y² + z²)
 *   Used for motion detection and impact sensing.
 *
 * Parameters:
 *   acc_x, acc_y, acc_z - acceleration components in m/s²
 *
 * Return:
 *   float - magnitude in m/s² (stationary ≈ 9.81 m/s² = 1g)
 *
 * Note:
 *   - Stationary: magnitude ≈ 9.81 m/s² (1g from gravity)
 *   - Moving: magnitude deviates from 9.81
 *   - Free fall: magnitude ≈ 0 (weightlessness)
 ******************************************************************************/
static float calculate_magnitude(float acc_x, float acc_y, float acc_z)
{
    return sqrtf(acc_x * acc_x + acc_y * acc_y + acc_z * acc_z);
}
```

### 2.3 เขียน Main Task Loop

```c
/*******************************************************************************
 * Function Name: sensor_hub_daq_task
 *******************************************************************************
 * Summary:
 *   FreeRTOS task that reads BMI270 sensor and displays magnitude
 ******************************************************************************/
static void sensor_hub_daq_task(void *pvParameters)
{
    TickType_t xLastWakeTime = 0;
    const TickType_t xDelay = 100 / portTICK_PERIOD_MS;

    float acc_x = 0.0f;
    float acc_y = 0.0f;
    float acc_z = 0.0f;
    float magnitude = 0.0f;

    (void)pvParameters;

    /* Initialize I2C */
    initStatus = Cy_SCB_I2C_Init(CYBSP_I2C_CONTROLLER_HW,
                                &CYBSP_I2C_CONTROLLER_config,
                                &CYBSP_I2C_CONTROLLER_context);

    if (CY_SCB_I2C_SUCCESS != initStatus)
    {
        handle_app_error();
    }

    Cy_SCB_I2C_Enable(CYBSP_I2C_CONTROLLER_HW);

    result = mtb_hal_i2c_setup(&CYBSP_I2C_CONTROLLER_hal_obj,
                                &CYBSP_I2C_CONTROLLER_hal_config,
                                &CYBSP_I2C_CONTROLLER_context,
                                NULL);

    if (CY_RSLT_SUCCESS != result)
    {
        handle_app_error();
    }

    /* Initialize BMI270 */
    result = mtb_bmi270_init_i2c(&bmi270,
                                &CYBSP_I2C_CONTROLLER_hal_obj,
                                MTB_BMI270_ADDRESS_DEFAULT);

    if (CY_RSLT_SUCCESS != result)
    {
        handle_app_error();
    }

    result = mtb_bmi270_config_default(&bmi270);

    if (CY_RSLT_SUCCESS != result)
    {
        handle_app_error();
    }

    /* Clear screen */
    printf("\x1b[2J\x1b[;H");

    printf("************************************************************\r\n");
    printf("     Lab 2-2: Acceleration Magnitude                        \r\n");
    printf("************************************************************\r\n\r\n");
    printf("Magnitude = sqrt(x^2 + y^2 + z^2)\r\n");
    printf("Stationary: ~9.81 m/s^2 (1g)\r\n\r\n");

    xLastWakeTime = xTaskGetTickCount();

    for (;;)
    {
        /* Read sensor */
        result = mtb_bmi270_read(&bmi270, &bmi270_data);

        if (CY_RSLT_SUCCESS != result)
        {
            handle_app_error();
        }

        /* Convert to m/s² */
        acc_x = lsb_to_mps2(bmi270_data.sensor_data.acc.x,
                            ACC_RANGE_2G,
                            bmi270.sensor.resolution);
        acc_y = lsb_to_mps2(bmi270_data.sensor_data.acc.y,
                            ACC_RANGE_2G,
                            bmi270.sensor.resolution);
        acc_z = lsb_to_mps2(bmi270_data.sensor_data.acc.z,
                            ACC_RANGE_2G,
                            bmi270.sensor.resolution);

        /* Calculate magnitude */
        magnitude = calculate_magnitude(acc_x, acc_y, acc_z);

        /* Display results */
        printf("Accelerometer:\r\n");
        printf("  x: %9.6f m/s^2\r\n", (double)acc_x);
        printf("  y: %9.6f m/s^2\r\n", (double)acc_y);
        printf("  z: %9.6f m/s^2\r\n", (double)acc_z);
        printf("\r\n");
        printf("Magnitude: %9.6f m/s^2 (%.2f g)\r\n",
               (double)magnitude,
               (double)(magnitude / GRAVITY_EARTH));

        /* Move cursor back for clean display */
        printf("\x1b[6A");

        /* Toggle LED to show activity */
        Cy_GPIO_Inv(CYBSP_USER_LED1_PORT, CYBSP_USER_LED1_PIN);

        /* Wait for UART */
        while(!(Cy_SCB_UART_IsTxComplete(CYBSP_DEBUG_UART_HW))) {};

        vTaskDelayUntil(&xLastWakeTime, xDelay);
    }
}
```

#### Create Sensor Hub DAQ Task Function

```c
/*******************************************************************************
 * Function Name: create_sensor_hub_daq_task
 ******************************************************************************/
cy_rslt_t create_sensor_hub_daq_task(void)
{
    BaseType_t status;

    status = xTaskCreate(sensor_hub_daq_task, "IMU Magnitude",
                            TASK_SENSOR_HUB_DAQ_STACK_SIZE, NULL,
                            TASK_SENSOR_HUB_DAQ_PRIORITY, NULL);

    return (pdPASS == status) ?
        CY_RSLT_SUCCESS : APP_RSLT_ACQ_TASK_CREATE_FAILED;
}
```

### 2.4 Build และ Flash

```bash
make build -j8
make program
```

### 2.5 Output ที่คาดหวัง

```bash
Accelerometer:
x: 0.012345, y: -0.023456, z: 9.806650 m/s²
Magnitude: 9.806789 m/s² (1.00 g)

[เมื่อเขย่า]
Magnitude: 12.345678 m/s² (1.26 g)

[เมื่อตกกระแทก]
Magnitude: 24.516625 m/s² (2.50 g)

Gyroscope:
x: 0.001234, y: 0.002345, z: -0.003456

Orientation = ORIENTATION_UP
```

#### Physical Meaning

| สถานะ             | Magnitude     | ความหมาย          |
| ----------------- | ------------- | ----------------- |
| วางนิ่ง           | ≈ 9.81 m/s²   | 1g จากแรงโน้มถ่วง |
| เคลื่อนไหวเบา     | 9.5-10.5 m/s² | ±0.1g deviation   |
| เคลื่อนไหวปานกลาง | 8-12 m/s²     | ±0.3g deviation   |
| ตกกระแทก          | > 20 m/s²     | > 2g (impact)     |
| ตกอิสระ           | ≈ 0 m/s²      | Weightlessness    |

### Flowchart

<figure><img src="/files/tgLgb3nY3BrFUTWyvfju" alt=""><figcaption></figcaption></figure>

***

### ✍️ Exercise

1\. **G-Force Display** : แสดงค่า magnitude ในหน่วย g พร้อม visual indicator

```
|====------| 0.8g (Low)
|=========-| 1.2g (High)
```

{% hint style="info" %}
**Hint**
{% endhint %}

```c
void print_g_force_bar(float magnitude)
{
    float g_force = magnitude / GRAVITY_EARTH;
    int bars = (int)(g_force * 10);  /* 0.1g per bar */

   ...

    printf("|");
    for (int i = 0; i < 20; i++)
    {
        ...
    }
    ...
}
```

2. **Max/Min Tracking :** เก็บค่า max และ min magnitude ที่เคยวัดได้

{% hint style="info" %}
**Hint**

```c
static float max_magnitude = 0.0f;
static float min_magnitude = 100.0f;

void track_magnitude(float magnitude)
{
    if (magnitude > max_magnitude)
    {
        ...
    }
    if (magnitude < min_magnitude)
    {
        ...
    }

    printf("Current: %.3f | Min: %.3f | Max: %.3f m/s²\r\n",
           (double)magnitude,
           (double)min_magnitude,
           (double)max_magnitude);
}
```

{% endhint %}

***

**จบ Session 2** | **ต่อไป:** Session 3: LVGL Display


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.aic-eec.com/interfacing-with-infineon-psoc-tm-edge/sensor-interfacing/workshops/acceleration-magnitude.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
