Skip to content

Commit 9bc8566

Browse files
author
clawpi
committed
hw_tests: rewrite config tests for functional verification
1 parent f60f430 commit 9bc8566

File tree

5 files changed

+1199
-201
lines changed

5 files changed

+1199
-201
lines changed
Lines changed: 208 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,240 @@
1+
/**
2+
* AS7331 Break Time Functional Test
3+
*
4+
* Tests that break_time setting actually affects the inter-measurement gap
5+
* in CONT mode, not just register readback.
6+
*
7+
* Approach:
8+
* - Use CONT mode with short integration time (16ms)
9+
* - Measure total time for N complete measurement cycles
10+
* - Compare break_time=0 vs break_time=255
11+
* - With 10 cycles, 255*8us*10 = ~20ms expected difference
12+
*
13+
* Hardware: Metro Mini, AS7331 on I2C, READY→D3
14+
*/
15+
116
#include <Adafruit_AS7331.h>
217
#include <Adafruit_NeoPixel.h>
318

19+
#define READY_PIN 3
420
#define NEOPIXEL_PIN 6
521
#define NEOPIXEL_COUNT 60
22+
#define TIMEOUT_MS 500
23+
#define NUM_CYCLES 10
624

725
Adafruit_AS7331 as7331;
826
Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
927

10-
struct BreakStep {
11-
uint8_t value;
12-
const char *label;
13-
};
28+
uint8_t testsPassed = 0;
29+
uint8_t testsFailed = 0;
30+
31+
void printResult(const char *testName, bool passed) {
32+
Serial.print(testName);
33+
Serial.print(F(": "));
34+
if (passed) {
35+
Serial.println(F("PASS"));
36+
testsPassed++;
37+
} else {
38+
Serial.println(F("FAIL"));
39+
testsFailed++;
40+
}
41+
}
42+
43+
// Wait for READY to transition to target state
44+
bool waitForReady(bool targetHigh, uint32_t timeout) {
45+
uint32_t start = millis();
46+
while (millis() - start < timeout) {
47+
if (digitalRead(READY_PIN) == (targetHigh ? HIGH : LOW))
48+
return true;
49+
}
50+
return false;
51+
}
52+
53+
// Measure total time for N complete measurement cycles in CONT mode
54+
// Returns time in microseconds, or 0 on error
55+
uint32_t measureNCycles(uint8_t numCycles) {
56+
// Wait for first READY HIGH to synchronize
57+
if (!waitForReady(true, TIMEOUT_MS)) {
58+
Serial.println(F(" Timeout waiting for first READY HIGH"));
59+
return 0;
60+
}
61+
62+
// Read data to acknowledge
63+
uint16_t uva, uvb, uvc;
64+
as7331.readAllUV(&uva, &uvb, &uvc);
65+
66+
// Start timing
67+
uint32_t startTime = micros();
68+
uint8_t cycles = 0;
1469

15-
const BreakStep break_steps[] = {
16-
{0, "0 (0us)"},
17-
{25, "25 (200us)"},
18-
{125, "125 (1ms)"},
19-
{255, "255 (2.04ms)"},
20-
};
70+
while (cycles < numCycles) {
71+
// Wait for READY LOW (next measurement starting)
72+
if (!waitForReady(false, TIMEOUT_MS)) {
73+
Serial.println(F(" Timeout waiting for READY LOW"));
74+
return 0;
75+
}
76+
77+
// Wait for READY HIGH (measurement complete)
78+
if (!waitForReady(true, TIMEOUT_MS)) {
79+
Serial.println(F(" Timeout waiting for READY HIGH"));
80+
return 0;
81+
}
82+
83+
// Read data
84+
as7331.readAllUV(&uva, &uvb, &uvc);
85+
cycles++;
86+
}
87+
88+
return micros() - startTime;
89+
}
90+
91+
void setup() {
92+
pinMode(READY_PIN, INPUT_PULLUP);
2193

22-
void setup(void) {
2394
Serial.begin(115200);
24-
while (!Serial) {
95+
while (!Serial)
2596
delay(10);
26-
}
2797

98+
Serial.println(F("\n========================================"));
99+
Serial.println(F("AS7331 Break Time Functional Test"));
100+
Serial.println(F("Tests actual timing, not just register readback"));
101+
Serial.println(F("========================================\n"));
102+
103+
// NeoPixels for consistent light source
28104
pixels.begin();
29105
pixels.setBrightness(255);
30106
pixels.fill(pixels.Color(255, 255, 255));
31107
pixels.show();
32108

33109
if (!as7331.begin()) {
34-
Serial.println("AS7331 not found");
35-
while (1) {
36-
delay(10);
37-
}
110+
Serial.println(F("ERROR: AS7331 not found!"));
111+
while (1)
112+
delay(100);
38113
}
114+
Serial.println(F("AS7331 found!\n"));
115+
116+
// ========================================
117+
// TEST 1: Register readback verification
118+
// ========================================
119+
Serial.println(F("--- TEST 1: Register Readback ---"));
120+
121+
as7331.powerDown(true);
122+
as7331.setBreakTime(0);
123+
uint8_t read0 = as7331.getBreakTime();
124+
printResult("break_time=0 readback", read0 == 0);
125+
126+
as7331.setBreakTime(255);
127+
uint8_t read255 = as7331.getBreakTime();
128+
printResult("break_time=255 readback", read255 == 255);
129+
130+
Serial.println();
131+
132+
// ========================================
133+
// TEST 2: Timing with break_time=0
134+
// ========================================
135+
Serial.println(F("--- TEST 2: Timing with break_time=0 ---"));
136+
Serial.print(F("Measuring "));
137+
Serial.print(NUM_CYCLES);
138+
Serial.println(F(" cycles..."));
39139

40140
as7331.powerDown(true);
41-
as7331.setGain(AS7331_GAIN_4X);
42-
as7331.setIntegrationTime(AS7331_TIME_64MS);
43141
as7331.setMeasurementMode(AS7331_MODE_CONT);
142+
as7331.setIntegrationTime(AS7331_TIME_16MS);
143+
as7331.setGain(AS7331_GAIN_16X);
144+
as7331.setClockFrequency(AS7331_CLOCK_1024MHZ);
145+
as7331.setBreakTime(0);
44146
as7331.powerDown(false);
147+
as7331.startMeasurement();
45148

46-
bool all_pass = true;
149+
delay(100); // Let CONT mode settle
47150

48-
for (size_t i = 0; i < sizeof(break_steps) / sizeof(break_steps[0]); i++) {
49-
uint8_t value = break_steps[i].value;
50-
as7331.powerDown(true);
51-
bool wrote = as7331.setBreakTime(value);
52-
uint8_t readback = as7331.getBreakTime();
53-
as7331.powerDown(false);
54-
delay(10);
55-
bool pass = wrote && (readback == value);
56-
if (!pass) {
57-
all_pass = false;
58-
}
151+
uint32_t totalTime0 = measureNCycles(NUM_CYCLES);
152+
Serial.print(F(" Total time for "));
153+
Serial.print(NUM_CYCLES);
154+
Serial.print(F(" cycles: "));
155+
Serial.print(totalTime0 / 1000);
156+
Serial.println(F(" ms"));
157+
158+
as7331.stopMeasurement();
159+
as7331.powerDown(true);
160+
delay(50);
161+
162+
// ========================================
163+
// TEST 3: Timing with break_time=255
164+
// ========================================
165+
Serial.println(F("\n--- TEST 3: Timing with break_time=255 ---"));
166+
Serial.print(F("Measuring "));
167+
Serial.print(NUM_CYCLES);
168+
Serial.println(F(" cycles..."));
169+
170+
as7331.setBreakTime(255);
171+
as7331.powerDown(false);
172+
as7331.startMeasurement();
59173

60-
Serial.print("Break time ");
61-
Serial.print(break_steps[i].label);
62-
Serial.print(": wrote=");
63-
Serial.print(value);
64-
Serial.print(", read=");
65-
Serial.print(readback);
66-
Serial.print(", ");
67-
Serial.println(pass ? "PASS" : "FAIL");
174+
delay(100); // Let CONT mode settle
175+
176+
uint32_t totalTime255 = measureNCycles(NUM_CYCLES);
177+
Serial.print(F(" Total time for "));
178+
Serial.print(NUM_CYCLES);
179+
Serial.print(F(" cycles: "));
180+
Serial.print(totalTime255 / 1000);
181+
Serial.println(F(" ms"));
182+
183+
as7331.stopMeasurement();
184+
185+
// ========================================
186+
// TEST 4: Verify timing difference
187+
// ========================================
188+
Serial.println(F("\n--- TEST 4: Timing Comparison ---"));
189+
190+
if (totalTime0 > 0 && totalTime255 > 0) {
191+
int32_t diff = (int32_t)totalTime255 - (int32_t)totalTime0;
192+
Serial.print(F("Time difference: "));
193+
Serial.print(diff / 1000);
194+
Serial.println(F(" ms"));
195+
196+
// Expected: ~20ms (255 * 8us * 10 cycles = 20.4ms)
197+
// Accept anything >5ms as meaningful (allows for noise)
198+
bool timingDifferent = diff > 5000;
199+
200+
Serial.print(F("Expected ~20ms difference, got "));
201+
Serial.print(diff / 1000);
202+
Serial.println(F(" ms"));
203+
204+
printResult("break_time=255 takes measurably longer", timingDifferent);
205+
206+
// Sanity: difference should be reasonable (<100ms)
207+
bool reasonableDiff = diff < 100000;
208+
printResult("Timing difference is reasonable", reasonableDiff);
209+
210+
// Per-cycle timing
211+
Serial.print(F("Per-cycle avg with break=0: "));
212+
Serial.print(totalTime0 / NUM_CYCLES);
213+
Serial.println(F(" us"));
214+
Serial.print(F("Per-cycle avg with break=255: "));
215+
Serial.print(totalTime255 / NUM_CYCLES);
216+
Serial.println(F(" us"));
217+
} else {
218+
Serial.println(F("ERROR: Could not measure timing"));
219+
printResult("Timing measurement", false);
68220
}
69221

70-
Serial.println(all_pass ? "Overall: PASS" : "Overall: FAIL");
222+
// ========================================
223+
// Summary
224+
// ========================================
225+
Serial.println(F("\n========================================"));
226+
Serial.print(F("SUMMARY: "));
227+
Serial.print(testsPassed);
228+
Serial.print(F(" passed, "));
229+
Serial.print(testsFailed);
230+
Serial.println(F(" failed"));
231+
Serial.println(F("========================================"));
232+
233+
if (testsFailed == 0) {
234+
Serial.println(F("Overall: PASS"));
235+
} else {
236+
Serial.println(F("Overall: FAIL"));
237+
}
71238
}
72239

73-
void loop(void) {}
240+
void loop() {}

0 commit comments

Comments
 (0)