Skip to content

Linux-based weather station with Buildroot using a webserver for visualization.

Notifications You must be signed in to change notification settings

prdktntwcklr/weatherstation-linux

Repository files navigation

Linux Weatherstation

This repository contains an embedded Linux system built for the Raspberry Pi 3 Model B+ using Buildroot (https://buildroot.org/).

This project runs a Python application that continuously reads from an I2C-connected SHT31 temperature & humidity sensor, then writes the environmental data to an SQLite database and functions as a web server to visualize the results on a dashboard.

For the individual projects providing sensor readings and dashboard functionality, see prdktntwcklr/python-sht31 and prdktntwcklr/weatherman, respectively.

Hardware

  • Raspberry Pi 3 Model B+
  • MicroSD card
  • Sensirion SHT31 temperature & humidity sensor
  • Jumper wires
  • USB Micro-B cable
  • RJ45 cable

Building the project

First, make sure you have all mandatory packages for Buildroot readily installed on your system. See the Buildroot user manual section for details.

Since this repository contains several submodules, it needs to be cloned using the --recursive flag:

git clone --recursive https://github.com/prdktntwcklr/weatherstation-linux.git

When building for the first time, the BR2_EXTERNAL variable needs to be set to point to the out-of-tree directory:

cd weatherstation-linux/buildroot
make BR2_EXTERNAL=../buildroot-external weatherstation_defconfig

This loads the default configuration for the project. To build the project, run:

make -j16 2>&1 | tee ../build.log

For ease of debugging, this will save build messages to a file called build.log in the top directory. The build products can be found under buildroot/output/images.

Installing

After copying the build products over to an SD card, insert the card into the Raspberry Pi and apply power to the board. You should be able to follow the boot messages over a serial port. When you reach the login prompt, enter root for both username and password.

Cron Job

The system is set up to sample environmental data from the attached SHT31 sensor by use of a Python script. Running the script continuously is defined as a cron job as part of the rootfs overlay under var/spool/cron/crontabs/root:

*/5 * * * * /bin/python /root/log-data.py

This ensures the log-data.py script runs every five minutes.

Python Script

The log-data.py Python script first opens an SQLite database file, reads environmental values from the sensor and inserts these values into the database together with the current timestamp:

def main():
    try:
        db = Database('/var/www/web-app/weather.db')
        sens = Sensor()

        values = sens.get_values()

        db.insert(values)

    finally:
        db.close()

If reading from the sensor fails for any reason, the script is configured to use dummy values of -99.99 instead. Seeing these values should alert the user that a read from the sensor was unsuccessful.

class Sensor:
    # class initialization omitted

    def get_values(self):
        curr_time = get_formatted_datetime()

        if self.instance is not None:
            curr_temp, curr_humi = self.instance.get_temp_and_humidity()

            if curr_temp is None or curr_humi is None:
                # error in reading values from sensor, use dummy values
                curr_temp = -99.99
                curr_humi = -99.99
        # else case omitted

        return (curr_time, round(curr_temp, 2), round(curr_humi, 2))

To allow for testing the script on a regular PC without having a sensor attached, random values are used when no instance of the sensor device has been defined. This is the default fallback solution if the SMBus library is not available, which only exists on the Raspberry Pi:

class Sensor:
    def __init__(self):
        if smbus_exists:
            # initialization of regular sensor omitted
        else:
            self.address = None
            self.bus = None
            self.instance = None

    def get_values(self):
        curr_time = get_formatted_datetime()
    
        if self.instance is not None:
            # reading data from regular sensor omitted
        else:
            # no sensor available, use random values
            curr_temp = random.uniform(-10, 40)
            curr_humi = random.uniform(0, 100)
    
        return (curr_time, round(curr_temp, 2), round(curr_humi, 2))

About

Linux-based weather station with Buildroot using a webserver for visualization.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published