Weather station

In this tutorial we are using an ESP32 with the Bosch BME280 sensor; an environmental sensor measuring temperature, the relative humidity, and the atmospheric pressure.

The code examples shown in this tutorial are also available here.

Connect the sensor

BME280
BME280

Follow the steps here to connect the BME280 sensor with your ESP32 using a Qwiic cable.

Install package

In order to get data from the sensor we make use of the BME280 driver available as a package from pkg.toit.io.

Open Visual Studio Code, and create a new file. Paste the following Toit program into the file and save the file as: weather-station.toit:

/**
Program measuring temperature, relative humidity, and atmospheric pressure
  with a BME280.
*/

import gpio
import i2c
import bme280

main:
  bus := i2c.Bus
    --sda=gpio.Pin 21
    --scl=gpio.Pin 22

  device := bus.device bme280.I2C-ADDRESS-ALT

  driver := bme280.Driver device

  print "Temperature: $driver.read-temperature C"
  print "Humidity: $driver.read-humidity %"
  print "Pressure: $driver.read-pressure Pa"

Then, open a terminal window in VS Code and execute the following commands in order to install the BME280 driver package locally:

jag pkg init
jag pkg install github.com/toitware/bme280-driver

Run Toit program

If you want to know more about what is happening in each step in the Toit program above, see here.

To run the program once on the ESP32, execute the CLI command

jag run weather-station.toit

If you haven't set your default device in the CLI, you can set it with the command jag scan. (Your workstation and your device must be on the same WiFi network.)

Alternatively, you can add -d device-name to the run command, where device-name is the name of your ESP32.

$ jag run weather-station.toit
Running 'weather-station.toit' on 'mydevice' ...
Success: Sent 37KB code to 'mydevice'

You can see the program's output on the USB/serial port using jag monitor:

[jaguar] INFO: program 7a3d83f9-837c-589d-a6e4-8f95ecb3cab4 started
Temperature: 25.769999999999999574 C
Humidity: 42.111328125 %
Pressure: 101686.515625 Pa
[jaguar] INFO: program 7a3d83f9-837c-589d-a6e4-8f95ecb3cab4 stopped

Running a Toit program in this way means that it will be uninstalled from the device once the program has terminated.

Deploy app

If we want the program to survive reboots, we have to install it as a container.

Deploy the application as follows:

jag container install weather weather-station.toit

Doing so will install the application so that it is automatically started whenever the ESP32 boots.

At the current state this isn't very useful, as the program stops after one iteration.

We have two options to fix this:

  1. Use an infinite loop inside the program, that sleeps, or
  2. Go into deep sleep and wake up after a few seconds. Waking up from deep sleep counts as rebooting, and will thus cause the container to be restarted.

Infinite loop

Change your program to:

/**
Program measuring temperature, relative humidity, and atmospheric pressure
  with a BME280.
*/

import gpio
import i2c
import bme280

main:
  bus := i2c.Bus
    --sda=gpio.Pin 21
    --scl=gpio.Pin 22

  device := bus.device bme280.I2C-ADDRESS-ALT

  driver := bme280.Driver device

  while true:
    print "Temperature: $driver.read-temperature C"
    print "Humidity: $driver.read-humidity %"
    print "Pressure: $driver.read-pressure Pa"
    sleep --ms=5000

Deploy the new version with jag container install weather weather-station.toit to replace the old version.

With this small modification, the program now runs continuously and outputs the measured values every 5 seconds.

Deep sleep

We first need to import ESP32 specific functions by adding the esp32 import:

import esp32

This provides the deep-sleep function which immediately puts the ESP32 into deep sleep. We need to be a bit careful with this function, though. If we call deep sleep too early, then the Jaguar service on the ESP32 won't have the time to connect to the WiFi and receive new commands. While you use Jaguar for development, it is a good idea to add a few seconds of delay before calling deep sleep. This way, Jaguar can start up and receive commands before your program shuts down the ESP32.

If you forget the timeout or set it too low, then you can always use the jag flash command to recover your ESP32.

Here is the updated version of our program that uses deep sleep:

/**
Program measuring temperature, relative humidity, and atmospheric pressure
  with a BME280.
*/

import gpio
import i2c
import bme280
import esp32

main:
  bus := i2c.Bus
    --sda=gpio.Pin 21
    --scl=gpio.Pin 22

  device := bus.device bme280.I2C-ADDRESS-ALT

  driver := bme280.Driver device

  print "Temperature: $driver.read-temperature C"
  print "Humidity: $driver.read-humidity %"
  print "Pressure: $driver.read-pressure Pa"
  sleep --ms=5000  // Give Jaguar time to receive commands.
  esp32.deep-sleep (Duration --s=10)

Deploy the new version with jag container install weather weather-station.toit to replace the old version.

When using jag monitor you should see new measurements every 15 seconds.