1+ /* *
2+ **************************************************
3+ *
4+ * @file Qwiic.ino
5+ * @brief Example demonstrating easyC (I2C) communication between Inkplate 6 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 6 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 6, visit:
19+ * https://soldered.com/documentation/inkplate/6/overview/
20+ *
21+ * @hardware Inkplate 6COLOR (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+
31+
32+ #include < Inkplate-LVGL.h>
33+ #include < BME280-SOLDERED.h> // Soldered BME280/BME680 library (easyC/I2C)
34+
35+ // Inkplate in 1-bit mode (fast partial updates)
36+ Inkplate inkplate (INKPLATE_1BIT);
37+ BME680 bme680; // easyC/I2C (Soldered uses 0x76)
38+
39+ // Optional temperature calibration offset
40+ const float TEMPERATURE_OFFSET = 0 .0f ;
41+
42+ // UI elements
43+ static lv_obj_t *panel_data;
44+ static lv_obj_t *lbl_title;
45+ static lv_obj_t *lbl_temp;
46+ static lv_obj_t *lbl_hum;
47+ static lv_obj_t *lbl_press;
48+ static lv_obj_t *lbl_warn;
49+
50+ // Refresh policy (do a FULL every ~20 partials)
51+ static int partialCount = 0 ;
52+ static const int FULL_REFRESH_EVERY = 20 ;
53+
54+ // Helpers
55+ static inline int dispW () { auto *d = lv_display_get_default (); return lv_display_get_horizontal_resolution (d); }
56+ static inline int dispH () { auto *d = lv_display_get_default (); return lv_display_get_vertical_resolution (d); }
57+
58+ static void make_opaque (lv_obj_t *obj) {
59+ lv_obj_set_style_bg_color (obj, lv_color_hex (0xFFFFFF ), 0 );
60+ lv_obj_set_style_bg_opa (obj, LV_OPA_COVER, 0 );
61+ lv_obj_set_style_border_width (obj, 0 , 0 );
62+ }
63+
64+ // Minimal LVGL UI (no GFX icons to keep it LVGL-only)
65+ static void ui_create () {
66+ lv_obj_set_style_bg_color (lv_screen_active (), lv_color_hex (0xFFFFFF ), LV_PART_MAIN);
67+
68+ lbl_title = lv_label_create (lv_screen_active ());
69+ lv_label_set_text (lbl_title, " Qwiic • BME280" );
70+ lv_obj_set_style_text_color (lbl_title, lv_color_hex (0x000000 ), 0 );
71+ lv_obj_set_pos (lbl_title, 8 , 8 );
72+ make_opaque (lbl_title);
73+
74+ panel_data = lv_obj_create (lv_screen_active ());
75+ make_opaque (panel_data);
76+ lv_obj_set_style_pad_all (panel_data, 0 , 0 );
77+ lv_obj_set_style_border_width (panel_data, 0 , 0 );
78+ lv_obj_set_pos (panel_data, 0 , 40 );
79+ lv_obj_set_size (panel_data, dispW (), dispH () - 80 );
80+
81+ lbl_temp = lv_label_create (panel_data);
82+ lv_obj_set_style_text_color (lbl_temp, lv_color_hex (0x000000 ), 0 );
83+ lv_obj_set_pos (lbl_temp, 24 , 40 );
84+
85+ lbl_hum = lv_label_create (panel_data);
86+ lv_obj_set_style_text_color (lbl_hum, lv_color_hex (0x000000 ), 0 );
87+ lv_obj_set_pos (lbl_hum, 24 , 140 );
88+
89+ lbl_press = lv_label_create (panel_data);
90+ lv_obj_set_style_text_color (lbl_press, lv_color_hex (0x000000 ), 0 );
91+ lv_obj_set_pos (lbl_press, 24 , 240 );
92+
93+ lbl_warn = lv_label_create (panel_data); // shown only if sensor looks unresponsive
94+ lv_obj_set_style_text_color (lbl_warn, lv_color_hex (0x000000 ), 0 );
95+ lv_obj_set_pos (lbl_warn, 24 , 320 );
96+ lv_label_set_text (lbl_warn, " " );
97+ }
98+
99+ static void update_readings () {
100+ // Read sensor
101+ float tC = bme280.readTemperature () + TEMPERATURE_OFFSET; // °C
102+ float hum = bme280.readHumidity () / 10 .0f ; // library returns x10
103+ float hPa = bme280.readPressure () * 10 .0f ; // hPa (original style)
104+
105+ // Basic sanity check (some libs return 0 or extreme values if not connected)
106+ bool looks_bad = (hPa <= 0 .0f ) || (hum < 0 .0f || hum > 100 .0f ) || (tC < -40 .0f || tC > 85 .0f );
107+
108+ char bufT[32 ], bufH[32 ], bufP[32 ];
109+ snprintf (bufT, sizeof (bufT), " Temperature: %.1f *C" , tC);
110+ snprintf (bufH, sizeof (bufH), " Humidity: %.0f %%" , hum);
111+ snprintf (bufP, sizeof (bufP), " Pressure: %.0f hPa" , hPa);
112+
113+ lv_label_set_text (lbl_temp, bufT);
114+ lv_label_set_text (lbl_hum, bufH);
115+ lv_label_set_text (lbl_press, bufP);
116+
117+ if (looks_bad) {
118+ lv_label_set_text (lbl_warn, " Warning: sensor readings look invalid.\n Check Qwiic cable and sensor power." );
119+ } else {
120+ lv_label_set_text (lbl_warn, " " );
121+ }
122+ }
123+
124+ void setup () {
125+ Serial.begin (115200 );
126+
127+ // LVGL + Inkplate in PARTIAL mode
128+ inkplate.begin (LV_DISP_RENDER_MODE_PARTIAL);
129+
130+ // Init BME280 (void return in this library)
131+ bme280.begin ();
132+
133+ ui_create ();
134+ update_readings ();
135+
136+ // Initial FULL refresh
137+ lv_tick_inc (20 );
138+ lv_timer_handler ();
139+ inkplate.display ();
140+ }
141+
142+ void loop () {
143+ update_readings ();
144+
145+ lv_tick_inc (10 );
146+ lv_timer_handler ();
147+ inkplate.display (); // FULL
148+
149+
150+ delay (60000 ); // ~60 s between readings
151+ }
0 commit comments