Skip to content

Commit 591440a

Browse files
authored
Merge pull request #2 from ladyada-piclaw/main
Add TFT bar graph demo for Feather ESP32-S2 TFT
2 parents 77c26a8 + 7b87c28 commit 591440a

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed

examples/AS7331_TFT_demo/.none.test.only

Whitespace-only changes.
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
/*!
2+
* @file AS7331_TFT_demo.ino
3+
*
4+
* TFT demo for AS7331 UV Spectral Sensor on Feather ESP32-S2 TFT
5+
* Displays UVA, UVB, UVC readings as bar graphs with temperature
6+
*
7+
* Hardware:
8+
* - Adafruit Feather ESP32-S2 TFT
9+
* - AS7331 UV Sensor breakout (I2C)
10+
*
11+
* Written by Limor Fried/Ladyada for Adafruit Industries.
12+
* BSD license, all text above must be included in any redistribution
13+
*/
14+
15+
#include <Adafruit_AS7331.h>
16+
#include <Adafruit_GFX.h>
17+
#include <Adafruit_ST7789.h>
18+
#include <Fonts/FreeSansBold9pt7b.h>
19+
#include <Fonts/FreeSans9pt7b.h>
20+
#include <Wire.h>
21+
22+
// Feather ESP32-S2 TFT built-in display
23+
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
24+
25+
// AS7331 UV sensor
26+
Adafruit_AS7331 as7331;
27+
28+
// Display layout constants (240x135 landscape)
29+
#define SCREEN_WIDTH 240
30+
#define SCREEN_HEIGHT 135
31+
32+
// Bar graph layout
33+
#define BAR_X 48 // Left edge of bars (after labels)
34+
#define BAR_WIDTH 120 // Maximum bar width
35+
#define BAR_HEIGHT 22 // Height of each bar
36+
#define BAR_SPACING 6 // Space between bars
37+
38+
// Y positions
39+
#define TITLE_Y 18
40+
#define UVA_BAR_Y 32
41+
#define UVB_BAR_Y (UVA_BAR_Y + BAR_HEIGHT + BAR_SPACING)
42+
#define UVC_BAR_Y (UVB_BAR_Y + BAR_HEIGHT + BAR_SPACING)
43+
#define TEMP_Y 128
44+
45+
// Colors
46+
#define COLOR_UVA 0x780F // Purple/violet
47+
#define COLOR_UVB 0x339F // Bright blue
48+
#define COLOR_UVC 0x07FF // Cyan
49+
#define COLOR_BAR_BG 0x2104 // Dark gray
50+
#define COLOR_TITLE 0xFFFF // White
51+
52+
// Fixed scale maximums (uW/cm2)
53+
#define UVA_MAX 500.0
54+
#define UVB_MAX 100.0
55+
#define UVC_MAX 50.0
56+
57+
// Previous values for flicker-free updates
58+
float prevUVA = -1, prevUVB = -1, prevUVC = -1;
59+
float prevTemp = -999;
60+
61+
void setup() {
62+
Serial.begin(115200);
63+
unsigned long start = millis();
64+
while (!Serial && (millis() - start < 3000)) {
65+
delay(10);
66+
}
67+
68+
Serial.println(F("AS7331 UV Sensor TFT Demo"));
69+
70+
// Enable TFT power
71+
pinMode(TFT_BACKLITE, OUTPUT);
72+
digitalWrite(TFT_BACKLITE, HIGH);
73+
pinMode(TFT_I2C_POWER, OUTPUT);
74+
digitalWrite(TFT_I2C_POWER, HIGH);
75+
delay(10);
76+
77+
// Initialize TFT
78+
tft.init(135, 240);
79+
tft.setRotation(3);
80+
tft.fillScreen(ST77XX_BLACK);
81+
82+
// Draw title with nice font
83+
tft.setFont(&FreeSansBold9pt7b);
84+
tft.setTextColor(COLOR_TITLE);
85+
tft.setCursor(0, TITLE_Y);
86+
tft.print(F("Adafruit AS7331 UV Sensor"));
87+
88+
// Initialize I2C and sensor
89+
Wire.begin();
90+
91+
if (!as7331.begin(&Wire)) {
92+
Serial.println(F("Failed to find AS7331 sensor!"));
93+
tft.setFont(&FreeSansBold9pt7b);
94+
tft.setTextColor(ST77XX_RED);
95+
tft.setCursor(20, 70);
96+
tft.print(F("Sensor Error!"));
97+
tft.setFont(&FreeSans9pt7b);
98+
tft.setCursor(10, 95);
99+
tft.print(F("Check wiring"));
100+
while (1) {
101+
delay(100);
102+
}
103+
}
104+
105+
Serial.println(F("AS7331 found!"));
106+
107+
// Configure sensor
108+
as7331.setMeasurementMode(AS7331_MODE_CMD);
109+
as7331.setGain(AS7331_GAIN_64X);
110+
as7331.setIntegrationTime(AS7331_TIME_64MS);
111+
112+
drawStaticUI();
113+
}
114+
115+
void drawStaticUI() {
116+
tft.setFont(&FreeSansBold9pt7b);
117+
118+
// Bar labels
119+
tft.setTextColor(COLOR_UVA);
120+
tft.setCursor(2, UVA_BAR_Y + 16);
121+
tft.print(F("UVA"));
122+
123+
tft.setTextColor(COLOR_UVB);
124+
tft.setCursor(2, UVB_BAR_Y + 16);
125+
tft.print(F("UVB"));
126+
127+
tft.setTextColor(COLOR_UVC);
128+
tft.setCursor(2, UVC_BAR_Y + 16);
129+
tft.print(F("UVC"));
130+
131+
// Bar backgrounds and outlines
132+
tft.fillRect(BAR_X, UVA_BAR_Y, BAR_WIDTH, BAR_HEIGHT, COLOR_BAR_BG);
133+
tft.fillRect(BAR_X, UVB_BAR_Y, BAR_WIDTH, BAR_HEIGHT, COLOR_BAR_BG);
134+
tft.fillRect(BAR_X, UVC_BAR_Y, BAR_WIDTH, BAR_HEIGHT, COLOR_BAR_BG);
135+
136+
tft.drawRect(BAR_X - 1, UVA_BAR_Y - 1, BAR_WIDTH + 2, BAR_HEIGHT + 2,
137+
COLOR_UVA);
138+
tft.drawRect(BAR_X - 1, UVB_BAR_Y - 1, BAR_WIDTH + 2, BAR_HEIGHT + 2,
139+
COLOR_UVB);
140+
tft.drawRect(BAR_X - 1, UVC_BAR_Y - 1, BAR_WIDTH + 2, BAR_HEIGHT + 2,
141+
COLOR_UVC);
142+
}
143+
144+
void updateBar(int y, float value, float maxVal, uint16_t color,
145+
float *prevValue) {
146+
int fillWidth = (int)((value / maxVal) * BAR_WIDTH);
147+
if (fillWidth > BAR_WIDTH)
148+
fillWidth = BAR_WIDTH;
149+
if (fillWidth < 0)
150+
fillWidth = 0;
151+
152+
int prevFillWidth = 0;
153+
if (*prevValue >= 0) {
154+
prevFillWidth = (int)((*prevValue / maxVal) * BAR_WIDTH);
155+
if (prevFillWidth > BAR_WIDTH)
156+
prevFillWidth = BAR_WIDTH;
157+
if (prevFillWidth < 0)
158+
prevFillWidth = 0;
159+
}
160+
161+
if (fillWidth != prevFillWidth) {
162+
tft.fillRect(BAR_X, y, BAR_WIDTH, BAR_HEIGHT, COLOR_BAR_BG);
163+
if (fillWidth > 0) {
164+
tft.fillRect(BAR_X, y, fillWidth, BAR_HEIGHT, color);
165+
}
166+
}
167+
168+
// Numeric value to the right of bar
169+
tft.fillRect(BAR_X + BAR_WIDTH + 4, y, 68, BAR_HEIGHT, ST77XX_BLACK);
170+
tft.setFont(&FreeSans9pt7b);
171+
tft.setTextColor(color);
172+
tft.setCursor(BAR_X + BAR_WIDTH + 6, y + 16);
173+
if (value < 10.0) {
174+
tft.print(value, 2);
175+
} else if (value < 100.0) {
176+
tft.print(value, 1);
177+
} else {
178+
tft.print(value, 0);
179+
}
180+
181+
*prevValue = value;
182+
}
183+
184+
void updateTemperature(float temp) {
185+
if (abs(temp - prevTemp) > 0.1) {
186+
tft.fillRect(0, TEMP_Y - 14, SCREEN_WIDTH, 18, ST77XX_BLACK);
187+
tft.setFont(&FreeSans9pt7b);
188+
tft.setTextColor(ST77XX_YELLOW);
189+
tft.setCursor(30, TEMP_Y);
190+
tft.print(F("Temp: ")); tft.print(temp, 1);
191+
tft.print(F(" C"));
192+
prevTemp = temp;
193+
}
194+
}
195+
196+
void loop() {
197+
float uva, uvb, uvc;
198+
199+
if (as7331.oneShot_uWcm2(&uva, &uvb, &uvc)) {
200+
float temp = as7331.readTemperature();
201+
202+
Serial.print(F("UVA: "));
203+
Serial.print(uva, 2);
204+
Serial.print(F(" | UVB: "));
205+
Serial.print(uvb, 2);
206+
Serial.print(F(" | UVC: "));
207+
Serial.print(uvc, 2);
208+
Serial.print(F(" | Temp: "));
209+
Serial.print(temp, 1);
210+
Serial.println(F(" C"));
211+
212+
updateBar(UVA_BAR_Y, uva, UVA_MAX, COLOR_UVA, &prevUVA);
213+
updateBar(UVB_BAR_Y, uvb, UVB_MAX, COLOR_UVB, &prevUVB);
214+
updateBar(UVC_BAR_Y, uvc, UVC_MAX, COLOR_UVC, &prevUVC);
215+
updateTemperature(temp);
216+
} else {
217+
Serial.println(F("Failed to read UV sensor!"));
218+
}
219+
220+
delay(200);
221+
}

0 commit comments

Comments
 (0)