1+ /* *
2+ **************************************************
3+ *
4+ * @file Qwiic.ino
5+ * @brief Example demonstrating easyC/Qwiic (I2C) communication between Inkplate 6FLICK and
6+ * a Soldered BME280 or BME680 environmental sensor, using the LVGL library
7+ * for display rendering.
8+ *
9+ * This example reads temperature, humidity, and pressure data from a
10+ * Soldered BME280 sensor connected via the easyC interface and displays
11+ * it on the Inkplate 6FLICK e-paper screen using LVGL elements.
12+ *
13+ * Note: Both BME280 and BME680 sensors are supported by the same
14+ * Soldered BME280/BME680 library. In this example, the BME280 is used,
15+ * as defined in the code. The sensor communicates over easyC (I2C)
16+ * using the default 0x76 address.
17+ *
18+ * For setup instructions and more information about Inkplate 6FLICK, visit:
19+ * https://soldered.com/documentation/inkplate/6flick/overview/
20+ *
21+ * @hardware Inkplate 6FLICK (ESP32-based e-paper display)
22+ * @sensors Soldered BME280 (or BME680) via easyC connector
23+ * @library Soldered BME280/BME680 Gas Sensor Arduino Library
24+ * https://github.com/SolderedElectronics/Soldered-BME280-BME680-Gas-Sensor-Arduino-Library
25+ *
26+ * @authors Soldered
27+ * @date November 2025
28+ ***************************************************/
29+
30+ #include < Inkplate-LVGL.h>
31+ #include < BME280-SOLDERED.h> // Soldered BME280/BME680 library (easyC/I2C)
32+
33+ // Inkplate in 1-bit mode (fast partial updates)
34+ Inkplate inkplate (INKPLATE_1BIT);
35+ BME280 bme280; // easyC/I2C (Soldered uses 0x76)
36+
37+ // Optional temperature calibration offset
38+ const float TEMPERATURE_OFFSET = 0 .0f ;
39+
40+ // UI elements
41+ static lv_obj_t *panel_data;
42+ static lv_obj_t *lbl_title;
43+ static lv_obj_t *lbl_temp;
44+ static lv_obj_t *lbl_hum;
45+ static lv_obj_t *lbl_press;
46+ static lv_obj_t *lbl_warn;
47+
48+ // Refresh policy (do a FULL every ~20 partials)
49+ static int partialCount = 0 ;
50+ static const int FULL_REFRESH_EVERY = 20 ;
51+
52+ // Helpers
53+ static inline int dispW () { auto *d = lv_display_get_default (); return lv_display_get_horizontal_resolution (d); }
54+ static inline int dispH () { auto *d = lv_display_get_default (); return lv_display_get_vertical_resolution (d); }
55+
56+ static void make_opaque (lv_obj_t *obj) {
57+ lv_obj_set_style_bg_color (obj, lv_color_hex (0xFFFFFF ), 0 );
58+ lv_obj_set_style_bg_opa (obj, LV_OPA_COVER, 0 );
59+ lv_obj_set_style_border_width (obj, 0 , 0 );
60+ }
61+
62+ // Minimal LVGL UI (no GFX icons to keep it LVGL-only)
63+ static void ui_create () {
64+ lv_obj_set_style_bg_color (lv_screen_active (), lv_color_hex (0xFFFFFF ), LV_PART_MAIN);
65+
66+ lbl_title = lv_label_create (lv_screen_active ());
67+ lv_label_set_text (lbl_title, " easyC • BME280" );
68+ lv_obj_set_style_text_color (lbl_title, lv_color_hex (0x000000 ), 0 );
69+ lv_obj_set_pos (lbl_title, 8 , 8 );
70+ make_opaque (lbl_title);
71+
72+ panel_data = lv_obj_create (lv_screen_active ());
73+ make_opaque (panel_data);
74+ lv_obj_set_style_pad_all (panel_data, 0 , 0 );
75+ lv_obj_set_style_border_width (panel_data, 0 , 0 );
76+ lv_obj_set_pos (panel_data, 0 , 40 );
77+ lv_obj_set_size (panel_data, dispW (), dispH () - 80 );
78+
79+ lbl_temp = lv_label_create (panel_data);
80+ lv_obj_set_style_text_color (lbl_temp, lv_color_hex (0x000000 ), 0 );
81+ lv_obj_set_pos (lbl_temp, 24 , 40 );
82+
83+ lbl_hum = lv_label_create (panel_data);
84+ lv_obj_set_style_text_color (lbl_hum, lv_color_hex (0x000000 ), 0 );
85+ lv_obj_set_pos (lbl_hum, 24 , 140 );
86+
87+ lbl_press = lv_label_create (panel_data);
88+ lv_obj_set_style_text_color (lbl_press, lv_color_hex (0x000000 ), 0 );
89+ lv_obj_set_pos (lbl_press, 24 , 240 );
90+
91+ lbl_warn = lv_label_create (panel_data); // shown only if sensor looks unresponsive
92+ lv_obj_set_style_text_color (lbl_warn, lv_color_hex (0x000000 ), 0 );
93+ lv_obj_set_pos (lbl_warn, 24 , 320 );
94+ lv_label_set_text (lbl_warn, " " );
95+ }
96+
97+ static void update_readings () {
98+ // Read sensor
99+ float tC = bme280.readTemperature () + TEMPERATURE_OFFSET; // °C
100+ float hum = bme280.readHumidity () / 10 .0f ; // library returns x10
101+ float hPa = bme280.readPressure () * 10 .0f ; // hPa (original style)
102+
103+ // Basic sanity check (some libs return 0 or extreme values if not connected)
104+ bool looks_bad = (hPa <= 0 .0f ) || (hum < 0 .0f || hum > 100 .0f ) || (tC < -40 .0f || tC > 85 .0f );
105+
106+ char bufT[32 ], bufH[32 ], bufP[32 ];
107+ snprintf (bufT, sizeof (bufT), " Temperature: %.1f *C" , tC);
108+ snprintf (bufH, sizeof (bufH), " Humidity: %.0f %%" , hum);
109+ snprintf (bufP, sizeof (bufP), " Pressure: %.0f hPa" , hPa);
110+
111+ lv_label_set_text (lbl_temp, bufT);
112+ lv_label_set_text (lbl_hum, bufH);
113+ lv_label_set_text (lbl_press, bufP);
114+
115+ if (looks_bad) {
116+ lv_label_set_text (lbl_warn, " Warning: sensor readings look invalid.\n Check easyC cable and sensor power." );
117+ } else {
118+ lv_label_set_text (lbl_warn, " " );
119+ }
120+ }
121+
122+ void setup () {
123+ Serial.begin (115200 );
124+
125+ // LVGL + Inkplate in PARTIAL mode
126+ inkplate.begin (LV_DISP_RENDER_MODE_PARTIAL);
127+ inkplate.selectDisplayMode (INKPLATE_1BIT);
128+
129+ // Init BME280 (void return in this library)
130+ bme280.begin ();
131+
132+ ui_create ();
133+ update_readings ();
134+
135+ // Initial FULL refresh
136+ lv_tick_inc (20 );
137+ lv_timer_handler ();
138+ inkplate.display ();
139+ }
140+
141+ void loop () {
142+ update_readings ();
143+
144+ lv_tick_inc (10 );
145+ lv_timer_handler ();
146+
147+ if (partialCount >= FULL_REFRESH_EVERY) {
148+ inkplate.display (); // FULL
149+ partialCount = 0 ;
150+ } else {
151+ inkplate.partialUpdate ();
152+ partialCount++;
153+ }
154+
155+ delay (10000 ); // ~10 s between readings
156+ }
0 commit comments