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? - จะได้เรียนรู้อะไร
Bar Chart (Real Data): เปรียบเทียบ Accel X/Y/Z แบบ side-by-side ด้วย
LV_CHART_TYPE_BAR+ colored seriesArea Chart (Faded): แสดง Tilt Magnitude พร้อม gradient fill ด้วย custom draw callback (
LV_EVENT_DRAW_TASK_ADDED)Scatter Chart (2D Mapping): แสดง Roll vs Pitch เป็น "Tilt Ball" ด้วย
LV_CHART_TYPE_SCATTER+lv_chart_set_next_value2()Line Chart (Multi-Series): แสดง Gyroscope Roll/Pitch/Yaw เป็น time-series
TabView LEFT Layout: จัดวาง 4 charts ใน tabs ด้านซ้าย (vertical tab bar 80px)
Active Tab Optimization: อัพเดทเฉพาะ tab ที่มองเห็นด้วย
lv_tabview_get_tab_active()Tilt Integration: ใช้
aic_tilt_init()+aic_tilt_update_from_imu()สำหรับ Area และ Scatter tabs
How? - จะทำอย่างไร
เรียก
aic_sensors_init()+aic_tilt_init(NULL)ก่อนสร้าง UIสร้าง TabView แบบ LEFT tab bar (80px) พร้อม 4 tabs: Bar, Area, Scatter, Line
แต่ละ tab สร้าง chart ด้วยฟังก์ชันแยก (
ex11_create_xxx_tab())Timer callback (100ms) อ่าน IMU + Gyro + Tilt แล้วอัพเดทเฉพาะ active tab
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
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
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
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)
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)wherereal[k] = sum(x[n] * cos(2*PI*k*n/N))andimag[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 -> IDLEPlayback timer: ใช้ timer เดิม แต่เปลี่ยน data source
7. References
lv_example_chart_5 (Area effect)
Last updated
Was this helpful?