Chart Dashboard

Lab 11: Real Chart Dashboard

Part 2 - Sensor Visualization

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

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

  • Multi-Chart Visualization: ในระบบ monitoring จริง ข้อมูล sensor เดียวกันแสดงได้หลายรูปแบบ ต้องเลือก chart type ที่เหมาะกับลักษณะข้อมูล

  • Active Tab Optimization: เมื่อมี chart หลายตัว การอัพเดทเฉพาะ chart ที่มองเห็นช่วยลด CPU load อย่างมาก (ลดได้ 75%)

  • Custom Draw Events: เทคนิค faded area chart ใช้ draw callback ซึ่งเป็นความสามารถขั้นสูงของ LVGL ที่ใช้ในระบบ production จริง

  • Tilt Analysis: รวม Complementary Filter (Accel + Gyro fusion) เพื่อคำนวณ Roll/Pitch angle ที่แม่นยำ

  • Professional Dashboard: รูปแบบ multi-chart dashboard ที่ใช้ใน SCADA, Process Control, และ Industrial IoT

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

  1. Bar Chart (Real Data): เปรียบเทียบ Accel X/Y/Z แบบ side-by-side ด้วย LV_CHART_TYPE_BAR + colored series

  2. Area Chart (Faded): แสดง Tilt Magnitude พร้อม gradient fill ด้วย custom draw callback (LV_EVENT_DRAW_TASK_ADDED)

  3. Scatter Chart (2D Mapping): แสดง Roll vs Pitch เป็น "Tilt Ball" ด้วย LV_CHART_TYPE_SCATTER + lv_chart_set_next_value2()

  4. Line Chart (Multi-Series): แสดง Gyroscope Roll/Pitch/Yaw เป็น time-series

  5. TabView LEFT Layout: จัดวาง 4 charts ใน tabs ด้านซ้าย (vertical tab bar 80px)

  6. Active Tab Optimization: อัพเดทเฉพาะ tab ที่มองเห็นด้วย lv_tabview_get_tab_active()

  7. Tilt Integration: ใช้ aic_tilt_init() + aic_tilt_update_from_imu() สำหรับ Area และ Scatter tabs

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

  1. เรียก aic_sensors_init() + aic_tilt_init(NULL) ก่อนสร้าง UI

  2. สร้าง TabView แบบ LEFT tab bar (80px) พร้อม 4 tabs: Bar, Area, Scatter, Line

  3. แต่ละ tab สร้าง chart ด้วยฟังก์ชันแยก (ex11_create_xxx_tab())

  4. Timer callback (100ms) อ่าน IMU + Gyro + Tilt แล้วอัพเดทเฉพาะ active tab

  5. Tab Area ใช้ custom draw callback สำหรับ faded gradient effect


2. หลักการทำงานและ Flowchart

2.1 Dashboard Architecture

2.2 Tab Layout (Side Tabs)

2.3 Chart Data Sources


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

3.1 Sensor & Tilt APIs

Function
Return
Description

aic_sensors_init()

void

Initialize sensor subsystem (เรียกครั้งเดียว)

aic_tilt_init(NULL)

void

Initialize Complementary Filter สำหรับ Tilt

aic_imu_read_accel(&ax, &ay, &az)

bool

อ่าน accelerometer (m/s2)

aic_imu_read_gyro(&gx, &gy, &gz)

bool

อ่าน gyroscope (rad/s)

aic_tilt_update_from_imu()

bool

อัพเดท tilt estimation (accel + gyro fusion)

aic_tilt_get_roll()

float

อ่าน roll angle (degrees)

aic_tilt_get_pitch()

float

อ่าน pitch angle (degrees)

3.2 Chart Type APIs

Chart Type
Create
Update
Description

BAR

lv_chart_set_type(chart, LV_CHART_TYPE_BAR)

lv_chart_set_value_by_id(chart, ser, id, val)

แท่งเปรียบเทียบค่า

LINE

lv_chart_set_type(chart, LV_CHART_TYPE_LINE)

lv_chart_set_next_value(chart, ser, val)

เส้น time-series

SCATTER

lv_chart_set_type(chart, LV_CHART_TYPE_SCATTER)

lv_chart_set_next_value2(chart, ser, x, y)

จุด X-Y correlation

3.3 TabView APIs

Function
Description

lv_tabview_create(parent)

สร้าง TabView

lv_tabview_set_tab_bar_position(tv, LV_DIR_LEFT)

Tab bar ด้านซ้าย

lv_tabview_set_tab_bar_size(tv, 80)

ความกว้าง tab bar 80px

lv_tabview_add_tab(tv, "name")

เพิ่ม tab ใหม่

lv_tabview_get_tab_active(tv)

อ่าน active tab index (0, 1, 2, 3)

lv_tabview_get_tab_bar(tv)

อ่าน tab button bar object

lv_tabview_get_content(tv)

อ่าน content container

3.4 Draw Callback APIs (สำหรับ Faded Area)

Function
Description

lv_obj_add_event_cb(obj, cb, LV_EVENT_DRAW_TASK_ADDED, NULL)

Register draw callback

lv_obj_add_flag(obj, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS)

Enable draw task events

lv_event_get_draw_task(e)

อ่าน draw task จาก event

lv_draw_task_get_draw_dsc(task)

อ่าน draw descriptor

lv_draw_task_get_type(task)

อ่าน draw type (LINE, RECT, etc.)

lv_draw_triangle(layer, &dsc)

วาดสามเหลี่ยม (gradient fill)

lv_draw_rect(layer, &dsc, &area)

วาดสี่เหลี่ยม (fade to transparent)

3.5 Include Files


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

4.1 Global Variables & Defines

4.2 Simulation Helpers (PC Simulator)

4.3 Timer Callback - Active Tab Optimization

นี่คือหัวใจสำคัญของ Lab นี้ -- timer callback ที่อ่านข้อมูลจากทุก sensor แต่อัพเดทเฉพาะ chart ของ tab ที่กำลังแสดงผลอยู่:

4.4 Tab 1: Bar Chart - Real Accel X/Y/Z

4.5 Faded Area Draw Callback

นี่คือ draw callback ที่สร้าง gradient fill ใต้เส้น chart ซึ่งอ้างอิงจาก lv_example_chart_5 ของ LVGL:

4.6 Tab 2: Area Chart - Tilt Magnitude

4.7 Tab 3: Scatter Chart - Roll vs Pitch (Tilt Ball)

4.8 Tab 4: Line Chart - Gyroscope R/P/Y

4.9 Main Function - Assembling the Dashboard


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

5.1 Active Tab Optimization - ทำไมต้องอัพเดทเฉพาะ Tab ที่มองเห็น

5.2 Area Chart - Custom Draw Callback อธิบาย

5.3 Scatter Chart - 2D Mapping Pattern

5.4 Data Scaling Patterns

5.5 Bar Chart: set_value_by_id vs set_next_value

5.6 Tilt Analysis: Complementary Filter


6. แบบฝึกหัด

Exercise 1: FFT Frequency Display Tab

โจทย์: เพิ่ม Tab ที่ 5 "FFT" แสดง Frequency Spectrum ของ accelerometer Z-axis:

Requirements:

  • เก็บข้อมูล Z-axis 64 samples ล่าสุด (circular buffer)

  • คำนวณ Simple DFT (Discrete Fourier Transform) ขนาด 64 จุด

  • แสดงเป็น Bar chart: แกน X = frequency bin (0-32), แกน Y = magnitude

  • อัพเดทผลลัพธ์ทุก 64 samples ใหม่ (ไม่ใช่ทุก sample)

  • แสดง dominant frequency (ความถี่ที่มี magnitude สูงสุด)

Layout:

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

  • Vibration Analysis: ตรวจจับ resonance frequency ของเครื่องจักร

  • Predictive Maintenance: ตรวจสอบ bearing wear จาก vibration spectrum

  • Structural Health Monitoring: ตรวจสอบ natural frequency ของสะพาน/อาคาร

Hint:

  • DFT bin k: mag[k] = sqrt(real[k]^2 + imag[k]^2) where real[k] = sum(x[n] * cos(2*PI*k*n/N)) and imag[k] = sum(x[n] * sin(2*PI*k*n/N))

  • Frequency resolution: f_res = sample_rate / N = 10Hz / 64 = 0.156 Hz/bin

  • ใช้ lv_chart_set_point_count(chart, 32) (แสดงเฉพาะครึ่งแรกของ DFT)

  • lv_chart_set_value_by_id() สำหรับอัพเดทแต่ละ bar


Exercise 2: Recording and Playback

โจทย์: เพิ่มปุ่ม Record/Playback สำหรับบันทึกข้อมูล sensor แล้วเล่นซ้ำ:

Requirements:

  • ปุ่ม "REC" สีแดง: เริ่มบันทึกข้อมูล (accel + gyro + tilt) สูงสุด 500 samples

  • ปุ่ม "STOP" สีเทา: หยุดบันทึก

  • ปุ่ม "PLAY" สีเขียว: เล่นข้อมูลที่บันทึกไว้กลับใน chart

  • แสดง recording status: "Recording... 123/500" หรือ "Playing... 45/123"

  • เมื่อ playback, timer อ่านจาก buffer แทน sensor จริง

Layout:

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

  • Flight Data Recorder: บันทึกข้อมูลการบินสำหรับวิเคราะห์ภายหลัง

  • Sports Analytics: บันทึก motion ของนักกีฬาแล้วเล่นซ้ำเพื่อวิเคราะห์ท่าทาง

  • Quality Control: บันทึก vibration pattern สำหรับเปรียบเทียบกับ reference

Hint:

  • ใช้ struct สำหรับ sample: typedef struct { float ax, ay, az, gx, gy, gz, roll, pitch; } sensor_sample_t;

  • Static array: static sensor_sample_t recording[500];

  • State machine: IDLE -> RECORDING -> STOPPED -> PLAYING -> IDLE

  • Playback timer: ใช้ timer เดิม แต่เปลี่ยน data source


7. References


Last updated

Was this helpful?