A Banana Pro Weather Logger

poll-weather-data.ino, the LeoStick sketch.

Here's poll-weather-data.ino which runs forever on the LeoStick in my weather logger circuit. there's not much to do in void loop() except wait for GPIO pin 0 on the Banana Pro to cause pin 4 on the LeoStick to go HIGH at which time the function get_data() is called.

/ poll-weather-data.ino RM20190427                                                                          /
/ This sketch is intended to collect weather data on a Leostick via I2C from an Adafruit                    /
/ HTU21D humidity module and a Freetronics MS5637 air pressure module. With the LeoStick,                   /
/ (I2C slave) the data can be accessed on request via I2C using a C program run on a Banana                 /
/ Pro (I2C master). To query data from a Banana Pro see companion C program, get-w-data.c.                  /
#include "Wire.h"                         // Wire.h library required for I2C communication.
#include "BaroSensor.h"                   // Freetronics library for the MS5637 air pressure module.
#include "cactus_io_HTU21D.h"             // I use cactus.io library for HTU21D. It calculates heat index.
#define slave_address 0x04                // LeoStick's I2C address.

HTU21D htu;                               // Create instance of object to be used in cactus.io function names.
const int swtch_pin = 4;                  // Pin used to trigger a sensor data poll.
volatile float temperature;               // Temperature reading from HTU21D module.
volatile float humidity;                  // Humidity reading from HTU21D module.
volatile float heat_index;                // Calculated heat index.
volatile float air_pressure;              // Barometric pressure reading from air pressure module.
volatile float value_to_send;             // Variable assigned to data sent via I2C.

void setup()
  pinMode(swtch_pin, LOW);                
  Wire.begin(slave_address);              // Initialise Leostick as I2C slave.
  Wire.onReceive(receive_data);           // Callbacks for i2c communication.
  BaroSensor.begin();                     // Initialise the pressure sensor module 
  get_data();                             // At boot all data variables will initialise as 0. Run 
                                          // get_data() or else all variables at first poll from the 
                                          // Banana Pro will be 0.0.
  Serial.begin(9600);                     // Only required for testing with serial monitor.
void loop() 
  if (digitalRead(swtch_pin) == HIGH){    // swtch_pin was set LOW. When it goes HIGH the function get_data()
                                          // is called and the weather data variables are updated.  
    // print_data();                         // Only required for testing with serial monitor

The LeoStick is the I2C master and the weather sensors are I2C slaves. The function get_data() polls the two sensors and updates the four data variables. The function print_data() is only required for testing. Note that if you have the circuit connected to your SBC you will not have anything printed to a serial monitor unless you disconnect the SDA and SCL wires from either the circuit or the SBC. I disconnect the 3.3V and 5V wires as well.

// Function for polling HTU21D and Baro Sensor for weather data.
void get_data(){
    htu.readSensor();                     // Initialise temp/Rh sensor                     
    temperature = htu.getTemperature_C();
    humidity = htu.getHumidity();
    heat_index = htu.getHeatIndex_C();
    air_pressure = BaroSensor.getPressure();
// Function for printing data to serial monitor. Not required after testing.
void print_data()
    Serial.print("  ");
    Serial.print("  ");
    Serial.print("  ");

The Banana Pro is the I2C master and the LeoStick is now the I2C slave. When the program get_w_data (to be discussed in the next section) sends a number via I2C to the LeoStick the corresponding variable's value is assigned to the variable value_to_send and that value is returned to get_w_data.

// Function used to provide data to I2C master on request.
void receive_data(int byte_count)
      int number_command = Wire.read();

          value_to_send = temperature;
          temperature = 0;
          value_to_send = humidity;
          humidity = 0;
          value_to_send = heat_index;
          heat_index = 0;
          value_to_send = air_pressure;
          air_pressure = 0;
// Function for sending data via I2C after converting float values into vectors of 4 bytes.
void send_data()
    char vector_to_send[4];       
    memcpy(vector_to_send, (char*) & (value_to_send), 4);
    Wire.write(vector_to_send, 4);

Note that you can copy and past these three blocks of code together and have the complete sketch.

What's up?