-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
165 lines (140 loc) · 5.49 KB
/
main.cpp
File metadata and controls
165 lines (140 loc) · 5.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <Adafruit_TCS34725.h>
#include <Arduino.h>
#include <FastLED.h>
#include <GyverHub.h>
#include <Wire.h>
#include "ColorHelpers.h"
#include "GyverHubNet.h"
#include "StripSettings.h"
#include "i2c/Tca9548a.h"
#include "sensors/SensorRing.h"
#include "ui/GyverHubDebug.h"
#include <GyverHubSettings.h>
constexpr uint8_t I2C_SDA_PIN = 21;
constexpr uint8_t I2C_SCL_PIN = 22;
constexpr uint32_t I2C_CLOCK_HZ = 400000;
constexpr uint8_t TCA9548A_ADDRESS = 0x70;
constexpr uint32_t SENSOR_READ_INTERVAL_MS = 20;
constexpr uint32_t SENSOR_SMOOTH_INTERVAL_MS = 16;
constexpr uint32_t LED_UPDATE_INTERVAL_MS = 16;
constexpr uint32_t HUB_UPDATE_INTERVAL_MS = 100;
constexpr uint32_t SERIAL_UPDATE_INTERVAL_MS = 1000;
constexpr uint8_t TCS_LED_PIN = 27;
constexpr uint8_t STRIP_PIN = 26;
constexpr uint16_t STRIP_LED_COUNT = 300; // 51+54+95+53+47
constexpr float LED_SMOOTH_ALPHA = 0.28f;
constexpr uint8_t SENSOR_DEADBAND = 2;
// Sensor order is fixed: 1..8 = Bottom, Bottom Left, Left, Top Left, Top, Top Right, Right, Bottom Right.
constexpr uint8_t kTcaChannelBySensor[sensor_ring::kSensorCount] = {0, 1, 2, 3, 4, 5, 6, 7};
constexpr float kLtc[3] = {1.0f, 0.95f, 0.75f};
// LED strip zone table.
// Chain order: BottomLeft(51) → Left(54) → Top(95) → Right(53) → BottomRight(47) = 300 total.
// BottomLeft DI at center-bottom going left; Left DI at bottom going up;
// Top DI at top-left going right; Right DI at top-right going down; BottomRight DI at right going to center.
// Sensor 1 (Bottom/center) is split across the strip boundary (indices 0 and 299).
constexpr color_helpers::LedZone kLedZones[] = {
{ 0, 24, 0}, // S1 B — near center, first half (BottomLeft strip start)
{ 25, 63, 1}, // S2 BL — bottom-left area
{ 64, 91, 2}, // S3 L — left side middle
{ 92, 128, 3}, // S4 TL — top-left area
{129, 175, 4}, // S5 T — top center
{176, 212, 5}, // S6 TR — top-right area
{213, 239, 6}, // S7 R — right side middle
{240, 275, 7}, // S8 BR — bottom-right area
{276, 299, 0}, // S1 B — near center, second half (BottomRight strip end)
};
constexpr uint8_t kLedZoneCount = sizeof(kLedZones) / sizeof(kLedZones[0]);
CRGB leds[STRIP_LED_COUNT];
StripSettings stripSettings;
GyverHub hub;
bool hubStarted = false;
Tca9548a tca(Wire, TCA9548A_ADDRESS);
Adafruit_TCS34725 tcs(
TCS34725_INTEGRATIONTIME_24MS,
TCS34725_GAIN_16X);
sensor_ring::SensorRing sensorRing(tca, tcs);
GyverHubDebugUi hubDebug(sensorRing, stripSettings);
void setup() {
Serial.begin(115200);
Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
Wire.setClock(I2C_CLOCK_HZ);
strip_settings::load(stripSettings);
pinMode(TCS_LED_PIN, OUTPUT);
digitalWrite(TCS_LED_PIN, LOW);
FastLED.addLeds<WS2812B, STRIP_PIN, GRB>(leds, STRIP_LED_COUNT);
FastLED.setBrightness(stripSettings.brightness);
color_helpers::renderStrip(leds, STRIP_LED_COUNT, STRIP_LED_COUNT, CRGB::Black);
sensorRing.setChannelMapping(kTcaChannelBySensor);
sensorRing.setReadInterval(SENSOR_READ_INTERVAL_MS);
sensorRing.setSmoothInterval(SENSOR_SMOOTH_INTERVAL_MS);
sensorRing.setSmoothAlpha(LED_SMOOTH_ALPHA);
sensorRing.setDeadband(SENSOR_DEADBAND);
sensorRing.setLtc(kLtc);
if (!sensorRing.begin()) {
Serial.println("No active TCS34725 sensors on startup, manager will keep retrying");
}
if (setupWiFi()) {
hub.config(GH_NETWORK_PREFIX, GH_DEVICE_NAME, GH_DEVICE_ICON);
hubDebug.attach(hub);
hub.begin();
hubStarted = true;
} else {
Serial.println("Network is not available. Hub disabled.");
}
}
void loop() {
if (hubStarted) {
hub.tick();
}
const uint32_t now = millis();
sensorRing.tick(now);
static uint32_t ledTimer = 0;
if ((uint32_t)(now - ledTimer) >= LED_UPDATE_INTERVAL_MS) {
ledTimer = now;
FastLED.setBrightness(stripSettings.brightness);
if (!stripSettings.stripOn) {
// Strip off — show black.
fill_solid(leds, STRIP_LED_COUNT, CRGB::Black);
FastLED.show();
} else if (hubDebug.isTestMode()) {
// Mode 1: slow flowing aurora rainbow — idle/test animation.
static uint8_t auroraHue = 0;
static uint8_t auroraSubtick = 0;
if (++auroraSubtick >= 3) { // advance hue every 3 frames (~50 ms) → full cycle ≈ 13 s
auroraSubtick = 0;
auroraHue++;
}
// One full rainbow spread across the strip; hue offset drifts slowly.
fill_rainbow(leds, STRIP_LED_COUNT, auroraHue, 1);
FastLED.show();
} else {
// Mode 2: each LED zone shows the calibrated color of its sensor.
CRGB colors[sensor_ring::kSensorCount];
for (uint8_t i = 0; i < sensor_ring::kSensorCount; i++) {
colors[i] = color_helpers::calibrateColor(
sensorRing.result(i).displayedColor,
stripSettings.hueShift,
stripSettings.saturation);
}
color_helpers::renderStripZoned(leds, STRIP_LED_COUNT, kLedZones, kLedZoneCount, colors);
}
}
static uint32_t hubTimer = 0;
if (hubStarted && (uint32_t)(now - hubTimer) >= HUB_UPDATE_INTERVAL_MS) {
hubTimer = now;
hubDebug.update();
}
static uint32_t serialTimer = 0;
if ((uint32_t)(now - serialTimer) >= SERIAL_UPDATE_INTERVAL_MS) {
serialTimer = now;
for (uint8_t i = 0; i < sensor_ring::kSensorCount; i++) {
const sensor_ring::SensorResult& result = sensorRing.result(i);
Serial.printf(
"S%u ch%u %s %s\n",
(unsigned)(i + 1),
(unsigned)result.channel,
result.online ? "ok" : "error",
result.statusText);
}
}
}