> For the complete documentation index, see [llms.txt](https://docs.aic-eec.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.aic-eec.com/interfacing-with-infineon-psoc-tm-edge/hmi-development/sensor-to-hmi-display/ux-ui-workshops/chart-dashboard.md).

# Chart Dashboard

## Lab 6: Chart Dashboard (Multiple Chart Types)

***

### 1. โครงสร้างภาพรวมของ Lab

#### Why? - ทำไมต้องเรียนรู้เรื่องนี้

* **Data Visualization**: ข้อมูลเดียวกันแสดงได้หลายรูปแบบ เลือก chart ที่เหมาะกับลักษณะข้อมูล
* **Chart Type Selection**: Bar chart เหมาะกับเปรียบเทียบค่า, Line chart เหมาะกับ time-series, Scatter chart เหมาะกับดูความสัมพันธ์
* **Professional Dashboard**: รูปแบบ multi-chart dashboard ใช้ในอุตสาหกรรม SCADA, Process Control

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

1. **Bar Chart**: เปรียบเทียบค่า X, Y, Z แบบ side-by-side ด้วย `LV_CHART_TYPE_BAR`
2. **Area Chart**: แสดง trend พร้อม fill ด้านล่าง (Line + Opacity)
3. **Scatter Chart**: แสดงความสัมพันธ์ X vs Y ด้วย `LV_CHART_TYPE_SCATTER`
4. **Line Chart**: Multi-series time-series
5. **2x2 Grid Layout**: จัดวาง 4 charts ในหน้าเดียว

#### How? - จะทำอย่างไร

1. สร้าง 2x2 grid layout บนหน้าจอ (480x320)
2. มุมซ้ายบน: Bar Chart - เปรียบเทียบ Accel X/Y/Z
3. มุมขวาบน: Area Chart - Magnitude over time
4. มุมซ้ายล่าง: Scatter Chart - X vs Y correlation
5. มุมขวาล่าง: Line Chart - Gyroscope Roll/Pitch/Yaw
6. Single timer อัพเดททุก chart ทุก 100ms

<figure><img src="https://1856353139-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MClo3nC-1US0rbK8Qau%2Fuploads%2F9PgM0BTaQuCW5nQOzfo9%2Fweek4_ex6_chart_dashboard.gif?alt=media&amp;token=2928fac6-dffb-4875-adcc-68dc764060bb" alt=""><figcaption></figcaption></figure>

***

### 2. ฟังก์ชันสำคัญ

#### 2.1 Chart Type Constants

<table><thead><tr><th width="207.4801025390625">Constant</th><th width="179.8721923828125">Description</th><th>Update Method</th></tr></thead><tbody><tr><td><code>LV_CHART_TYPE_LINE</code></td><td>เส้นเชื่อมจุด (default)</td><td><code>lv_chart_set_next_value()</code></td></tr><tr><td><code>LV_CHART_TYPE_BAR</code></td><td>แท่ง bar graph</td><td><code>lv_chart_set_value_by_id()</code> + <code>refresh()</code></td></tr><tr><td><code>LV_CHART_TYPE_SCATTER</code></td><td>จุดกระจาย (x, y)</td><td><code>lv_chart_set_next_value2()</code></td></tr></tbody></table>

#### 2.2 Bar Chart Functions

<table><thead><tr><th width="420.54833984375">Function</th><th>Description</th></tr></thead><tbody><tr><td><code>lv_chart_set_type(chart, LV_CHART_TYPE_BAR)</code></td><td>ตั้งเป็น Bar chart</td></tr><tr><td><code>lv_chart_set_point_count(chart, n)</code></td><td>จำนวน bars (เช่น 3 สำหรับ X/Y/Z)</td></tr><tr><td><code>lv_chart_set_value_by_id(chart, ser, id, val)</code></td><td>อัพเดทค่า bar ตาม index</td></tr><tr><td><code>lv_chart_refresh(chart)</code></td><td><strong>REQUIRED</strong> - รีเฟรชหลังอัพเดท</td></tr><tr><td><code>lv_obj_set_style_pad_column(chart, px, 0)</code></td><td>ระยะห่างระหว่าง bars</td></tr></tbody></table>

#### 2.3 Scatter Chart Functions

<table><thead><tr><th width="534.6072387695312">Function</th><th>Description</th></tr></thead><tbody><tr><td><code>lv_chart_set_type(chart, LV_CHART_TYPE_SCATTER)</code></td><td>ตั้งเป็น Scatter chart</td></tr><tr><td><code>lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_X, min, max)</code></td><td>ช่วงแกน X (<strong>ต้อง set</strong>)</td></tr><tr><td><code>lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, min, max)</code></td><td>ช่วงแกน Y</td></tr><tr><td><code>lv_chart_set_next_value2(chart, ser, x, y)</code></td><td>เพิ่มจุด (x, y)</td></tr></tbody></table>

#### 2.4 Area Chart (Line + Fill)

```c
/* Area Chart = Line Chart + Background Opacity บน LV_PART_ITEMS */
lv_chart_set_type(chart, LV_CHART_TYPE_LINE);
lv_obj_set_style_bg_opa(chart, LV_OPA_50, LV_PART_ITEMS);  /* Fill 50% */
```

#### 2.5 Chart Styling Functions

<table><thead><tr><th width="506.55682373046875">Function</th><th>Description</th></tr></thead><tbody><tr><td><code>lv_obj_set_style_size(chart, w, h, LV_PART_INDICATOR)</code></td><td>ขนาดจุด (0,0 = ซ่อน)</td></tr><tr><td><code>lv_obj_set_style_line_width(chart, px, LV_PART_ITEMS)</code></td><td>ความหนาเส้น</td></tr><tr><td><code>lv_chart_set_div_line_count(chart, h, v)</code></td><td>เส้น grid (horizontal, vertical)</td></tr><tr><td><code>lv_obj_set_style_bg_opa(chart, opa, LV_PART_ITEMS)</code></td><td>Area fill opacity</td></tr></tbody></table>

***

### 3. โค้ดตัวอย่าง

#### 3.1 Global Variables

```c
#include "lvgl.h"
#include <math.h>

#define CHART_POINTS    50
#define SCATTER_POINTS  30
#define CHART_W         220
#define CHART_H         110

/* Bar Chart */
static lv_obj_t * bar_chart;
static lv_chart_series_t * bar_ser;
static lv_obj_t * bar_value_label;

/* Area Chart */
static lv_obj_t * area_chart;
static lv_chart_series_t * area_ser;
static lv_obj_t * area_value_label;

/* Scatter Chart */
static lv_obj_t * scatter_chart;
static lv_chart_series_t * scatter_ser;
static lv_obj_t * scatter_value_label;

/* Line Chart */
static lv_obj_t * line_chart;
static lv_chart_series_t * line_ser[3];
static lv_obj_t * line_value_label;

static lv_timer_t * chart_timer;
```

#### 3.2 Simulation Helpers

```c
static void simulate_imu_accel(float *ax, float *ay, float *az)
{
    static float t = 0.0f;
    t += 0.05f;
    *ax = 0.5f * sinf(t * 1.0f) + 0.1f * sinf(t * 3.7f);
    *ay = 0.3f * cosf(t * 0.7f) + 0.05f * sinf(t * 5.1f);
    *az = 9.81f + 0.2f * sinf(t * 2.0f);
}

static void simulate_imu_gyro(float *gx, float *gy, float *gz)
{
    static float t = 0.0f;
    t += 0.04f;
    *gx = 0.3f * sinf(t * 1.5f);
    *gy = 0.2f * cosf(t * 1.2f);
    *gz = 0.15f * sinf(t * 0.8f);
}
```

#### 3.3 Timer Callback - อัพเดททุก Chart

```c
static void chart_timer_cb(lv_timer_t * timer)
{
    (void)timer;

    float ax, ay, az, gx, gy, gz;
    simulate_imu_accel(&ax, &ay, &az);
    simulate_imu_gyro(&gx, &gy, &gz);

    /* ===== BAR CHART: Accel X/Y/Z comparison ===== */
    int32_t bx = (int32_t)((ax + 2.0f) * 25.0f);  /* -2..+2 -> 0..100 */
    int32_t by = (int32_t)((ay + 2.0f) * 25.0f);
    int32_t bz = (int32_t)((az / 10.0f) * 10.0f);
    bx = LV_CLAMP(0, bx, 100);
    by = LV_CLAMP(0, by, 100);
    bz = LV_CLAMP(0, bz, 100);

    lv_chart_set_value_by_id(bar_chart, bar_ser, 0, bx);
    lv_chart_set_value_by_id(bar_chart, bar_ser, 1, by);
    lv_chart_set_value_by_id(bar_chart, bar_ser, 2, bz);
    lv_chart_refresh(bar_chart);  /* REQUIRED for bar chart */

    lv_label_set_text_fmt(bar_value_label,
        "X:%.1f Y:%.1f Z:%.1f", (double)ax, (double)ay, (double)az);

    /* ===== AREA CHART: Magnitude over time ===== */
    float mag = sqrtf(ax * ax + ay * ay + az * az);
    int32_t mag_scaled = (int32_t)(mag * 10.0f);
    if(mag_scaled > 150) mag_scaled = 150;

    lv_chart_set_next_value(area_chart, area_ser, mag_scaled);
    lv_label_set_text_fmt(area_value_label, "Mag: %.2f m/s2",
                          (double)mag);

    /* ===== SCATTER CHART: X vs Y ===== */
    int32_t sx = (int32_t)((ax + 2.0f) * 50.0f);  /* -2..+2 -> 0..200 */
    int32_t sy = (int32_t)((ay + 2.0f) * 50.0f);
    lv_chart_set_next_value2(scatter_chart, scatter_ser, sx, sy);
    lv_label_set_text_fmt(scatter_value_label,
        "X:%.2f Y:%.2f", (double)ax, (double)ay);

    /* ===== LINE CHART: Gyroscope Roll/Pitch/Yaw ===== */
    int32_t gr = (int32_t)((gx + 1.0f) * 50.0f);  /* -1..+1 -> 0..100 */
    int32_t gp = (int32_t)((gy + 1.0f) * 50.0f);
    int32_t gyw = (int32_t)((gz + 1.0f) * 50.0f);

    lv_chart_set_next_value(line_chart, line_ser[0], gr);
    lv_chart_set_next_value(line_chart, line_ser[1], gp);
    lv_chart_set_next_value(line_chart, line_ser[2], gyw);

    lv_label_set_text_fmt(line_value_label,
        "R:%.2f P:%.2f Y:%.2f", (double)gx, (double)gy, (double)gz);
}
```

#### 3.4 สร้าง Bar Chart (มุมซ้ายบน)

```c
static void create_bar_chart(lv_obj_t * parent)
{
    /* Title */
    lv_obj_t * title = lv_label_create(parent);
    lv_label_set_text(title, "Bar: Accel X/Y/Z");
    lv_obj_set_style_text_font(title, &lv_font_montserrat_14, 0);
    lv_obj_align(title, LV_ALIGN_TOP_LEFT, 10, 5);

    /* Bar Chart */
    bar_chart = lv_chart_create(parent);
    lv_obj_set_size(bar_chart, CHART_W, CHART_H);
    lv_obj_align(bar_chart, LV_ALIGN_TOP_LEFT, 10, 25);
    lv_chart_set_type(bar_chart, LV_CHART_TYPE_BAR);
    lv_chart_set_point_count(bar_chart, 3);  /* X, Y, Z */
    lv_chart_set_range(bar_chart, LV_CHART_AXIS_PRIMARY_Y, 0, 100);

    bar_ser = lv_chart_add_series(bar_chart,
                  lv_palette_main(LV_PALETTE_BLUE),
                  LV_CHART_AXIS_PRIMARY_Y);

    /* เพิ่มระยะห่างระหว่าง bars */
    lv_obj_set_style_pad_column(bar_chart, 30, 0);

    /* Value label */
    bar_value_label = lv_label_create(parent);
    lv_label_set_text(bar_value_label, "X:0 Y:0 Z:0");
    lv_obj_set_style_text_font(bar_value_label, &lv_font_montserrat_12, 0);
    lv_obj_align(bar_value_label, LV_ALIGN_TOP_LEFT, 10, CHART_H + 30);
}
```

#### 3.5 สร้าง Area Chart (มุมขวาบน)

```c
static void create_area_chart(lv_obj_t * parent)
{
    /* Title */
    lv_obj_t * title = lv_label_create(parent);
    lv_label_set_text(title, "Area: Magnitude");
    lv_obj_set_style_text_font(title, &lv_font_montserrat_14, 0);
    lv_obj_align(title, LV_ALIGN_TOP_LEFT, 250, 5);

    /* Area Chart (Line + Fill) */
    area_chart = lv_chart_create(parent);
    lv_obj_set_size(area_chart, CHART_W, CHART_H);
    lv_obj_align(area_chart, LV_ALIGN_TOP_LEFT, 250, 25);
    lv_chart_set_type(area_chart, LV_CHART_TYPE_LINE);
    lv_chart_set_point_count(area_chart, CHART_POINTS);
    lv_chart_set_range(area_chart, LV_CHART_AXIS_PRIMARY_Y, 0, 150);

    area_ser = lv_chart_add_series(area_chart,
                   lv_palette_main(LV_PALETTE_RED),
                   LV_CHART_AXIS_PRIMARY_Y);

    /* Area fill effect */
    lv_obj_set_style_bg_opa(area_chart, LV_OPA_50, LV_PART_ITEMS);
    lv_obj_set_style_size(area_chart, 3, 3, LV_PART_INDICATOR);
    lv_obj_set_style_line_width(area_chart, 2, LV_PART_ITEMS);
    lv_chart_set_div_line_count(area_chart, 4, 6);

    /* Value label */
    area_value_label = lv_label_create(parent);
    lv_label_set_text(area_value_label, "Mag: 0.00 m/s2");
    lv_obj_set_style_text_font(area_value_label, &lv_font_montserrat_12, 0);
    lv_obj_set_style_text_color(area_value_label,
        lv_palette_main(LV_PALETTE_RED), 0);
    lv_obj_align(area_value_label, LV_ALIGN_TOP_LEFT, 250, CHART_H + 30);
}
```

#### 3.6 สร้าง Scatter Chart (มุมซ้ายล่าง)

```c
static void create_scatter_chart(lv_obj_t * parent)
{
    /* Title */
    lv_obj_t * title = lv_label_create(parent);
    lv_label_set_text(title, "Scatter: X vs Y");
    lv_obj_set_style_text_font(title, &lv_font_montserrat_14, 0);
    lv_obj_align(title, LV_ALIGN_TOP_LEFT, 10, 170);

    /* Scatter Chart */
    scatter_chart = lv_chart_create(parent);
    lv_obj_set_size(scatter_chart, CHART_W, CHART_H);
    lv_obj_align(scatter_chart, LV_ALIGN_TOP_LEFT, 10, 190);
    lv_chart_set_type(scatter_chart, LV_CHART_TYPE_SCATTER);
    lv_chart_set_point_count(scatter_chart, SCATTER_POINTS);

    /* IMPORTANT: ต้อง set ทั้ง X range และ Y range */
    lv_chart_set_range(scatter_chart, LV_CHART_AXIS_PRIMARY_X, 0, 200);
    lv_chart_set_range(scatter_chart, LV_CHART_AXIS_PRIMARY_Y, 0, 200);

    scatter_ser = lv_chart_add_series(scatter_chart,
                      lv_palette_main(LV_PALETTE_BLUE),
                      LV_CHART_AXIS_PRIMARY_Y);

    /* จุดใหญ่ ๆ ให้เห็นชัด */
    lv_obj_set_style_size(scatter_chart, 8, 8, LV_PART_INDICATOR);
    lv_obj_set_style_bg_opa(scatter_chart, LV_OPA_70, LV_PART_INDICATOR);
    lv_chart_set_div_line_count(scatter_chart, 4, 4);

    /* Value label */
    scatter_value_label = lv_label_create(parent);
    lv_label_set_text(scatter_value_label, "X:0 Y:0");
    lv_obj_set_style_text_font(scatter_value_label, &lv_font_montserrat_12, 0);
    lv_obj_align(scatter_value_label, LV_ALIGN_TOP_LEFT, 10, CHART_H + 195);
}
```

#### 3.7 สร้าง Line Chart (มุมขวาล่าง)

```c
static void create_line_chart(lv_obj_t * parent)
{
    /* Title */
    lv_obj_t * title = lv_label_create(parent);
    lv_label_set_text(title, "Line: Gyro R/P/Y");
    lv_obj_set_style_text_font(title, &lv_font_montserrat_14, 0);
    lv_obj_align(title, LV_ALIGN_TOP_LEFT, 250, 170);

    /* Line Chart */
    line_chart = lv_chart_create(parent);
    lv_obj_set_size(line_chart, CHART_W, CHART_H);
    lv_obj_align(line_chart, LV_ALIGN_TOP_LEFT, 250, 190);
    lv_chart_set_type(line_chart, LV_CHART_TYPE_LINE);
    lv_chart_set_point_count(line_chart, CHART_POINTS);
    lv_chart_set_range(line_chart, LV_CHART_AXIS_PRIMARY_Y, 0, 100);

    /* ซ่อนจุด แสดงแค่เส้น */
    lv_obj_set_style_size(line_chart, 0, 0, LV_PART_INDICATOR);
    lv_obj_set_style_line_width(line_chart, 2, LV_PART_ITEMS);
    lv_chart_set_div_line_count(line_chart, 4, 4);

    /* 3 series: Roll(Red), Pitch(Green), Yaw(Blue) */
    lv_color_t colors[] = {
        lv_palette_main(LV_PALETTE_RED),
        lv_palette_main(LV_PALETTE_GREEN),
        lv_palette_main(LV_PALETTE_BLUE)
    };
    for(int i = 0; i < 3; i++) {
        line_ser[i] = lv_chart_add_series(line_chart, colors[i],
                                           LV_CHART_AXIS_PRIMARY_Y);
    }

    /* Value label */
    line_value_label = lv_label_create(parent);
    lv_label_set_text(line_value_label, "R:0 P:0 Y:0");
    lv_obj_set_style_text_font(line_value_label, &lv_font_montserrat_12, 0);
    lv_obj_align(line_value_label, LV_ALIGN_TOP_LEFT, 250, CHART_H + 195);
}
```

#### 3.8 Main Function

```c
void part2_ex6_chart_dashboard(void)
{
    /* พื้นหลังสีเทาอ่อน */
    lv_obj_set_style_bg_color(lv_screen_active(),
        lv_color_hex(0xF0F0F0), LV_PART_MAIN);

    /* สร้าง 4 charts ใน grid 2x2 */
    lv_obj_t * screen = lv_screen_active();
    create_bar_chart(screen);
    create_area_chart(screen);
    create_scatter_chart(screen);
    create_line_chart(screen);

    /* Single timer สำหรับอัพเดททุก chart */
    chart_timer = lv_timer_create(chart_timer_cb, 100, NULL);
}
```

***

### 4. องค์ความรู้และเทคนิค

#### 4.1 เลือก Chart Type ที่เหมาะสม

<table><thead><tr><th width="310.5198974609375">ลักษณะข้อมูล</th><th width="174.3245849609375">Chart Type ที่เหมาะ</th><th>เหตุผล</th></tr></thead><tbody><tr><td>เปรียบเทียบค่าหลาย ๆ ตัว ณ เวลาเดียว</td><td><strong>Bar</strong></td><td>เห็นความแตกต่างชัดเจน</td></tr><tr><td>ข้อมูลเปลี่ยนแปลงตามเวลา</td><td><strong>Line</strong></td><td>เห็น trend ชัด</td></tr><tr><td>ข้อมูลเปลี่ยนแปลงตามเวลา + ปริมาณ</td><td><strong>Area</strong> (Line+Fill)</td><td>เห็นทั้ง trend และ volume</td></tr><tr><td>ความสัมพันธ์ระหว่าง 2 ตัวแปร</td><td><strong>Scatter</strong></td><td>เห็น correlation pattern</td></tr><tr><td>สัดส่วน/เปอร์เซ็นต์</td><td><strong>Arc/Bar</strong></td><td>เห็นสัดส่วนชัด</td></tr></tbody></table>

#### 4.2 Bar Chart Gotchas

```c
/* BAR Chart: 3 ข้อควรจำ */

/* 1. point_count = จำนวน bars (ไม่ใช่ data points) */
lv_chart_set_point_count(chart, 3);  /* 3 bars: X, Y, Z */

/* 2. ใช้ set_value_by_id (ไม่ใช่ set_next_value) */
lv_chart_set_value_by_id(chart, ser, 0, val_x);  /* bar index 0 */
lv_chart_set_value_by_id(chart, ser, 1, val_y);  /* bar index 1 */

/* 3. MUST call refresh หลังอัพเดท */
lv_chart_refresh(chart);
```

#### 4.3 Scatter Chart Gotchas

```c
/* SCATTER Chart: 2 ข้อควรจำ */

/* 1. ต้อง set ทั้ง X range และ Y range */
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_X, 0, 200);
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, 200);

/* 2. ใช้ set_next_value2 (ส่งทั้ง x และ y) */
lv_chart_set_next_value2(chart, ser, x_val, y_val);
```

#### 4.4 Data Scaling Pattern

```c
/* Pattern: แปลงค่า float range เป็น int range สำหรับ chart */

/* Accel: -2.0..+2.0 -> 0..100 */
int32_t scaled = (int32_t)((value + 2.0f) * 25.0f);
scaled = LV_CLAMP(0, scaled, 100);

/* Gyro: -1.0..+1.0 -> 0..100 */
int32_t scaled = (int32_t)((value + 1.0f) * 50.0f);

/* General formula: */
/* scaled = (value - src_min) / (src_max - src_min) * (dst_max - dst_min) + dst_min */
```

#### 4.5 Grid Layout Tips

```c
/* คำนวณ layout สำหรับ 2x2 grid บนหน้าจอ 480x320 */
#define SCREEN_W    480
#define SCREEN_H    320
#define MARGIN      10
#define CHART_W     ((SCREEN_W - 3 * MARGIN) / 2)   /* ~220 */
#define CHART_H     ((SCREEN_H - 3 * MARGIN - 40) / 2)  /* ~110 (reserve 40 for labels) */

/* ตำแหน่ง: */
/* Top-Left:     (MARGIN, 25) */
/* Top-Right:    (MARGIN + CHART_W + MARGIN, 25) */
/* Bottom-Left:  (MARGIN, 25 + CHART_H + 40) */
/* Bottom-Right: (MARGIN + CHART_W + MARGIN, 25 + CHART_H + 40) */
```

***

### 5. แบบฝึกหัด

#### Exercise 1: Weather Dashboard

**โจทย์:** สร้าง Weather Dashboard แบบ 2x2 grid แสดง 4 charts:

| ตำแหน่ง  | Chart Type | ข้อมูล           | Range       |
| -------- | ---------- | ---------------- | ----------- |
| ซ้ายบน   | Line       | Temperature (C)  | 20-40       |
| ขวาบน    | Area       | Humidity (%)     | 40-100      |
| ซ้ายล่าง | Bar        | Pressure (hPa)   | 990-1030    |
| ขวาล่าง  | Scatter    | Temp vs Humidity | correlation |

* จำลองข้อมูลให้สมจริง (อุณหภูมิสัมพันธ์กับความชื้น)
* แต่ละ chart มี title และ value label
* อัพเดททุก 200ms

**การประยุกต์ใช้งานจริง:**

* สถานีตรวจอากาศ (Weather Station)
* ระบบ HVAC ในอาคาร
* Smart Agriculture - ตรวจสอบสภาพอากาศในฟาร์ม

***

#### Exercise 2: Chart Type Selector

**โจทย์:** เพิ่ม Dropdown ที่ด้านบนของหน้าจอ ให้ผู้ใช้เลือกประเภท Chart สำหรับ Accelerometer data:

* ตัวเลือก: "Line\nBar\nScatter"
* เมื่อเปลี่ยน dropdown จะทำลาย chart เก่าและสร้างใหม่ตาม type ที่เลือก
* ข้อมูลที่แสดงเหมือนกัน (Accel X/Y/Z) แต่เปลี่ยนวิธีแสดงผล

**การประยุกต์ใช้งานจริง:**

* Data Analytics Dashboard ที่ให้ผู้ใช้เลือกมุมมองข้อมูล
* Lab Equipment Software ที่วิศวกรต้องวิเคราะห์ข้อมูลหลายมุมมอง

**Hint:**

* `lv_dropdown_create(parent)` สร้าง dropdown
* `lv_dropdown_set_options(dd, "Line\nBar\nScatter")`
* Event callback: `lv_dropdown_get_selected(dd)` return 0, 1, 2
* ลบ chart เก่า: `lv_obj_delete(old_chart)`

***

### 6. References

* [LVGL Chart](https://docs.lvgl.io/9.2/widgets/chart.html)
* [lv\_example\_chart\_1.c](https://github.com/lvgl/lvgl/blob/release/v9.2/examples/widgets/chart/lv_example_chart_1.c)
* [LVGL TabView](https://docs.lvgl.io/9.2/widgets/tabview.html)

***
