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.
Wire.onRequest(send_data);
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.
get_data();
// 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(temperature);
Serial.print(" ");
Serial.print(humidity);
Serial.print(" ");
Serial.print(heat_index);
Serial.print(" ");
Serial.println(air_pressure);
}
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)
{
while(Wire.available())
{
int number_command = Wire.read();
if(number_command==1){
value_to_send = temperature;
temperature = 0;
}
if(number_command==2){
value_to_send = humidity;
humidity = 0;
}
if(number_command==3){
value_to_send = heat_index;
heat_index = 0;
}
if(number_command==4){
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.