diff --git a/UCPSMain/UCPSMain.ino b/UCPSMain/UCPSMain.ino new file mode 100644 index 0000000..db18bef --- /dev/null +++ b/UCPSMain/UCPSMain.ino @@ -0,0 +1,156 @@ +#include +#include +#include +#include + +// Wifi (Hotspot) +const char wifiSSID[] = "FreeWifi"; +const char wifiPASS[] = "temppassword"; + +// ESP8266 (Wifi module, AT firmware) +SoftwareSerial wifiSerial(2, 3); // RX = 2, TX = 3 +WiFiEspClient client; + +// LCD Display +#define DHT_SENSOR_TYPE DHT_TYPE_11 +static const int DHT_SENSOR_PIN = A1; +DHT_nonblocking dht_sensor(DHT_SENSxOR_PIN, DHT_SENSOR_TYPE); + +LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // RS, EN, D4, D5, D6, D7 + +// Light sensor and LEDs +int lightPin = A0; // LDR +int dataPin = 4; // DS +int latchPin = 5; // ST_CP +int clockPin = 6; // SH_CP +int leds = 0; + +// API +const float NO_TEMP = -999.0; +const unsigned long API_INTERVAL = 600000UL; // 10m +const unsigned long RETRY_INTERVAL = 30000UL; // 30s +unsigned long lastApiFetch = 0; +unsigned long fetchInterval = API_INTERVAL; +float outdoorTemp = NO_TEMP; + +// Connect to hotspot if not connected, then fetch the current temperature +float fetchOutdoorTemp() { + if (WiFi.status() != WL_CONNECTED) { + WiFi.begin(wifiSSID, wifiPASS); + if (WiFi.status() != WL_CONNECTED) return NO_TEMP; + } + + client.setTimeout(5000); + if (!client.connect("api.open-meteo.com", 80)) return NO_TEMP; + + client.print(F("GET /v1/forecast?latitude=49.46998&longitude=8.4819¤t=temperature_2m HTTP/1.1\r\n" + "Host: api.open-meteo.com\r\n" + "Connection: close\r\n" + "\r\n")); + + // Skip ahead to the number in {"current":{..."temperature_2m":12.3}} + float t = NO_TEMP; + if (client.find("\"current\":") && client.find("\"temperature_2m\":")) { + t = client.parseFloat(); + } + client.stop(); + return t; +} + +// Write to LCD display +void lcdLine(uint8_t row, const char *text) { + lcd.setCursor(0, row); + uint8_t i = 0; + for (; text[i] != '\0' && i < 16; i++) lcd.write(text[i]); + for (; i < 16; i++) lcd.write(' '); +} + +// LEDs for light sensor +void updateShiftRegister() { + digitalWrite(latchPin, LOW); + shiftOut(dataPin, clockPin, LSBFIRST, leds); + digitalWrite(latchPin, HIGH); +} + +// Measure temperature and humidity +static bool measure_environment(float *temp, float *hum) { + static unsigned long timestamp = millis(); + + if (millis() - timestamp > 3000ul) { + if (dht_sensor.measure(temp, hum) == true) { + timestamp = millis(); + return true; + } + } + return false; +} + +void setup() { + pinMode(latchPin, OUTPUT); + pinMode(dataPin, OUTPUT); + pinMode(clockPin, OUTPUT); + + Serial.begin(115200); + lcd.begin(16, 2); + lcdLine(0, "Connecting WiFi"); + lcdLine(1, ""); + + wifiSerial.begin(9600); + WiFi.init(&wifiSerial); + + if (WiFi.status() == WL_NO_SHIELD) { + lcdLine(0, "ESP not found"); + delay(2000); + } + + outdoorTemp = fetchOutdoorTemp(); + lastApiFetch = millis(); + fetchInterval = (outdoorTemp == NO_TEMP) ? RETRY_INTERVAL : API_INTERVAL; + lcd.clear(); +} + +void loop() { + float indoorTemp; + float indoorHum; + + if (measure_environment(&indoorTemp, &indoorHum) == true) { + char tempStr[10]; + dtostrf(indoorTemp, 4, 1, tempStr); + char line0[20]; + snprintf(line0, sizeof(line0), "In: %s C", tempStr); + lcdLine(0, line0); + } + + if (millis() - lastApiFetch >= fetchInterval) { + float t = fetchOutdoorTemp(); + lastApiFetch = millis(); + if (t != NO_TEMP) { + outdoorTemp = t; + fetchInterval = API_INTERVAL; + } else { + fetchInterval = RETRY_INTERVAL; + } + } + + if (outdoorTemp != NO_TEMP) { + char outStr[10]; + dtostrf(outdoorTemp, 4, 1, outStr); + char line1[20]; + snprintf(line1, sizeof(line1), "Out: %s C", outStr); + lcdLine(1, line1); + } else { + lcdLine(1, "Out: API Error"); + } + + int reading = analogRead(lightPin); + int numLEDSLit = reading / 57; + + if (numLEDSLit > 8) numLEDSLit = 8; + leds = 0; + for (int i = 0; i < numLEDSLit; i++) { + leds = leds + (1 << i); + } + updateShiftRegister(); + + delay(100); +}