IoT Weather Data capture
I’m using the Arduino R4 Wifi with the DFRobot BME280 sensor.
- The BME280 is an environment sensor collecting temperature, humidity, pressure and altitude.
- The R4 is the WIFI IoT development board in the Arduino suit of boards.
- This allows me to view collected data on (i) the Arduino serial port and (ii) internet browser.
Project Architecture
Phase 1 will be Arduino -> Sensor -> Internet/Network -> Raspberry Pi / Server – PostgreSQL Database
Phase 2 – To be advised – will be to send data to AWS IOT platform
Phase 3 – To be advised – Display data in Grafana, GnuPlot, and MS Excel

The DFRRobot BME280 wiki page provides the code, libraries to load and R4 to sensor connections.
The Plan
The plan is to use the Raspberry Pi 5 to collect the remotely/outside stationed arduino with the
Below is the working modified code I used to connect to my Wi-Fi and output to a browser in HTTP (e.g. http://192.168.1.12).
// Using the DFRobot library for BME280 sensor
#include "DFRobot_BME280.h"
#include "Wire.h"
// For network connectivity via the Arduino R4 WiFi module
#include <WiFiS3.h>
#include <WiFiServer.h>
// My WiFi credentials — used to connect to local network
const char* ssid = "XXXXXX";
const char* password = "XXXXXX";
// I’ll host a simple web server on port 80 to serve readings
WiFiServer server(80);
// Alias the BME280 object type for clarity/brevity
typedef DFRobot_BME280_IIC BME;
// Initialise the sensor using the Wire and address
BME bme(&Wire, 0x77);
// Local reference pressure for altitude calculations
#define SEA_LEVEL_PRESSURE 1015.0f
// Utility function to print the last known sensor status
void printLastOperateStatus(BME::eStatus_t eStatus)
{
switch(eStatus) {
case BME::eStatusOK: Serial.println("everything ok"); break;
case BME::eStatusErr: Serial.println("unknown error"); break;
case BME::eStatusErrDeviceNotDetected: Serial.println("device not detected"); break;
case BME::eStatusErrParameter: Serial.println("parameter error"); break;
default: Serial.println("unknown status"); break;
}
}
void setup() {
// Start serial output for monitoring via USB
Serial.begin(115200);
// Connect to WiFi network
Serial.print("Connecting to WiFi...");
while (WiFi.begin(ssid, password) != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("\nConnected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Start the HTTP server
server.begin();
// Reset the BME280 sensor (just to be safe)
bme.reset();
Serial.println("bme read data test");
// Loop until the sensor responds correctly
while (bme.begin() != BME::eStatusOK) {
Serial.println("bme begin failed");
printLastOperateStatus(bme.lastOperateStatus);
delay(2000);
}
Serial.println("bme begin success");
delay(100); // Give the sensor a moment to settle
}
void loop() {
// Read sensor values and calculate altitude
float temp = bme.getTemperature();
uint32_t press = bme.getPressure();
float alti = bme.calAltitude(SEA_LEVEL_PRESSURE, press);
float humi = bme.getHumidity();
// Wait for an incoming client (browser or script)
WiFiClient client = server.available();
if (client) {
// Wait for full HTTP request to arrive
while (!client.available()) delay(1);
// Read request line (basic parsing)
String req = client.readStringUntil('\r');
client.readStringUntil('\n'); // consume the blank line
// If someone requested /json, serve structured sensor values
if (req.indexOf("GET /json") != -1) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: application/json");
client.println("Connection: close");
client.println();
// Output JSON object with current readings (rounded as needed)
client.print("{\"temperature\":"); client.print(temp, 2);
client.print(",\"pressure\":"); client.print(press);
client.print(",\"altitude\":"); client.print(alti, 2);
client.print(",\"humidity\":"); client.print(humi, 2);
client.println("}");
}
// Otherwise, serve a human-readable HTML page
else {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("<html><body><h2>BME280 Sensor Data</h2>");
client.print("<p>Temperature: "); client.print(temp); client.println(" unit Celsius</p>");
client.print("<p>Pressure: "); client.print(press); client.println(" unit pa</p>");
client.print("<p>Altitude: "); client.print(alti); client.println(" unit meter</p>");
client.print("<p>Humidity: "); client.print(humi); client.println(" unit percent</p>");
client.println("</body></html>");
}
// Flush buffers and close connection
delay(1);
client.flush();
client.stop();
}
// Serial output for local debugging or monitoring over USB
Serial.println();
Serial.println("======== start print ========");
Serial.print("temperature (unit Celsius): "); Serial.println(temp);
Serial.print("pressure (unit pa): "); Serial.println(press);
Serial.print("altitude (unit meter): "); Serial.println(alti);
Serial.print("humidity (unit percent): "); Serial.println(humi);
Serial.println("======== end print ========");
// Wait 10 seconds before next cycle
delay(10000);
}
The Arduino serial output looks like below

The browser out looks like below:

Create Database Table
The below SQL was used to create the table in my PostgreSQL database.
Note. As the data is being ingested, I’m timestamp it with current data as per my PC / internet time.
CREATE TABLE arduino_weather_log (
id SERIAL PRIMARY KEY,
timestamp TIMESTAMPTZ DEFAULT NOW(),
temperature REAL,
pressure INTEGER,
altitude REAL,
humidity REAL
);
Use the below query to view 50 lines of the most recent logged data
SELECT timestamp, temperature, pressure, altitude, humidity
FROM arduino_weather_log
ORDER BY timestamp DESC
LIMIT 50;