Not a member of gistpad yet?
Sign Up,
it unlocks many cool features!
- #include <WiFi.h>
- #include <WebServer.h>
- #include <HTTPClient.h>
- #include <LiquidCrystal_I2C.h>
- // ==========================================
- // 1. CONFIGURATION
- // ==========================================
- const char* ssid = "css_STEAM";
- const char* password = ""; // Update this!
- // Pins
- #define I2C_SDA 7
- #define I2C_SCL 8
- #define SERVO_PIN 22
- // Servo Settings (ESP32 v3.0+)
- #define PWM_FREQ 50
- #define PWM_RES 16
- #define MIN_DUTY 1638 // 0 degrees
- #define MAX_DUTY 8191 // 180 degrees
- // Weather API (Hong Kong Coordinates)
- const String weatherURL = "https://api.open-meteo.com/v1/forecast?latitude=22.31&longitude=114.16¤t_weather=true";
- // Objects
- LiquidCrystal_I2C lcd(0x27, 16, 2);
- WebServer server(80);
- // Global Variables
- float currentTemp = 0.0;
- String ipAddress = "0.0.0.0";
- // ==========================================
- // 2. HELPER FUNCTIONS
- // ==========================================
- // Move Servo to specific angle
- void setServo(int angle) {
- angle = constrain(angle, 0, 180);
- uint32_t duty = map(angle, 0, 180, MIN_DUTY, MAX_DUTY);
- ledcWrite(SERVO_PIN, duty);
- }
- // Fetch Weather from Open-Meteo
- void updateWeather() {
- HTTPClient http;
- http.begin(weatherURL);
- int httpCode = http.GET();
- if (httpCode == 200) {
- String payload = http.getString();
- // Manual String Parsing (Simpler than installing ArduinoJson)
- // We look for "temperature":
- int tempIndex = payload.indexOf("\"temperature\":");
- if (tempIndex > 0) {
- int startIndex = tempIndex + 14;
- int endIndex = payload.indexOf(",", startIndex);
- String tempString = payload.substring(startIndex, endIndex);
- currentTemp = tempString.toFloat();
- Serial.println("Weather Updated: " + String(currentTemp) + "C");
- }
- } else {
- Serial.println("Weather Error: " + String(httpCode));
- }
- http.end();
- }
- // Scroll Text on LCD Line 1 (Line 0 is top, Line 1 is bottom)
- void scrollText(String message, int row, int delayTime) {
- for (int i = 0; i < message.length() - 15; i++) {
- lcd.setCursor(0, row);
- lcd.print(message.substring(i, i + 16));
- delay(delayTime);
- }
- }
- // ==========================================
- // 3. WEB HANDLERS
- // ==========================================
- // ROOT PAGE: The HTML Dashboard
- void handleRoot() {
- String html = "<!DOCTYPE html><html><head><meta name='viewport' content='width=device-width, initial-scale=1'>";
- html += "<style>body{font-family:sans-serif;text-align:center;margin-top:50px;}";
- html += "button{padding:15px 30px;font-size:20px;margin:10px;border-radius:10px;border:none;background:#007BFF;color:white;}";
- html += "button:active{background:#0056b3;}</style></head><body>";
- html += "<h1>ESP32 Control</h1>";
- html += "<p>Current HK Temp: <b>" + String(currentTemp) + "°C</b></p>";
- html += "<a href='/set?angle=0'><button>0°</button></a>";
- html += "<a href='/set?angle=90'><button>90°</button></a>";
- html += "<a href='/set?angle=180'><button>180°</button></a><br>";
- html += "<a href='/swing'><button style='background:#28a745'>SWING!</button></a>";
- html += "</body></html>";
- server.send(200, "text/html", html);
- }
- // API: Set Angle (Usage: /set?angle=45)
- void handleSetAngle() {
- if (server.hasArg("angle")) {
- int angle = server.arg("angle").toInt();
- setServo(angle);
- server.send(200, "text/plain", "OK: Angle set to " + String(angle));
- Serial.println("API Request: Set Angle " + String(angle));
- } else {
- server.send(400, "text/plain", "Error: Missing 'angle' parameter");
- }
- }
- // API: Swing (Usage: /swing)
- void handleSwing() {
- server.send(200, "text/plain", "OK: Swinging...");
- Serial.println("API Request: Swinging");
- // Simple swing animation
- for(int i=0; i<=180; i+=5) { setServo(i); delay(15); }
- for(int i=180; i>=0; i-=5) { setServo(i); delay(15); }
- setServo(90); // Return to center
- }
- // ==========================================
- // 4. MAIN SETUP
- // ==========================================
- void setup() {
- Serial.begin(115200);
- // 1. Setup LCD
- Wire.begin(I2C_SDA, I2C_SCL);
- lcd.init();
- lcd.backlight();
- lcd.setCursor(0, 0);
- lcd.print("System Booting..");
- // 2. Setup Servo
- if (!ledcAttach(SERVO_PIN, PWM_FREQ, PWM_RES)) {
- Serial.println("Servo Attach Failed");
- }
- setServo(0); // Start at 0
- // 3. Connect to WiFi
- WiFi.begin(ssid, password);
- lcd.setCursor(0, 1);
- lcd.print("Connecting WiFi ");
- int dots = 0;
- while (WiFi.status() != WL_CONNECTED) {
- delay(500);
- Serial.print(".");
- lcd.print(".");
- dots++;
- if (dots > 5) {
- dots = 0;
- lcd.setCursor(15, 1);
- lcd.print(" "); // Clear dots
- lcd.setCursor(15, 1);
- }
- // If it takes too long (> 20 seconds), scroll error
- if (millis() > 20000 && WiFi.status() != WL_CONNECTED) {
- lcd.clear();
- lcd.print("WiFi Error!");
- scrollText("Check SSID/Password... Retrying... ", 1, 300);
- }
- }
- // 4. Connection Success
- ipAddress = WiFi.localIP().toString();
- Serial.println("\nWiFi Connected! IP: " + ipAddress);
- // 5. Initial Weather Fetch
- updateWeather();
- // 6. Update LCD with Info
- lcd.clear();
- lcd.setCursor(0, 0);
- lcd.print("IP:");
- lcd.print(ipAddress);
- lcd.setCursor(0, 1);
- lcd.print("HK:");
- lcd.print(currentTemp, 1); // 1 decimal place
- lcd.print("C Running");
- // 7. Start Web Server
- server.on("/", handleRoot);
- server.on("/set", handleSetAngle);
- server.on("/swing", handleSwing);
- server.begin();
- }
- void loop() {
- server.handleClient();
- // Optional: Refresh weather every 10 minutes
- static unsigned long lastWeatherTime = 0;
- if (millis() - lastWeatherTime > 600000) {
- updateWeather();
- lcd.setCursor(0, 1);
- lcd.print("HK:");
- lcd.print(currentTemp, 1);
- lcd.print("C ");
- lastWeatherTime = millis();
- }
- }
RAW Gist Data
Copied
