Documentation / Hardware

Charts

Series, two Y axes, scatter with a real X, and a window that is an hour rather than a count.

A chart is the widget with the most moving parts, so it has its own page. It holds one or more series; each series is fed by a Push onto chart binding from a variable, and the chart decides what the axes mean and how many readings it keeps.

Chart settings and the series editor for a two-series chart with a secondary axis: the humidity series is measured against the right-hand axis.
Chart settings and the series editor for a two-series chart with a secondary axis: the humidity series is measured against the right-hand axis.

Series

Under Chart data in the Inspector, each series has a name, a colour, a list of design-time values (what the canvas draws, and the initial points on the device), and - once a secondary axis exists - which axis it is measured against. A scatter chart's series also has a list of design-time X values. Add as many series as you have things to plot; the feed for each is a binding.

Feeding it

Select the chart, add a Data binding, choose the variable, set Drives to Push onto chart and pick the Series. Every refresh in which the variable is due, its value is appended with lv_chart_set_next_value(). A temperature line and a humidity line are two bindings on one chart pointed at two series.

Two Y axes

Switch on Secondary Y axis and the chart gains a right-hand axis with its own range (Secondary Y range min / max), and each series gains the Measured against choice. That is what lets 0-50 °C sit beside 400-2000 ppm CO2 without one of them drawing as a flat line along the bottom. The canvas draws the second axis's labels on the right. The validator warns when a series is measured against a secondary axis the chart does not have.

Scatter and the X axis

A Scatter chart plots each point at an X as well as a Y. The X range is set on the chart (X range min / max), and X from names the variable every point takes its X from - one setting for the whole chart, because a chart has one X axis. Left empty, each reading keeps the X it already had and the series stacks on one column, which the validator warns about.

A time axis

Point X from at a variable reading a real-time clock - the DS3231's Unix time channel - and the scatter chart becomes a time axis. Two details make that work on a microcontroller:

The rolling window

Rolling window is either The last N points - N is the chart's point count, and When full decides whether new points shift the old ones left or overwrite them circularly - or A span of time in seconds. With a time span, the firmware paces the pushes so the point count covers the span: an hour across 120 points is one reading every 30 seconds, whatever the refresh rate. The Inspector shows the resulting cadence under the setting, and the validator warns if it is faster than the refresh loop can deliver. On a scatter chart with a time axis the X range also rolls, so the last hour is always what is on screen.

Ticks and labels

Major and minor tick lengths and counts, whether the X and primary Y axes are labelled, and the axis font size. On LVGL 8 these become lv_chart_set_axis_tick() calls, including a set for the secondary axis when there is one; LVGL 9 removed that API in favour of the scale widget, so on 9 the ticks are a canvas hint only.

Generated code, briefly

The screen file creates the chart, sets its type, point count, division lines, ranges (primary, secondary and X where used), update mode and ticks, then adds each series on its axis and fills in the design-time values. app_logic.cpp holds a per-chart pacing timer and, for a scatter chart, the X origin; each push is one lv_chart_set_next_value() or, with an X source, lv_chart_set_next_value2(), followed by lv_chart_set_range() on the X axis when the window is a time span.