IOT Weather Station With Google Chrome

by WombaticsCo in Circuits > Arduino

50 Views, 0 Favorites, 0 Comments

IOT Weather Station With Google Chrome

Weather Station Power On.jpg
html UI.png
Thingspeak IOT.png

This project demonstrates how to use an SAM01 Arduino Nano board without WiFi to communicate with Google Chrome through the Serial Port API. The data collected from sensors (like temperature and humidity) is sent to an IoT platform such as ThingSpeak for visualization and analysis. Additionally, a Traffic Light LED Board displays the comfort level in real time using red, yellow, and green LEDs.

Supplies

Weather Station Parts.jpg
  1. SAM01 Arduino Nano Board or Similar
  2. DHT11 temperature and humidity sensor
  3. Traffic Light LED Board (with Red, Yellow, and Green LEDs)
  4. Jumper wires
  5. USB cable to connect Arduino to a PC
  6. A PC with Google Chrome browser installed
  7. ThingSpeak account (free account is sufficient)

Features

  1. Read temperature, humidity, and calculate a 10-level comfort score.
  2. Display comfort levels using a Traffic Light LED Board:
  3. Red LED: Low comfort level (1–3).
  4. Yellow LED: Medium comfort level (4–7).
  5. Green LED: High comfort level (8–10).
  6. Visualise real-time sensor data on a browser-based dashboard.
  7. Send data to ThingSpeak for IoT data logging and visualisation.

Circuit Diagram

Screenshot 2024-11-15 at 22.56.05.png

Build the circuit as shown below:

  1. Connect the DHT sensor to the Arduino:
  2. VCC to 5V
  3. GND to GND
  4. DATA to Pin 8
  5. Connect the Traffic Light LED Board:
  6. Red LED to Pin 3
  7. Yellow LED to Pin 4
  8. Green LED to Pin 5

Arduino Code

Upload the following code to your Arduino. It reads temperature, humidity, and calculates a 10-level comfort score. The comfort level is displayed using the Traffic Light LED Board, and data is sent to the serial port in a format that can be read by the browser.


#include <DHT.h>

#define DHTPIN 8 // DHT sensor connected to pin 8
#define DHTTYPE DHT11 // Define your DHT sensor type (DHT11, DHT22, etc.)
#define RED_LED 3 // Red LED connected to pin 3
#define YELLOW_LED 4
#define GREEN_LED 5

DHT dht(DHTPIN, DHTTYPE);

void setup() {
Serial.begin(9600);
dht.begin();

// Set LED pins as output
pinMode(RED_LED, OUTPUT);
pinMode(YELLOW_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
}

void loop() {
// Reading temperature and humidity from the DHT sensor
float humidity;
float temperature;
int comfortLevel;

humidity = dht.readHumidity();
temperature = dht.readTemperature();

// Determine comfort level
comfortLevel = calculateComfortLevel(temperature, humidity);
// Print readings in the specified format for HTML parsing
Serial.print("Temp: ");
Serial.print(temperature);
Serial.print(" Hum: ");
Serial.print(humidity);
Serial.print(" Comfort Level: ");
Serial.println(comfortLevel);

// Control LEDs based on comfort level
if(comfortLevel <= 3 )
{
digitalWrite(RED_LED, HIGH);
digitalWrite(YELLOW_LED, LOW);
digitalWrite(GREEN_LED, LOW);
}
else if (comfortLevel <= 7)
{
digitalWrite(RED_LED, LOW);
digitalWrite(YELLOW_LED, HIGH);
digitalWrite(GREEN_LED, LOW);
}
else
{
digitalWrite(RED_LED, LOW);
digitalWrite(YELLOW_LED, LOW);
digitalWrite(GREEN_LED, HIGH);
}
delay(2000); // Wait for 2 seconds before next reading
}

// Function to calculate the comfort level based on temperature and humidity
int calculateComfortLevel(float temperature, float humidity) {
if (temperature < 15 || temperature > 35 || humidity < 20 || humidity > 80) {
return 1; // Extremely uncomfortable
} else if ((temperature < 16 || temperature > 34) || (humidity < 25 || humidity > 75)) {
return 2; // Very uncomfortable
} else if ((temperature < 17 || temperature > 33) || (humidity < 30 || humidity > 70)) {
return 3; // Uncomfortable
} else if ((temperature < 18 || temperature > 32) || (humidity < 35 || humidity > 65)) {
return 4; // Slightly uncomfortable
} else if ((temperature < 19 || temperature > 31) || (humidity < 38 || humidity > 62)) {
return 5; // Neutral
} else if ((temperature >= 19 && temperature <= 31) && (humidity >= 40 && humidity <= 60)) {
return 6; // Slightly comfortable
} else if ((temperature >= 20 && temperature <= 30) && (humidity >= 42 && humidity <= 58)) {
return 7; // Comfortable
} else if ((temperature >= 21 && temperature <= 29) && (humidity >= 45 && humidity <= 55)) {
return 8; // Very comfortable
} else if ((temperature >= 22 && temperature <= 28) && (humidity >= 48 && humidity <= 52)) {
return 9; // Optimal comfort
} else if (temperature == 25 && humidity == 50) {
return 10; // Perfect conditions
}
return 5; // Default neutral
}


Downloads

Create a ThingSpeak Account

Screenshot 2024-11-15 at 22.17.12.png
Screenshot 2024-11-15 at 22.17.35.png

Sign up a ThingSpeak Account

  1. Visit ThingSpeak.
  2. Click on "Sign Up" at the top-right corner of the page.
  3. Fill out the registration form with your details (email address, password, etc.).
  4. Verify your email address by following the link sent to your inbox.
  5. Log in to your account.

Set Up a ThingSpeak Channel

  1. Once logged in, click on "Channels" in the top menu and select "My Channels".
  2. Click the "New Channel" button.
  3. Fill in the required details:
  4. Name: Give your channel a meaningful name (e.g., "Arduino Environment Monitor").
  5. Fields: Add three fields:
  6. Field 1: Temperature
  7. Field 2: Humidity
  8. Field 3: Comfort Level
  9. Click "Save Channel".

Get Your API Key

  1. Open your newly created channel and navigate to the API Keys tab.
  2. Copy the Write API Key provided. You'll use this key in the HTML file to send data to ThingSpeak.


HTML Dashboard

Create an HTML file to communicate with the Arduino via the Serial Port API and send the temperature, humidity, and comfort level to ThingSpeak.

  1. Copy and paste the code below into a text editor.
  2. Save it as dht_weather_station.html
  3. Replace the "const apiKey =" with your ThingSpeak Channel API Key


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Arduino Temperature and Humidity Monitor</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; }
h1 { color: #333; }
.data { font-size: 1.2em; margin-top: 20px; }
.comfort-status { font-weight: bold; color: red; }
#frame {
margin-top: 20px;
padding: 10px;
border: 1px solid #ddd;
background-color: #f9f9f9;
font-family: monospace;
color: #444;
max-height: 200px;
overflow-y: auto;
}
</style>
</head>
<body>
<h1>Arduino Temperature and Humidity Monitor</h1>
<button id="connectButton">Connect to Arduino</button>
<div class="data">
<p>Temperature: <span id="temperature">--</span> °C</p>
<p>Humidity: <span id="humidity">--</span> %</p>
<p>Comfort Level: <span id="comfortLevel" class="comfort-status">--</span></p>
</div>
<div id="frame">
<h3>Raw Data from Serial Port:</h3>
<div id="rawData"></div>
</div>

<script>
let port;
let reader;
let keepReading = false;

// Connect Button
document.getElementById("connectButton").addEventListener("click", async () => {
try {
// Request a serial port and open a connection
port = await navigator.serial.requestPort();
await port.open({ baudRate: 9600 });

// Disable the connect button
document.getElementById("connectButton").disabled = true;

// Start reading data from the serial port
keepReading = true;
readData();
} catch (error) {
console.error("Error connecting to serial port:", error);
}
});

// Automatically close the serial port when the window is closed or refreshed
window.addEventListener("beforeunload", async () => {
if (port) {
keepReading = false;

// Cancel and release the reader if it exists
if (reader) {
await reader.cancel();
reader.releaseLock();
}

// Close the port
await port.close();
console.log("Serial port closed.");
}
});

async function readData() {
const textDecoder = new TextDecoderStream();
port.readable.pipeTo(textDecoder.writable);
reader = textDecoder.readable.getReader();

let buffer = ''; // Buffer to store incoming data

try {
while (keepReading) {
const { value, done } = await reader.read();
if (done) {
console.log("Stream closed");
break;
}
if (value) {
// Accumulate data in buffer
buffer += value;

// Check if buffer contains a full line (newline character)
let lines = buffer.split('\n');
buffer = lines.pop(); // Keep the last partial line in the buffer

// Process each complete line
for (let line of lines) {
displayRawData(line.trim());
parseData(line.trim());
}
}
}
} catch (error) {
if (error.name !== "CanceledError") {
console.error("Error reading data:", error);
}
} finally {
reader.releaseLock();
}
}

function displayRawData(data) {
const rawDataDiv = document.getElementById("rawData");
// Append the data with an HTML line break for proper new line display
rawDataDiv.innerHTML += data + "<br>";
rawDataDiv.scrollTop = rawDataDiv.scrollHeight; // Scroll to the bottom to show the latest data
}

function parseData(data) {
console.log("Received data:", data); // Debugging: log raw data

// Try matching temperature, humidity, and comfort level
const tempMatch = data.match(/Temp:\s*(-?\d+(\.\d+)?)/);
const humMatch = data.match(/Hum:\s*(\d+(\.\d+)?)/);
const comfortMatch = data.match(/Comfort Level:\s*(\d+)/);

if (tempMatch && humMatch && comfortMatch) {
const temperature = tempMatch[1];
const humidity = humMatch[1];
const comfortLevel = parseInt(comfortMatch[1]);

console.log("Parsed Temperature:", temperature);
console.log("Parsed Humidity:", humidity);
console.log("Parsed Comfort Level:", comfortLevel);

// Update the HTML elements with the parsed data
document.getElementById("temperature").textContent = temperature;
document.getElementById("humidity").textContent = humidity;
document.getElementById("comfortLevel").textContent = comfortLevel;

// Set the comfort level color
const comfortLevelElement = document.getElementById("comfortLevel");
if (comfortLevel <= 3) {
comfortLevelElement.style.color = "red"; // Low comfort
} else if (comfortLevel <= 7) {
comfortLevelElement.style.color = "orange"; // Medium comfort
} else {
comfortLevelElement.style.color = "green"; // High comfort
}


// Send data to ThingSpeak
sendToThingSpeak(temperature, humidity, comfortLevel);
} else {
console.warn("Data format did not match expected pattern.");
}
}

function sendToThingSpeak(temperature, humidity, comfortLevel) {
const apiKey = "LHCU6IB02EH0RAKC"; // Replace with your ThingSpeak API key
const url = `https://api.thingspeak.com/update?api_key=${apiKey}&field1=${temperature}&field2=${humidity}&field3=${comfortLevel}`;


fetch(url)
.then(response => {
if (response.ok) {
console.log("Data sent to ThingSpeak successfully");
} else {
console.error("Failed to send data to ThingSpeak");
}
})
.catch(error => {
console.error("Error:", error);
});
}
</script>
</body>
</html>

Test and Run

html UI.png
Thingspeak IOT.png

Connect the Arduino to your PC via USB.

Open dht_weather_station.html in Google Chrome.

Click "Connect to Arduino" and select your serial port.

Observe:

  1. Temperature, humidity, and comfort level displayed on the webpage.
  2. The Traffic Light LED Board indicating the comfort level.
  3. Data sent to ThingSpeak for real-time logging and visualisation.


Conclusion

This project showcases how to bridge the gap between an Arduino without WiFi and IoT platforms like ThingSpeak using the Google Chrome Serial Port API. With visual indicators from the Traffic Light LED Board, users can easily monitor environmental comfort levels.

Let me know if you need further refinements!