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.