feat: colored gradient by height

This commit is contained in:
Alessevan 2025-05-16 14:37:08 +02:00
parent 71432ff96c
commit badb6ac5f0

View File

@ -1,4 +1,4 @@
#include <Adafruit_NeoPixel.h> #include <FastLED.h>
#include <ESP32Servo.h> #include <ESP32Servo.h>
#include <Wire.h> #include <Wire.h>
#include <VL53L0X.h> #include <VL53L0X.h>
@ -9,8 +9,9 @@
#ifdef __AVR__ #ifdef __AVR__
#include <avr/power.h> #include <avr/power.h>
#endif #endif
#define PIN 5 #define PIN_PIXELS 4
#define NUMPIXELS 6 #define NUM_PIXELS 6
#define TUBES_COUNT 6
// Web server configuration // Web server configuration
const char* ssid = "ESP_ping"; const char* ssid = "ESP_ping";
@ -21,7 +22,7 @@ const char* PARAM_INPUT_2 = "state";
AsyncWebServer server(80); AsyncWebServer server(80);
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); CRGB leds[NUM_PIXELS];
struct pin { struct pin {
int id; int id;
@ -33,6 +34,7 @@ enum state {
STATE_NONE, STATE_NONE,
STATE_INIT, STATE_INIT,
STATE_OK, STATE_OK,
STATE_MOVING,
STATE_ERROR STATE_ERROR
}; };
@ -57,39 +59,32 @@ struct tube {
enum mode { enum mode {
NONE, NONE,
SINUS, SINUS,
MAX_MODE,
}; };
enum mode current_mode = NONE; enum mode current_mode = NONE;
const struct pin all_xshuts[6] = { const struct pin all_xshuts[6] = {
{.id = 17, .is_extender = 0},
{.id = 2, .is_extender = 1},
{.id = 3, .is_extender = 1},
{.id = 5, .is_extender = 1},
{.id = 7, .is_extender = 1}, {.id = 7, .is_extender = 1},
{.id = 1, .is_extender = 1} {.id = 0, .is_extender = 1},
{.id = 1, .is_extender = 1},
{.id = 6, .is_extender = 1},
{.id = 5, .is_extender = 1},
{.id = 4, .is_extender = 1}
}; };
const struct pin all_gpios[6] = {
{.id = -1, .is_extender = 0},
{.id = 18, .is_extender = 0},
{.id = 19, .is_extender = 0},
{.id = -1, .is_extender = 1},
{.id = 6, .is_extender = 1},
{.id = 0, .is_extender = 1}
};
const struct pin all_servos[6] = { const struct pin all_servos[6] = {
{.id = 32, .is_extender = 0}, {.id = 32, .is_extender = 0},
{.id = 33, .is_extender = 0}, {.id = 33, .is_extender = 0},
{.id = 23, .is_extender = 0}, {.id = 18, .is_extender = 0},
{.id = 16, .is_extender = 0}, {.id = 27, .is_extender = 0},
{.id = 4, .is_extender = 0}, {.id = 14, .is_extender = 0},
{.id = 2, .is_extender = 0} {.id = 19, .is_extender = 0}
}; };
struct tube all_tubes[6]; struct tube all_tubes[6];
const int TUBES_COUNT = 2;
const float minHeight = 50; const float minHeight = 50;
const float maxHeight = 445; const float maxHeight = 445;
@ -164,25 +159,36 @@ void changePinMode(struct pin pin, int state) {
void change_led(int id) { void change_led(int id) {
Serial.print("Changing led color of #"); Serial.print("Changing led color of #");
Serial.println(id); Serial.println(id);
int led_id = NUMPIXELS -1 - id; int led_id = NUM_PIXELS - 1 - id;
switch (all_tubes[id].state) { switch (all_tubes[id].state) {
case STATE_INIT: { case STATE_INIT: {
pixels.setPixelColor(led_id, pixels.Color(255, 210, 70)); leds[led_id] = CRGB(255, 210, 70);
break; break;
} }
case STATE_OK: { case STATE_OK: {
pixels.setPixelColor(led_id, pixels.Color(0, 0, 190)); leds[led_id] = CRGB::Blue;
break;
}
case STATE_MOVING: {
float ratio = (all_tubes[id].height) / (maxHeight);
if (ratio > 1.0) {
ratio = 1.0;
} else if (ratio < 0.0f) {
ratio = 0.0;
}
leds[led_id] = CHSV((int) (ratio * 128.0 + (1 - ratio) * 240.0) - 90, 255, 255);
break; break;
} }
case STATE_ERROR: { case STATE_ERROR: {
pixels.setPixelColor(led_id, pixels.Color(0, 190, 0)); leds[led_id] = CRGB::Red;
break; break;
} }
default: { default: {
pixels.setPixelColor(led_id, pixels.Color(3, 3, 3)); leds[led_id] = CRGB::Black;
break; break;
} }
} }
FastLED.show();
} }
// Web Server configuration // Web Server configuration
@ -209,6 +215,8 @@ const char index_html[] PROGMEM = R"rawliteral(
<body> <body>
<h2>Balle Ping Pong flottante</h2> <h2>Balle Ping Pong flottante</h2>
%BUTTONPLACEHOLDER% %BUTTONPLACEHOLDER%
<button id="switch_mode">Changer mode</button>
<div id="mode"></div>
<script> <script>
function sendSliderValue(id, element) { function sendSliderValue(id, element) {
@ -218,6 +226,17 @@ const char index_html[] PROGMEM = R"rawliteral(
xhr.send(); xhr.send();
} }
var mode = 0;
document.getElementById('switch_mode').addEventListener('click', function() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/switch_mode", true);
xhr.send();
mode += 1;
mode %= 2;
document.getElementById('mode').innerText = mode;
});
</script> </script>
</body> </body>
</html> </html>
@ -243,9 +262,6 @@ String processor(const String& var){
void wifisetup() { void wifisetup() {
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
Serial.print("Setting AP (Access Point)…"); Serial.print("Setting AP (Access Point)…");
WiFi.softAP(ssid); WiFi.softAP(ssid);
@ -260,6 +276,10 @@ void wifisetup() {
// Send a GET request to <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2> // Send a GET request to <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) { server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
if (current_mode != NONE) {
request->send(401, "text/plain", "NOK");
return;
}
int inputMessage1; int inputMessage1;
int inputMessage2; int inputMessage2;
// GET input1 value on <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2> // GET input1 value on <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
@ -281,6 +301,12 @@ void wifisetup() {
request->send(200, "text/plain", "OK"); request->send(200, "text/plain", "OK");
}); });
// Send a GET request to <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
server.on("/switch_mode", HTTP_GET, [] (AsyncWebServerRequest *request) {
current_mode = static_cast<mode>(NONE + (current_mode + 1) % MAX_MODE);
request->send(200, "text/plain", "OK");
});
// Start server // Start server
server.begin(); server.begin();
} }
@ -303,7 +329,6 @@ void setup_all_tofs() {
Serial.println(F("Failed to boot VL53L0X")); Serial.println(F("Failed to boot VL53L0X"));
all_tubes[i].state = STATE_ERROR; all_tubes[i].state = STATE_ERROR;
change_led(i); change_led(i);
pixels.show();
goto error; goto error;
} }
all_tubes[i].tof.hard.setAddress(0x31 + i); all_tubes[i].tof.hard.setAddress(0x31 + i);
@ -321,15 +346,20 @@ void calibrate_tube(int i){
delay(5000); delay(5000);
Serial.println("Setuping downards"); Serial.println("Setuping downards");
uint16_t h = mesureHeight(i); uint16_t h = mesureHeight(i);
if (h < 100) {
all_tubes[i].state = STATE_ERROR;
Serial.printf("Tube %d HS ! (pas assez haut)\n", i);
change_led(i);
return;
}
int angle = minServo; int angle = minServo;
while (h > maxHeight) { while (h > maxHeight) {
Serial.printf("%dmm %d°\n",h, angle); Serial.printf("%dmm %d°\n",h, angle);
++angle; ++angle;
if (angle > maxServo) { if (angle > maxServo) {
all_tubes[i].state = STATE_ERROR; all_tubes[i].state = STATE_ERROR;
Serial.printf("Tube %d HS !\n", i); Serial.printf("Tube %d HS ! (moteur ne tourne pas ?)\n", i);
change_led(i); change_led(i);
pixels.show();
return; return;
} }
all_tubes[i].servo.hard.write(angle); all_tubes[i].servo.hard.write(angle);
@ -343,7 +373,6 @@ void calibrate_tube(int i){
Serial.printf("Tube %d calibrated.\n", i); Serial.printf("Tube %d calibrated.\n", i);
all_tubes[i].state = STATE_OK; all_tubes[i].state = STATE_OK;
change_led(i); change_led(i);
pixels.show();
} }
void setup_servos() { void setup_servos() {
@ -365,17 +394,17 @@ int servoPosition(float ratio){
} }
void setup() { void setup() {
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
Serial.begin(115200); // Starts the serial communication Serial.begin(115200); // Starts the serial communication
while (! Serial) { while (! Serial) {
delay(1); delay(1);
} }
pixels.begin(); FastLED.addLeds<NEOPIXEL, PIN_PIXELS>(leds, NUM_PIXELS);
pixels.setBrightness(255); FastLED.setBrightness(255);
pixels.show(); for (int i = 0; i < NUM_PIXELS; ++i) {
leds[i] = CRGB::Black;
}
FastLED.show();
setup_servos(); setup_servos();
delay(5000); delay(5000);
@ -403,44 +432,33 @@ void setup() {
for (int i = 0; i<TUBES_COUNT; i++){ for (int i = 0; i<TUBES_COUNT; i++){
calibrate_tube(i); calibrate_tube(i);
} }
for (int i = 0; i < TUBES_COUNT; ++i) {
if (all_tubes[i].state == STATE_OK) {
all_tubes[i].state = STATE_MOVING;
}
}
} }
int sinus_center = 300; int sinus_center = 300;
int sinus_radius = 100; float sinus_radius = 100.0;
float step = 0; float step = 0;
float rate = 0.01; double rate = 0.000001;
void loop() { void loop() {
if (current_mode == SINUS) {
Serial.printf("SINUS moving\n");
pixels.clear();
pixels.show();
Serial.println("Cleared");
delay(500);
for(int i=0; i<NUMPIXELS; i++) {
Serial.print("Set light");
Serial.println(i);
pixels.setPixelColor(i, pixels.Color(0, 150, 0));
pixels.show();
delay(500);
}
switch (current_mode) {
case SINUS: {
for (int i = 0; i < TUBES_COUNT; i++) { for (int i = 0; i < TUBES_COUNT; i++) {
all_tubes[i].target = 300 + ((int) sinus_radius * sin(rate * (step + i * 0.1) * 3.14)); float angle = (rate * step + ((float) i) * 3.14/6.0) * 3.14;
all_tubes[i].target = sinus_center + ((int) sinus_radius * sin(angle * 3.14));
Serial.printf("%d - %d = => %f\n", all_tubes[i].height, all_tubes[i].target, angle);
} }
step += 0.1; step += 0.1;
break;
}
default: {
}
} }
for (int i = 0; i<TUBES_COUNT; i++){ for (int i = 0; i<TUBES_COUNT; i++){
change_led(i); change_led(i);
if (all_tubes[i].state != STATE_OK) { if (all_tubes[i].state != STATE_MOVING) {
continue; continue;
} }
all_tubes[i].height = mesureHeight(i); all_tubes[i].height = mesureHeight(i);
@ -458,14 +476,13 @@ void loop() {
angle = all_tubes[i].servo.equilibrium; angle = all_tubes[i].servo.equilibrium;
} }
Serial.printf("%d - %d = %d => %d\n", all_tubes[i].height, all_tubes[i].target, diff, angle); //Serial.printf("%d - %d = %d => %d\n", all_tubes[i].height, all_tubes[i].target, diff, angle);
all_tubes[i].servo.last_angle = min(max(angle, minServo), maxServo); all_tubes[i].servo.last_angle = min(max(angle, minServo), maxServo);
all_tubes[i].servo.hard.write(all_tubes[i].servo.last_angle); all_tubes[i].servo.hard.write(all_tubes[i].servo.last_angle);
} }
pixels.show();
// Serial.println(); // Serial.println();