You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

495 lines
14 KiB
C++

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Wire.h>
#include <INA226.h>
#include <ESP8266HTTPClient.h>
const int redPin = 12; // Red
const int greenPin = 13; // Green
const int bluePin = 14; // Blue
const int warning = 16;
const int pwmResolution = 1024;
TwoWire Wire_;
// INA226 instances
INA226 redINA(0x45, &Wire_); // 1000101
INA226 blueINA(0x41, &Wire_); // 1000100
INA226 greenINA(0x44, &Wire_); // 1000001
const char *ssid = "dlink-AB48";
const char *password = "mjjbk74568";
// Array to store slave IP addresses
const char* slaveIPs[] = {
"192.168.129.119", // Slave 1
};
const int NUM_SLAVES = sizeof(slaveIPs) / sizeof(slaveIPs[0]);
int redValue = 0;
int greenValue = 0;
int blueValue = 0;
float brightness = 100.0;
bool rainbowActive = false;
unsigned long lastRainbowUpdate = 0;
int currentHue = 0;
// New variables for current monitoring
float redCurrent = 0;
float greenCurrent = 0;
float blueCurrent = 0;
unsigned long lastCurrentUpdate = 0;
ESP8266WebServer server(80);
WiFiClient wifiClient;
void handleSetRGB() {
if (server.hasArg("r") && server.hasArg("g") && server.hasArg("b")) {
redValue = server.arg("r").toInt();
greenValue = server.arg("g").toInt();
blueValue = server.arg("b").toInt();
rainbowActive = false;
// Set master LED
setRGB(redValue, greenValue, blueValue, brightness);
// Propagate to slaves
String url = String("/set_rgb?r=") + redValue +
String("&g=") + greenValue +
String("&b=") + blueValue;
propagateToSlaves(url);
server.send(200, "text/plain", "RGB updated");
} else {
server.send(400, "text/plain", "Missing RGB arguments");
}
}
// Modified handleSetBrightness to propagate to slaves
void handleSetBrightness() {
if (server.hasArg("value")) {
brightness = server.arg("value").toFloat();
setRGB(redValue, greenValue, blueValue, brightness);
// Propagate to slaves
String url = String("/set_brightness?value=") + brightness;
propagateToSlaves(url);
server.send(200, "text/plain", "Brightness updated");
} else {
server.send(400, "text/plain", "Missing brightness argument");
}
}
// Modified handleRainbow to propagate to slaves
void handleRainbow() {
if (server.hasArg("state")) {
rainbowActive = server.arg("state") == "true";
if (!rainbowActive) {
setRGB(redValue, greenValue, blueValue, brightness);
}
// Propagate to slaves
String url = String("/rainbow?state=") + server.arg("state");
propagateToSlaves(url);
}
server.send(200, "text/plain", rainbowActive ? "Rainbow started" : "Rainbow stopped");
}
// New function to propagate commands to slaves
void propagateToSlaves(String endpoint) {
HTTPClient http;
for (int i = 0; i < NUM_SLAVES; i++) {
String url = String("http://") + slaveIPs[i] + endpoint;
http.begin(wifiClient, url);
int httpCode = http.GET();
if (httpCode != HTTP_CODE_OK) {
Serial.printf("Failed to propagate to slave %s: %d\n", slaveIPs[i], httpCode);
}
http.end();
}
}
void handleGetCurrents() {
String json = "{\"red\":" + String(redCurrent, 3) +
",\"green\":" + String(greenCurrent, 3) +
",\"blue\":" + String(blueCurrent, 3) +
",\"total\":" + String(redCurrent + greenCurrent + blueCurrent, 3) +
",\"redBusV\":" + String(redINA.getBusVoltage(), 3) +
",\"greenBusV\":" + String(greenINA.getBusVoltage(), 3) +
",\"blueBusV\":" + String(blueINA.getBusVoltage(), 3) +
"}";
server.send(200, "application/json", json);
}
void scanI2CBus(TwoWire &wire) {
Serial.println("Scanning I2C Bus...");
for (uint8_t address = 1; address < 127; ++address) {
wire.beginTransmission(address);
if (wire.endTransmission() == 0) {
Serial.print("Device found at address 0x");
Serial.println(address, HEX);
}
}
}
void initializeINA226(INA226 &sensor, const char* name) {
if (!sensor.begin()) {
Serial.print("INA226 initialization failed for ");
Serial.println(name);
} else {
Serial.print("INA226 initialized for ");
Serial.println(name);
}
if (strcmp(name, "RED") == 0) {
sensor.setMaxCurrentShunt(0.4, 0.09);
} else if (strcmp(name, "GREEN") == 0) {
sensor.setMaxCurrentShunt(0.35, 0.18);
} else if (strcmp(name, "BLUE") == 0) {
sensor.setMaxCurrentShunt(0.35, 0.18);
} else {
// Default case for unknown names
sensor.setMaxCurrentShunt(0, 0);
}
}
void setup() {
Serial.begin(115200);
analogWriteRange(pwmResolution);
Serial.println("Initializing RGB LED Controller with Current Monitoring");
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
setRGB(redValue, greenValue, blueValue, brightness);
delay(100);
Wire_.begin(5, 4);
delay(200);
scanI2CBus(Wire_);
delay(200); // Extended delay
initializeINA226(redINA, "RED");
delay(200);
initializeINA226(greenINA, "GREEN");
delay(200);
initializeINA226(blueINA, "BLUE");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("Connected to Wi-Fi");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
server.on("/", handleRoot);
server.on("/set_rgb", handleSetRGB);
server.on("/set_brightness", handleSetBrightness);
server.on("/rainbow", handleRainbow);
server.on("/get_currents", handleGetCurrents);
server.begin();
}
void loop() {
server.handleClient();
unsigned long currentMillis = millis();
// Current measurement update (every 100ms)
if (currentMillis - lastCurrentUpdate >= 100) {
// Get current readings from all sensors
redCurrent = redINA.getCurrent_mA();
greenCurrent = greenINA.getCurrent_mA();
blueCurrent = blueINA.getCurrent_mA();
lastCurrentUpdate = currentMillis;
}
// Rainbow animation update (every 20ms)
if (rainbowActive && (currentMillis - lastRainbowUpdate >= 20)) {
float r, g, b;
hsvToRgb(currentHue, 1.0, brightness / 100.0, r, g, b);
setRGB((int)(r * 255), (int)(g * 255), (int)(b * 255), brightness);
currentHue = (currentHue + 1) % 360;
lastRainbowUpdate = currentMillis;
}
}
void hsvToRgb(int hue, float saturation, float value, float &r, float &g, float &b) {
float c = value * saturation;
float x = c * (1 - abs(fmod(hue / 60.0, 2) - 1));
float m = value - c;
if (hue >= 0 && hue < 60) {
r = c; g = x; b = 0;
} else if (hue >= 60 && hue < 120) {
r = x; g = c; b = 0;
} else if (hue >= 120 && hue < 180) {
r = 0; g = c; b = x;
} else if (hue >= 180 && hue < 240) {
r = 0; g = x; b = c;
} else if (hue >= 240 && hue < 300) {
r = x; g = 0; b = c;
} else {
r = c; g = 0; b = x;
}
r += m; g += m; b += m;
}
int mapDutyCycle(int value, float brightness) {
float adjusted = value * (brightness / 100.0);
return (int)(adjusted * pwmResolution / 255.0);
}
void setRGB(int red, int green, int blue, float brightness) {
analogWrite(redPin, mapDutyCycle(red, brightness));
analogWrite(greenPin, mapDutyCycle(green, brightness));
analogWrite(bluePin, mapDutyCycle(blue, brightness));
}
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
// [Previous ESP8266 setup code remains the same until handleRoot()]
void handleRoot() {
String html = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<title>RGB Control</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-color/2.8.1/vue-color.min.js"></script>
<style>
@import url(https://fonts.googleapis.com/css?family=Barlow);
* { font-family: "Barlow"; box-sizing: border-box; }
body {
text-align: center;
margin: 0;
padding: 20px;
background: #f0f0f0;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.page-container {
display: flex;
flex-wrap: wrap;
gap: 2rem;
justify-content: center;
align-items: stretch;
max-width: 1200px;
margin: 0 auto;
}
.container {
background: white;
padding: 2rem;
border-radius: 15px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
width: 500px;
display: flex;
flex-direction: column;
align-items: center;
}
.current-monitor {
background: white;
padding: 2rem;
border-radius: 15px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
width: 500px;
}
.current-display {
display: flex;
flex-direction: column;
gap: 1rem;
margin-top: 1rem;
}
.current-item {
padding: 1rem;
border-radius: 10px;
color: white;
text-align: left;
display: flex;
justify-content: space-between;
}
.current-red { background: linear-gradient(to right, #ff0000, #ff4444); }
.current-green { background: linear-gradient(to right, #00ff00, #44ff44); }
.current-blue { background: linear-gradient(to right, #0000ff, #4444ff); }
.current-total {
background: linear-gradient(to right, #666, #999);
font-weight: bold;
}
.vc-chrome {
width: 100% !important;
margin: 1rem 0;
}
.controls {
width: 100%;
margin-top: 1rem;
}
.brightness-control {
margin: 1rem 0;
}
.brightness-control input {
width: 100%;
}
.color-preview {
width: 100%;
height: 60px;
border-radius: 10px;
margin: 1rem 0;
transition: all 0.3s ease;
}
@media (max-width: 768px) {
.container,
.current-monitor {
width: 100%;
max-width: 500px;
}
.page-container {
flex-direction: column;
align-items: center;
}
}
</style>
</head>
<body>
<div id="app"></div>
<script>
new Vue({
el: "#app",
components: {
'chrome-picker': VueColor.Chrome
},
data: {
color: {
hex: "#000000",
rgba: { r: 0, g: 0, b: 0, a: 1 }
},
brightness: 0,
rainbow: false,
currents: {
red: 0,
green: 0,
blue: 0,
total: 0
}
},
methods: {
updateColor(color) {
this.color = color;
const { r, g, b } = color.rgba;
fetch(`/set_rgb?r=${r}&g=${g}&b=${b}`);
},
updateBrightness() {
fetch(`/set_brightness?value=${this.brightness}`);
},
toggleRainbow() {
fetch(`/rainbow?state=${this.rainbow}`);
},
async updateCurrents() {
try {
const response = await fetch('/get_currents');
this.currents = await response.json();
} catch (error) {
console.error('Error fetching currents:', error);
}
}
},
mounted() {
// Send initial state to the server
const { r, g, b } = this.color.rgba;
fetch(`/set_rgb?r=${r}&g=${g}&b=${b}`);
fetch(`/set_brightness?value=${this.brightness}`);
setInterval(this.updateCurrents, 200);
},
computed: {
previewStyle() {
const { r, g, b } = this.color.rgba;
const brightness = this.brightness / 100;
return {
backgroundColor: `rgba(${r}, ${g}, ${b}, ${brightness})`,
boxShadow: `0 0 15px rgba(${r}, ${g}, ${b}, ${brightness})`
};
}
},
template: `
<div class="page-container">
<div class="container">
<h1 class="title">RGB Control</h1>
<div class="color-preview" :style="previewStyle"></div>
<chrome-picker
:value="color"
@input="updateColor"
:disable-alpha="true"
></chrome-picker>
<div class="controls">
<div class="brightness-control">
<p>Brightness: {{ brightness }}%</p>
<input
type="range"
min="0"
max="100"
v-model="brightness"
@change="updateBrightness"
/>
</div>
<div class="rainbow-toggle">
<label>
<input
type="checkbox"
v-model="rainbow"
@change="toggleRainbow"
/>
Rainbow Animation
</label>
</div>
</div>
</div>
<div class="current-monitor">
<h2>Current Monitor</h2>
<div class="current-display">
<div class="current-item current-red">
<span>Red LED:</span>
<span>{{ currents.red.toFixed(2) }} mA</span>
</div>
<div class="current-item current-green">
<span>Green LED:</span>
<span>{{ currents.green.toFixed(2) }} mA</span>
</div>
<div class="current-item current-blue">
<span>Blue LED:</span>
<span>{{ currents.blue.toFixed(2) }} mA</span>
</div>
<div class="current-item current-total">
<span>Total Current:</span>
<span>{{ currents.total.toFixed(2) }} mA</span>
</div>
</div>
</div>
</div>
`
});
</script>
</body>
</html>
)rawliteral";
server.send(200, "text/html", html);
}