Saturday, 18 January 2025

VU3CFC Ham Clock Version 1.0

 

VU3CFC Ham Clock Version 1.0

Introduction

The VU3CFC Ham Clock Version 1.0 is a multi-functional device built using a NodeMCU ESP8266. It integrates weather data, local and UTC time, and environmental readings, displaying them on a 20x4 LCD. This blog will guide you through the hardware connections, required libraries, setup instructions, and the display's functionality.




Hardware Connections

  1. NodeMCU ESP8266:

    • Acts as the main microcontroller to interface with the DHT11 sensor, LCD, and APIs.
  2. DHT11 Sensor:

    • Pin D4 (GPIO2): Data pin connected to NodeMCU for temperature and humidity readings.
    • VCC and GND: Connect to NodeMCU's 3.3V and GND pins, respectively.
  3. 20x4 I2C LCD:

    • Uses an I2C interface, reducing the number of pins required for communication.
    • Connections:
      • SDA: Connect to NodeMCU's D2 (GPIO4).
      • SCL: Connect to NodeMCU's D1 (GPIO5).
      • VCC and GND: Connect to NodeMCU's 3.3V and GND pins.

Libraries to Install

Before uploading the code, ensure the following libraries are installed in the Arduino IDE:

  1. LiquidCrystal_PCF8574
    For interfacing with the 20x4 LCD using the I2C protocol.
    Installation: Go to Tools > Manage Libraries and search for LiquidCrystal_PCF8574.

  2. ESP8266WiFi
    Allows WiFi connectivity on the ESP8266 module.
    Pre-installed with the ESP8266 board package.

  3. WiFiClientSecure
    For secure HTTPS requests to APIs.
    Pre-installed with the ESP8266 board package.

  4. NTPClient
    Fetches the current time from NTP servers.
    Installation: Search for NTPClient in the Library Manager.

  5. DHT
    Reads data from the DHT11 sensor.
    Installation: Search for DHT sensor library by Adafruit.

  6. TimeLib
    Helps in manipulating epoch time.
    Installation: Search for TimeLib.


Setting Up WiFi and API Keys

In the code, update the following placeholders with your specific information:

  1. WiFi Credentials
    Replace the placeholders in the ssid and password variables:

    const char* ssid = "Your_SSID";      // Replace with your WiFi name
    const char* password = "Your_Password"; // Replace with your WiFi password
    
  2. Weather API Key
    Sign up at OpenWeather and get an API key. Replace the key in the following line:

    const String weatherApiPath = "/data/2.5/weather?q=Kalyan,IN&appid=Your_API_Key&units=metric";

What the Display Shows

The 20x4 LCD dynamically updates with the following information:

  1. Line 1: Local Time and Date
    Displays the current time in the local timezone (e.g., LOC-10:45 18/01).

  2. Line 2: UTC Time and Date
    Shows the UTC equivalent of the local time (e.g., UTC-05:15 18/01).

  3. Line 3: Temperature and Humidity
    Retrieves real-time environmental readings from the DHT11 sensor (e.g., TEMP:28C HUM:62%).

  4. Line 4: Weather Condition
    Fetches weather data from the OpenWeather API and displays conditions like Sunny, Cloudy, etc.


How It Works

  1. Setup Phase:
    The device initializes all components, connects to WiFi, and fetches initial data from APIs.

  2. Loop Phase:

    • Continuously updates time using the NTP client.
    • Fetches temperature and humidity from the DHT11 sensor.
    • Periodically queries the weather API for updates.

Conclusion

The VU3CFC Ham Clock Version 1.0 is a versatile device for monitoring time, weather, and environmental conditions. It’s perfect for amateur radio operators and weather enthusiasts alike. By following the steps above, you can easily replicate and customize this project to suit your needs. Happy building!


Code - 

#include <Wire.h>
#include <LiquidCrystal_PCF8574.h> // Compatible with ESP8266
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <DHT.h>
#include <TimeLib.h> // For handling epoch time

#define DHTPIN D4
#define DHTTYPE DHT11

// WiFi credentials
const char* ssid = "Enter SSID";
const char* password = "Password";

// LCD configuration
LiquidCrystal_PCF8574 lcd(0x3F);

// DHT sensor
DHT dht(DHTPIN, DHTTYPE);

// NTP client for local and UTC time
WiFiUDP ntpUDP;
NTPClient localTimeClient(ntpUDP, "pool.ntp.org", 19800, 60000); // UTC+5:30 for Kalyan
NTPClient utcTimeClient(ntpUDP, "pool.ntp.org", 0, 60000);

// HamQSL API configuration
const char* hamqslUrl = "https://www.hamqsl.com/solarxml.php";

// Weather API configuration
const char* weatherApiHost = "api.openweathermap.org";
const String weatherApiPath = "/data/2.5/weather?q=Kalyan,IN&appid=806a74b5cdc039b3cbb7e9bbb8b8d82a&units=metric";

unsigned long lastUpdateTime = 0;
const unsigned long updateInterval = 15 * 60 * 1000; // 15 minutes

String solarFlux = "";
String kIndex = "";
String bandConditions[3] = {"", "", ""};
String weatherCondition = "Weather Unavailable";

void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);

  // Initialize DHT sensor
  dht.begin();

  // Initialize LCD
  lcd.begin(20, 4);
  lcd.setBacklight(255);
  lcd.setCursor(0, 0);
  lcd.print("Connecting WiFi");

  // Connect to WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    lcd.print(".");
  }
  lcd.clear();
  lcd.print("WiFi Connected");
  delay(2000);

  // Initialize NTP clients
  localTimeClient.begin();
  utcTimeClient.begin();

  // Fetch initial data
  fetchBandConditions();
  fetchWeatherData();
}

void loop() {
  // Update time
  localTimeClient.update();
  utcTimeClient.update();

  // Read temperature and humidity
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();

  // Calculate date and time from epoch
  time_t localTime = localTimeClient.getEpochTime();
  time_t utcTime = utcTimeClient.getEpochTime();

  int localYear = year(localTime);
  int localMonth = month(localTime);
  int localDay = day(localTime);

  int localHour = hour(localTime);
  int localMinute = minute(localTime);

  int utcYear = year(utcTime);
  int utcMonth = month(utcTime);
  int utcDay = day(utcTime);

  int utcHour = hour(utcTime);
  int utcMinute = minute(utcTime);

  // Update band conditions and weather data every 15 minutes
  if (millis() - lastUpdateTime > updateInterval) {
    fetchBandConditions();
    fetchWeatherData();
    lastUpdateTime = millis();
  }

  // Display data on LCD
  lcd.setCursor(0, 0);
  lcd.printf("LOC-%02d:%02d     %02d/%02d", localHour, localMinute, localDay, localMonth);

  lcd.setCursor(0, 1);
  lcd.printf("UTC-%02d:%02d     %02d/%02d", utcHour, utcMinute, utcDay, utcMonth);

  lcd.setCursor(0, 2);
  lcd.printf("TEMP:%.0fC HUM:%.0f%%", temperature, humidity);

  lcd.setCursor(0, 3);
  lcd.print("WEATHER-" + weatherCondition);

  delay(1000); // Update display every second
}

void fetchBandConditions() {
  WiFiClientSecure client;
  client.setInsecure(); // Allow insecure connections for HTTPS

  if (client.connect("www.hamqsl.com", 443)) {
    client.println("GET /solarxml.php HTTP/1.1");
    client.println("Host: www.hamqsl.com");
    client.println("Connection: close");
    client.println();

    String response = "";
    while (client.connected() || client.available()) {
      if (client.available()) {
        response += client.readString();
      }
    }
    client.stop();

    Serial.println("Full XML Response:");
    Serial.println(response);

    parseBandConditions(response);
  } else {
    Serial.println("Connection to hamqsl.com failed");
  }
}

void parseBandConditions(String xml) {
  int sIndex = xml.indexOf("<solarflux>");
  if (sIndex != -1) {
    solarFlux = xml.substring(sIndex + 11, xml.indexOf("</solarflux>", sIndex));
  } else {
    solarFlux = "N/A";
  }

  int kIndexPos = xml.indexOf("<kindex>");
  if (kIndexPos != -1) {
    kIndex = xml.substring(kIndexPos + 8, xml.indexOf("</kindex>", kIndexPos));
  } else {
    kIndex = "N/A";
  }

  String bands[] = {"20m", "40m", "80m"};
  for (int i = 0; i < 3; i++) {
    int bIndex = xml.indexOf("<band_" + bands[i] + ">");
    if (bIndex != -1) {
      bandConditions[i] = xml.substring(bIndex + 7 + bands[i].length(), xml.indexOf("</band_" + bands[i] + ">", bIndex)).substring(0, 1);
    } else {
      bandConditions[i] = "U"; // Unavailable
    }
  }
}

void fetchWeatherData() {
  WiFiClientSecure client;
  client.setInsecure(); // Allow insecure connections for HTTPS

  if (client.connect(weatherApiHost, 443)) {
    client.println("GET " + weatherApiPath + " HTTP/1.1");
    client.println("Host: " + String(weatherApiHost));
    client.println("Connection: close");
    client.println();

    String response = "";
    while (client.connected() || client.available()) {
      if (client.available()) {
        response += client.readString();
      }
    }
    client.stop();

    Serial.println("Weather API Response:");
    Serial.println(response);

    parseWeatherData(response);
  } else {
    Serial.println("Connection to Weather API failed");
  }
}

void parseWeatherData(String json) {
  int descIndex = json.indexOf("\"description\":");

  if (descIndex != -1) {
    weatherCondition = json.substring(descIndex + 15, json.indexOf("\"", descIndex + 15));
  } else {
    weatherCondition = "Unavailable";
  }
}





No comments:

Post a Comment

VU3CFC Ham Clock Version 1.0

  VU3CFC Ham Clock Version 1.0 Introduction The VU3CFC Ham Clock Version 1.0 is a multi-functional device built using a NodeMCU ESP8266. ...