Guest

ESP32 Sample

Dec 12th, 2025
18
0
Never
Not a member of gistpad yet? Sign Up, it unlocks many cool features!
Python 34.91 KB | Source Code | 0 0
  1. #include <WiFi.h>
  2. #include <WebServer.h>
  3. #include <HTTPClient.h>
  4. #include <LiquidCrystal_I2C.h>
  5.  
  6. // ==========================================
  7. // 1. CONFIGURATION
  8. // ==========================================
  9. const char* ssid = "css_STEAM";
  10. const char* password = ""; // Update this!
  11.  
  12. // Pins
  13. #define I2C_SDA 7
  14. #define I2C_SCL 8
  15. #define SERVO_PIN 22
  16.  
  17. // Servo Settings (ESP32 v3.0+)
  18. #define PWM_FREQ 50
  19. #define PWM_RES 16
  20. #define MIN_DUTY 1638 // 0 degrees
  21. #define MAX_DUTY 8191 // 180 degrees
  22.  
  23. // Weather API (Hong Kong Coordinates)
  24. const String weatherURL = "https://api.open-meteo.com/v1/forecast?latitude=22.31&longitude=114.16&current_weather=true";
  25.  
  26. // Objects
  27. LiquidCrystal_I2C lcd(0x27, 16, 2);
  28. WebServer server(80);
  29.  
  30. // Global Variables
  31. float currentTemp = 0.0;
  32. String ipAddress = "0.0.0.0";
  33.  
  34. // ==========================================
  35. // 2. HELPER FUNCTIONS
  36. // ==========================================
  37.  
  38. // Move Servo to specific angle
  39. void setServo(int angle) {
  40. angle = constrain(angle, 0, 180);
  41. uint32_t duty = map(angle, 0, 180, MIN_DUTY, MAX_DUTY);
  42. ledcWrite(SERVO_PIN, duty);
  43. }
  44.  
  45. // Fetch Weather from Open-Meteo
  46. void updateWeather() {
  47. HTTPClient http;
  48. http.begin(weatherURL);
  49.  
  50. int httpCode = http.GET();
  51. if (httpCode == 200) {
  52. String payload = http.getString();
  53.  
  54. // Manual String Parsing (Simpler than installing ArduinoJson)
  55. // We look for "temperature":
  56. int tempIndex = payload.indexOf("\"temperature\":");
  57. if (tempIndex > 0) {
  58. int startIndex = tempIndex + 14;
  59. int endIndex = payload.indexOf(",", startIndex);
  60. String tempString = payload.substring(startIndex, endIndex);
  61. currentTemp = tempString.toFloat();
  62. Serial.println("Weather Updated: " + String(currentTemp) + "C");
  63. }
  64. } else {
  65. Serial.println("Weather Error: " + String(httpCode));
  66. }
  67. http.end();
  68. }
  69.  
  70. // Scroll Text on LCD Line 1 (Line 0 is top, Line 1 is bottom)
  71. void scrollText(String message, int row, int delayTime) {
  72. for (int i = 0; i < message.length() - 15; i++) {
  73. lcd.setCursor(0, row);
  74. lcd.print(message.substring(i, i + 16));
  75. delay(delayTime);
  76. }
  77. }
  78.  
  79. // ==========================================
  80. // 3. WEB HANDLERS
  81. // ==========================================
  82.  
  83. // ROOT PAGE: The HTML Dashboard
  84. void handleRoot() {
  85. String html = "<!DOCTYPE html><html><head><meta name='viewport' content='width=device-width, initial-scale=1'>";
  86. html += "<style>body{font-family:sans-serif;text-align:center;margin-top:50px;}";
  87. html += "button{padding:15px 30px;font-size:20px;margin:10px;border-radius:10px;border:none;background:#007BFF;color:white;}";
  88. html += "button:active{background:#0056b3;}</style></head><body>";
  89.  
  90. html += "<h1>ESP32 Control</h1>";
  91. html += "<p>Current HK Temp: <b>" + String(currentTemp) + "&deg;C</b></p>";
  92.  
  93. html += "<a href='/set?angle=0'><button>0&deg;</button></a>";
  94. html += "<a href='/set?angle=90'><button>90&deg;</button></a>";
  95. html += "<a href='/set?angle=180'><button>180&deg;</button></a><br>";
  96. html += "<a href='/swing'><button style='background:#28a745'>SWING!</button></a>";
  97.  
  98. html += "</body></html>";
  99. server.send(200, "text/html", html);
  100. }
  101.  
  102. // API: Set Angle (Usage: /set?angle=45)
  103. void handleSetAngle() {
  104. if (server.hasArg("angle")) {
  105. int angle = server.arg("angle").toInt();
  106. setServo(angle);
  107. server.send(200, "text/plain", "OK: Angle set to " + String(angle));
  108. Serial.println("API Request: Set Angle " + String(angle));
  109. } else {
  110. server.send(400, "text/plain", "Error: Missing 'angle' parameter");
  111. }
  112. }
  113.  
  114. // API: Swing (Usage: /swing)
  115. void handleSwing() {
  116. server.send(200, "text/plain", "OK: Swinging...");
  117. Serial.println("API Request: Swinging");
  118. // Simple swing animation
  119. for(int i=0; i<=180; i+=5) { setServo(i); delay(15); }
  120. for(int i=180; i>=0; i-=5) { setServo(i); delay(15); }
  121. setServo(90); // Return to center
  122. }
  123.  
  124. // ==========================================
  125. // 4. MAIN SETUP
  126. // ==========================================
  127. void setup() {
  128. Serial.begin(115200);
  129.  
  130. // 1. Setup LCD
  131. Wire.begin(I2C_SDA, I2C_SCL);
  132. lcd.init();
  133. lcd.backlight();
  134. lcd.setCursor(0, 0);
  135. lcd.print("System Booting..");
  136.  
  137. // 2. Setup Servo
  138. if (!ledcAttach(SERVO_PIN, PWM_FREQ, PWM_RES)) {
  139. Serial.println("Servo Attach Failed");
  140. }
  141. setServo(0); // Start at 0
  142.  
  143. // 3. Connect to WiFi
  144. WiFi.begin(ssid, password);
  145. lcd.setCursor(0, 1);
  146. lcd.print("Connecting WiFi ");
  147.  
  148. int dots = 0;
  149. while (WiFi.status() != WL_CONNECTED) {
  150. delay(500);
  151. Serial.print(".");
  152. lcd.print(".");
  153. dots++;
  154. if (dots > 5) {
  155. dots = 0;
  156. lcd.setCursor(15, 1);
  157. lcd.print(" "); // Clear dots
  158. lcd.setCursor(15, 1);
  159. }
  160.  
  161. // If it takes too long (> 20 seconds), scroll error
  162. if (millis() > 20000 && WiFi.status() != WL_CONNECTED) {
  163. lcd.clear();
  164. lcd.print("WiFi Error!");
  165. scrollText("Check SSID/Password... Retrying... ", 1, 300);
  166. }
  167. }
  168.  
  169. // 4. Connection Success
  170. ipAddress = WiFi.localIP().toString();
  171. Serial.println("\nWiFi Connected! IP: " + ipAddress);
  172.  
  173. // 5. Initial Weather Fetch
  174. updateWeather();
  175.  
  176. // 6. Update LCD with Info
  177. lcd.clear();
  178. lcd.setCursor(0, 0);
  179. lcd.print("IP:");
  180. lcd.print(ipAddress);
  181.  
  182. lcd.setCursor(0, 1);
  183. lcd.print("HK:");
  184. lcd.print(currentTemp, 1); // 1 decimal place
  185. lcd.print("C Running");
  186.  
  187. // 7. Start Web Server
  188. server.on("/", handleRoot);
  189. server.on("/set", handleSetAngle);
  190. server.on("/swing", handleSwing);
  191. server.begin();
  192. }
  193.  
  194. void loop() {
  195. server.handleClient();
  196.  
  197. // Optional: Refresh weather every 10 minutes
  198. static unsigned long lastWeatherTime = 0;
  199. if (millis() - lastWeatherTime > 600000) {
  200. updateWeather();
  201. lcd.setCursor(0, 1);
  202. lcd.print("HK:");
  203. lcd.print(currentTemp, 1);
  204. lcd.print("C ");
  205. lastWeatherTime = millis();
  206. }
  207. }
RAW Gist Data Copied