The task for the ninth week is to control a circuit using wireless network and fetching data from the Internet.
I will do something for my final project. I already bought ESP32 Cam and made it work. Now, I want to control the motor in the Turntable using the camera's webserver. Additionally, I want to turn on a IR LED lamp during night time. I do not have the LED lamp yet, so I will simulate with normal red LED.
First, I renamed the config file to myconfig.h and saved my Wi-fi SSID and password there. Then, I add these parts of code to index_OV2640.h file to create new control slider.
<div class="input-group" id="turn-group" title="Turning the table">
<label for="turn">Turn</label>
<div class="range-min">-180</div>
<input type="range" id="turn" min="-180" max="180" value="0" class="default-action">
<div class="range-max">180</div>
</div>
/*
...
*/
const turnGroup = document.getElementById('turn-group')
I defined my stepper motor in app_httpd.cpp and created the turning logic.
//Includes the Arduino Stepper Library
#include <Stepper.h>
// Defines the number of steps per rotation
const int stepsPerRevolution = 2038;
// Creates an instance of stepper class
// Pins entered in sequence IN1-IN3-IN2-IN4 for proper step sequence
Stepper myStepper = Stepper(stepsPerRevolution, 2, 15, 14, 13);
/*
...
*/
int turnDegree;
/*
...
*/
static esp_err_t cmd_handler(httpd_req_t *req){
...
else if (!strcmp(variable, "turn")) {
int diff = val - turnDegree;
int steps = 2 * diff * (stepsPerRevolution / 360); // 2:1 gear ration
// Rotate fast at 10 RPM
myStepper.setSpeed(10);
myStepper.step(steps);
turnDegree = val;
}
And finally, I edited esp32-cam-webserver and implemented fetching weather data from OpenWeather. I am particulary interested in sunrise and sunset. The LED should turn on 30 minutes after sunset and turn off 30 minutes before sunrise. It checks every 15 minutes. Also current temperature is printed.
#include <HTTPClient.h>
#include <ArduinoJson.h> // Install from Library Manager
const String apiKey = "1008dca4dd348ba868f400b270b8766f";
const String lat = "50.09";
const String lon = "14.42";
String weatherURL = "https://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon=" + lon + "&appid=" + apiKey + "&units=metric";
// Timezone offset in seconds (e.g., +2 hours = 7200)
const int timezoneOffset = 2 * 3600;
unsigned long lastUpdate = 0;
const unsigned long updateInterval = 15UL * 60UL * 1000UL; // 15 minutes in ms
// LED pin
const int ledIRPin = 12;
/*
...
*/
void printTime(const String& label, time_t rawTime) {
struct tm * timeinfo = localtime(&rawTime);
Serial.print(label);
Serial.print(": ");
Serial.print(asctime(timeinfo));
}
void fetchWeatherData() {
HTTPClient http;
http.begin(weatherURL);
int httpCode = http.GET();
if (httpCode > 0) {
String payload = http.getString();
DynamicJsonDocument doc(2048);
deserializeJson(doc, payload);
float temperature = doc["main"]["temp"];
time_t sunrise = doc["sys"]["sunrise"];
time_t sunset = doc["sys"]["sunset"];
time_t current = doc["dt"];
// Convert to local time
sunrise += timezoneOffset;
sunset += timezoneOffset;
current += timezoneOffset;
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" °C");
printTime("Current", current);
printTime("Sunrise", sunrise);
printTime("Sunset", sunset);
// Light control logic
if (current >= (sunset + 1800)) {
digitalWrite(ledIRPin, HIGH); // Turn on LED after 30 mins past sunset
Serial.println("LED ON (it's dark)");
} else if (current >= (sunrise - 1800) && current < sunrise) {
digitalWrite(ledIRPin, LOW); // Turn off LED 30 mins before sunrise
Serial.println("LED OFF (light is coming soon)");
}
} else {
Serial.print("HTTP error: ");
Serial.println(httpCode);
}
http.end();
}
void setup() {
// Set LED
pinMode(ledIRPin, OUTPUT);
digitalWrite(ledIRPin, LOW);
/*
...
*/
void loop() {
/*
* Just loop forever, reconnecting Wifi As necesscary in client mode
* The stream and URI handler processes initiated by the startCameraServer() call at the
* end of setup() will handle the camera and UI processing from now on.
*/
// fetching weather and operating LED
unsigned long now = millis();
// Only fetch every 15 minutes
if (now - lastUpdate >= updateInterval || lastUpdate == 0) {
fetchWeatherData();
lastUpdate = now;
}