#include #include #include "Adafruit_VL53L0X.h" #include "PCF8574.h" #include #include #include struct pin { int id; int is_extender; }; struct tube { float height; float target; struct { Servo hard; struct pin pin; int last_angle; int equilibrium; } servo; struct { Adafruit_VL53L0X hard; struct pin gpio; struct pin xshut; } tof; int id; }; const int minHeight = 50; const int maxHeight = 445; int minServo = 0; int maxServo = 180; // Replace with your network credentials const char* ssid = "ESP_ping"; const char* password = "pong"; const char* PARAM_INPUT_1 = "output"; const char* PARAM_INPUT_2 = "state"; // Create AsyncWebServer object on port 80 AsyncWebServer server(80); const char index_html[] PROGMEM = R"rawliteral( ESP Web Server

ESP Web Server

%BUTTONPLACEHOLDER% )rawliteral"; // Replaces placeholder with button section in your web page String processor(const String& var){ //Serial.println(var); if(var == "BUTTONPLACEHOLDER"){ String buttons = ""; buttons += "
"; buttons += "
"; buttons += "
"; buttons += "
"; buttons += "
"; return buttons; } return String(); } auto mesureHeight(Adafruit_VL53L0X lox){ VL53L0X_RangingMeasurementData_t measure; lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout! if (measure.RangeStatus != 4) { // phase failures have incorrect data float height = measure.RangeMilliMeter; if (height < 1000){ curHeight = height; return height; } else { Serial.println("Incoherent measurement. Returning previous one."); return curHeight; } } else { Serial.println(" out of range "); return curHeight; } } int requestedValue = 250; void wifisetup() { Serial.print("Setting AP (Access Point)…"); WiFi.softAP(ssid); IPAddress IP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(IP); // Route for root / web page server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/html", index_html, processor); }); // Send a GET request to /update?output=&state= server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) { String inputMessage1; String inputMessage2; // GET input1 value on /update?output=&state= if (request->hasParam(PARAM_INPUT_1) && request->hasParam(PARAM_INPUT_2)) { inputMessage1 = request->getParam(PARAM_INPUT_1)->value(); inputMessage2 = request->getParam(PARAM_INPUT_2)->value(); requestedValue = inputMessage2.toInt(); } else { inputMessage1 = "No message sent"; inputMessage2 = "No message sent"; } Serial.print("GPIO: "); Serial.print(inputMessage1); Serial.print(" - Set to: "); Serial.println(inputMessage2); request->send(200, "text/plain", "OK"); }); // Start server server.begin(); } PCF8574 pcf8574(0x20); void change_pin(struct pin pin, int state) { if (pin.is_extender) { pcf8574.digitalWrite(pin, state); } else { digitalWrite(pin, state); } } struct tube all_tubes[6] = {0}; Adafruit_VL53L0X tofs_talk_through[6] = {Adafruit_VL53L0X(), Adafruit_VL53L0X(), Adafruit_VL53L0X(), Adafruit_VL53L0X(), Adafruit_VL53L0X(), Adafruit_VL53L0X()}; void init_tube(struct tube *tube, char id, struct pin servo_pin, struct pin gpio, struct pin xshut) { Serial.print(" Initialiazing tube #"); Serial.println(id); tube->id = id; tube->servo.pin = servo_pin; tube->tof.gpio = gpio; tube->tof.xshut = xshut; tube->height = 250.0; tube->target = 250.0; change_pin(xshut, HIGH); if (!tofs_talk_through[id].begin(0x30 + id)) { Serial.println(F("Failed to boot VL53L0X")); while(1); } tube->servo.hard.attach(tube->servo.pin); tube->servo.hard.write(minServo); delay(5000); Serial.println("Setuping downards"); float h = mesureHeight(tofs_talk_through[id]); int angle = minServo; while (h > maxHeight) { ++angle; tube->servo.hard.write(angle); delay(100); h = mesureHeight(tofs_talk_through[id]); } angle -= 2; tube->servo.hard.write(angle); tube->servo.equilibrium = angle; Serial.println("Done."); } const int ACTIVES = 1; void setup_all_tubes() { const int all_xshuts[6] = { {.id = 17, .is_extender = 0}, {.id = P2, .is_extender = 1}, {.id = P3, .is_extender = 1}, {.id = P5, .is_extender = 1}, {.id = P7, .is_extender = 1}, {.id = P1, .is_extender = 1} }; const int all_gpios[6] = { {.id = 5, .is_extender = 0}, {.id = 18, .is_extender = 0}, {.id = 19, .is_extender = 0}, {.id = P4, .is_extender = 1}, {.id = P6, .is_extender = 1}, {.id = P0, .is_extender = 1} }; const int all_servos[6] = { {.id = 32, .is_extender = 0}, {.id = 33, .is_extender = 0}, {.id = 23, .is_extender = 0}, {.id = 16, .is_extender = 0}, {.id = 14, .is_extender = 0}, {.id = 2, .is_extender = 0} }; for (int i = 0; i < ACTIVES; ++i) { change_pin(all_xshuts[i], LOW); } delay(10); for (int i = 0; i < ACTIVES; ++i) { change_pin(all_xshuts[i], HIGH); } delay(10); for (int i = 0; i < ACTIVES; ++i) { change_pin(all_xshuts[i], LOW); } for (int i = 0; i < ACTIVES; ++i) { init_tube(all_tubes, i, all_servos[i], all_gpios[i], all_xshuts[i]); } } void setup() { Serial.begin(115200); // Starts the serial communication while (! Serial) { delay(1); } Wire.begin(); pcf8574.begin(); wifisetup(); setup_all_tubes(); Serial.println("Done setuping have funning"); } auto heightRatio(float height){ return max(min(1.0f, (height - minHeight) / (maxHeight-minHeight)), 0.0f); } int servoPosition(float ratio){ return (ratio * maxServo) + ((1-ratio) * minServo); } void loop() { for (int i = 0; i < ACTIVES; i++) { struct tube tube = all_tubes[i]; tube.height = mesureHeight(tofs_talk_through[tube.id]); Serial.print("Measure = "); Serial.println(tube.height); int angle = 0; float diff = tube.height - tube.target; if (abs(diff) > 5.0f) { Serial.println("HEYEYEYEYEYEYEY"); angle = tube.servo.equilibrium + (diff * 1 / (7)); } else if (abs(diff) > 2.0f) { angle = tube.servo.equilibrium + (diff * 1 / (7)); } else { error = 0; angle = tube.servo.equilibrium; } Serial.print("angle = "); Serial.print(angle); Serial.print("; equilibrium = "); Serial.println(tube.servo.equilibrium); tube.servo.last_angle = angle; tube.servo.hard.write(min(max(angle, minServo), maxServo)); } delay(1); }