Arduino Ek R4 Main Sketch
ek_r4_circuit_main.ino
/*
Project: Smart Home
Component: Main Circuit
Sketch Description: This sketch has the main setup() and loop() functions that call
the functions to manage the components.
Installation:
Ensure that the R4 board package is installed.
Read this for details on how Arduino compiles sketches distributed across multiple files.
https://arduino.github.io/arduino-cli/1.0/sketch-build-process/#pre-processing
All .ino files in the sketch folder are concatenated together,
starting with the file that matches the folder name followed by the others in alphabetical order.
The .cpp filename extension is then added to the resulting file.
Author: STEMVentor Educonsulting
This code is copyrighted. Please do not reuse or share for any purpose other than for learning with subscribed STEMVentor programs. This code is for educational purposes only and is not for production use.
*/
// LIBRARIES
#include <ArduinoBLE.h>
// Project library/data files.
// Use "" when including library files in same directory
// as against <> for library files in global directory.
// All global definitions, including pins, constants and BLE UUIDs are mainatained in the board_parameters.h file.
#include "board_parameters.h"
// These are used to turn off any functionality during development to focus on testing something specific.
const bool ENABLE_LED_MATRIX = true;
const bool ENABLE_BUZZER = true;
const bool ENABLE_RGB_LED = true;
const bool ENABLE_LCD = true;
const bool ENABLE_DHT_SENSOR = true;
const bool ENABLE_GAS_SENSOR = true;
const bool ENABLE_SOUND_SENSOR = true;
const bool ENABLE_AMBIENT_LIGHT_SENSOR = true;
const bool ENABLE_SOIL_MOISTURE_SENSOR = true;
const bool ENABLE_ULTRASONIC_DISTANCE_SENSOR = true;
const bool ENABLE_PIR_MOTION_SENSOR = true;
const bool ENABLE_RELAY = true;
const bool ENABLE_SERVO = true;
const bool ENABLE_WIFI = true;
const bool ENABLE_RTC_TIME = true; // ENABLE_WIFI must also be true.
const bool ENABLE_MQTT = true; // ENABLE_WIFI must also be true.
const bool ENABLE_BLE = true; // ENABLE_BLE_PERIPHERAL must also be true.
// const bool ENABLE_BLE_CENTRAL = false; // Not implemented, keep false.
const bool ENABLE_BLE_PERIPHERAL = true; // ENABLE_BLE must also be true.
// PIN DEFINITIONS
// Defined in board_parameters.h
// GLOBAL VARIABLES
// Defined in board_parameters.h
// We need to run the sensors in sequence since simultaneous operations may lead
// to unpredictable behaviour. Individual timers won't guarantee no overlap.
// So at the end of each sensor process we will set which sensor to process next.
// Bit of hard-coding but can't think of a more generic approach.
// Exclude any sensors that work with an Interrupt Service Request (ISR).
// Sequence is assigned in the board_parameters.h file.
// Start with one and then set the next one in each.
uint8_t sensor_to_read = DHT_SENSOR;
// Also, to add an interval between each sensor read we will have a single last_read time and interval.
// For last_read use unsigned long since this can go very long if the board is kept running.
// Can it be reset to 0 after max value?
const uint32_t SENSOR_READ_INTERVAL = 10*1000; // 10 seconds
uint64_t sensor_last_read = 0;
// DECLARE FUNCTION PROTOTYPES
// In some cases you need to declare an explicit function prototype at the beginning of the calling sketch.
// So far, observed that functions that take parameters need to be explicitly declared here.
void printToLCDByRow(uint8_t row, String text, bool clear_all);
void writeBLECharacteristicValue(String characteristic_uuid, int value);
// INITIALIZE OBJECTS
/* Libraries usually follow an object-oriented approach that requires
* an instance of the class to call its methods.
*/
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Native USB only
}
// In Serial.println enclosing a static string within F("") indicates that the
// string must be stored in Flash (ROM) memory instead of the RAM.
// This is useful if you would like to have extra RAM available for computations.
// Of course this takes up Flash memory which is also used to store your compiled code
// so it is a trade off depending on your sketch.
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up connected components..."));
}
// Add a small delay between each component setup.
if(ENABLE_LED_MATRIX){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the LED Matrix..."));
}
LEDMatrixSetup();
displayNotConnectedOnLEDMatrix();
}
delay(2*1000);
if(ENABLE_BUZZER){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the buzzer..."));
}
buzzerSetup();
}
delay(2*1000);
if(ENABLE_RGB_LED){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the RGB LED..."));
}
RGBLEDSetup();
}
delay(2*1000);
if(ENABLE_LCD){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the LCD Display..."));
}
LCDSetup();
}
delay(2*1000);
if(ENABLE_DHT_SENSOR){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the DHT temperature and humidity sensor..."));
}
DHTSetup();
}
delay(2*1000);
if(ENABLE_GAS_SENSOR){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the gas sensor..."));
}
gasSensorSetup();
}
delay(2*1000);
if(ENABLE_SOUND_SENSOR){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the sound sensor..."));
}
soundSensorSetup();
}
delay(2*1000);
if(ENABLE_AMBIENT_LIGHT_SENSOR){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the ambient light sensor..."));
}
ambientLightSensorSetup();
}
delay(2*1000);
if(ENABLE_SOIL_MOISTURE_SENSOR){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the soil moisture sensor..."));
}
soilMoistureSensorSetup();
}
delay(2*1000);
if(ENABLE_ULTRASONIC_DISTANCE_SENSOR){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the ultrasonic distance sensor..."));
}
ultrasonicDistanceSensorSetup();
}
delay(2*1000);
if(ENABLE_PIR_MOTION_SENSOR){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the PIR motion sensor..."));
}
PIRMotionSensorSetup(); // This uses an interrupt function so need not be called in the loop.
}
delay(2*1000);
if(ENABLE_RELAY){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the relay..."));
}
relaySetup();
}
delay(2*1000);
if(ENABLE_SERVO){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the servo..."));
}
servoSetup();
}
delay(2*1000);
if(ENABLE_WIFI){
if(OPERATING_MODE == 'D'){
Serial.println(F("Connecting to WiFi..."));
}
WiFiSetup();
}
delay(3*1000);; // Temp delay to let WiFi connect
if(ENABLE_RTC_TIME){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up the RTC..."));
}
setRTCTime();
}
delay(2*1000);
// if(ENABLE_BLE && ENABLE_BLE_CENTRAL){
// if(OPERATING_MODE == 'D'){
// Serial.println(F("Setting up BLE Central Device..."));
// }
// BLECentralSetup();
// }
// delay(3*1000);; // Temp delay to let BLE connect
if(ENABLE_BLE && ENABLE_BLE_PERIPHERAL){
if(OPERATING_MODE == 'D'){
Serial.println(F("Setting up BLE Peripheral Device..."));
}
BLEPeripheralSetup();
}
delay(3*1000); // Temp delay to let BLE setup
if(OPERATING_MODE == 'D'){
Serial.println(F("Connected components setup completed successfully!"));
}
}
void loop() { // run over and over
// Get current elapsed milliseconds since board was last powered on.
// Var type must be unsigned long.
// millis() will reset to 0 after the max value (about 50 days).
unsigned long current_millis = millis();
if(ENABLE_LCD){
// If there is any text in the global lcd_text variable display it on the LCD and clear it.
// This is only required for data received via an ISR (Interrupt) since you cannot write
// to Serial or LCD in an ISR.
if(lcd_text != "" && lcd_row != 0){
printToLCDByRow(lcd_row, lcd_text, true);
lcd_text = "";
lcd_row = 0;
}
}
/********** DHT SENSOR **********/
// Read data if sensor is enabled, it is the next in sequence and interval since last read has elapsed.
if(ENABLE_DHT_SENSOR && sensor_to_read == DHT_SENSOR && (current_millis - sensor_last_read) >= SENSOR_READ_INTERVAL){
// Receive the sensor values returned from the read sensor function
// and do what you need to do with the data here (Serial.print, send to MQTT, send to BLE).
structDHTData dht_values = readDHTValues();
if(OPERATING_MODE == 'D'){
Serial.println("--- READING DHT SENSOR ---");
// Print the temperature in °C (only C value is returned)
Serial.println("Temperature:" + String(dht_values.temperature) + "°C");
// Print the humidity in %
Serial.println("Humidity:" + String(dht_values.humidity) + "%");
// Print the heat index in °C (only C value is returned)
Serial.println("Heat Index:" + String(dht_values.heat_index) + "°C");
}
// Display on LCD
printToLCDByRow(1, "Temperature:" + String(dht_values.temperature) + "C", true);
printToLCDByRow(2, "Humidity:" + String(dht_values.humidity) + "%", false);
printToLCDByRow(3, "Heat Index:" + String(dht_values.heat_index) + "C", false);
// Send to MQTT over WiFi
if(ENABLE_WIFI && ENABLE_MQTT && is_wifi_connected){
Serial.println("Publishing Temp to MQTT");
publishToMQTTServer(TEMPERATURE_CHARACTERISTIC_UUID, dht_values.temperature);
publishToMQTTServer(HUMIDITY_CHARACTERISTIC_UUID, dht_values.humidity);
}
// Send over BLE
if(ENABLE_BLE && ENABLE_BLE_PERIPHERAL){
writeBLECharacteristicValue(TEMPERATURE_CHARACTERISTIC_UUID, dht_values.temperature);
writeBLECharacteristicValue(HUMIDITY_CHARACTERISTIC_UUID, dht_values.humidity);
}
// Update the last read to now.
sensor_last_read = current_millis;
// And set the next sensor to read.
sensor_to_read = GAS_SENSOR;
}else if(!ENABLE_DHT_SENSOR){
// For dev if any sensor is disabled, don't read but move to the next one.
sensor_to_read = GAS_SENSOR;
}
/********** GAS SENSOR **********/
// Read data if sensor is enabled and interval since last read has elapsed.
// We will be receiving the digital value (HIGH or LOW) only.
if(ENABLE_GAS_SENSOR && sensor_to_read == GAS_SENSOR && (current_millis - sensor_last_read) >= SENSOR_READ_INTERVAL){
uint8_t gas_sensor_digital_value = readGasSensorValues();
if(OPERATING_MODE == 'D'){
Serial.println("--- READING GAS SENSOR ---");
Serial.println("Gas Sensor Value: " + gas_sensor_digital_value);
}
// Display on LCD and sound the buzzer.
if(gas_sensor_digital_value == HIGH){
printToLCDByRow(1, "Gas Detected!", true);
soundBuzzerIntermittent(1000, 3*1000, 15*1000);
}else{
printToLCDByRow(1, "No Gas Detected!", true);
switchBuzzerOff();
}
// Send to MQTT over WiFi
if(ENABLE_WIFI && ENABLE_MQTT && is_wifi_connected){
if(gas_sensor_digital_value == HIGH){
publishToMQTTServer(GAS_CHARACTERISTIC_UUID, 1);
}else{
publishToMQTTServer(GAS_CHARACTERISTIC_UUID, 0);
}
}
// Send over BLE
if(ENABLE_BLE && ENABLE_BLE_PERIPHERAL && is_ble_connected){
// For binary indicator we will be using a Detected parameter with values of Y or N.
// Since the characteristic type is BLEInt, see if we want to use BLEString.
if(gas_sensor_digital_value == HIGH){
writeBLECharacteristicValue(GAS_CHARACTERISTIC_UUID, 1);
}else{
writeBLECharacteristicValue(GAS_CHARACTERISTIC_UUID, 0);
}
}
// Update the last read to now.
sensor_last_read = current_millis;
// And set the next sensor to read.
sensor_to_read = SOUND_SENSOR;
}else if(!ENABLE_GAS_SENSOR){
// For dev if any sensor is disabled, don't read but move to the next one.
// Since the if has multiple conditions we need to explicitly specify the else condition.
// Without that it is skipping even if it fails the time condition.
sensor_to_read = SOUND_SENSOR;
}
/********** SOUND SENSOR **********/
// Read data if sensor is enabled and interval since last read has elapsed.
// Sound sensor will return a % value
if(ENABLE_SOUND_SENSOR && sensor_to_read == SOUND_SENSOR && (current_millis - sensor_last_read) >= SENSOR_READ_INTERVAL){
uint8_t sound_sensor_percent_value = readSoundSensorValues();
if(OPERATING_MODE == 'D'){
Serial.println("-- READING SOUND SENSOR ---");
Serial.println("Sound Sensor Value: " + String(sound_sensor_percent_value));
}
// Display on LCD
printToLCDByRow(1, "Sound Level: " + String(sound_sensor_percent_value), true);
// We will be using the sound level to toggle a light on and off.
if(sound_sensor_percent_value >= 50){
if(!is_light_on){
switchRelayOn(LIGHT_RELAY);
if(OPERATING_MODE == 'D'){
Serial.println("Switching the light on!");
}
}else{
switchRelayOff(LIGHT_RELAY);
if(OPERATING_MODE == 'D'){
Serial.println("Switching the light off!");
}
}
}
// Send to MQTT over WiFi
// Not publishing this since only 7 characteristics are supported by a service.
// We will only use it to toggle the light.
// if(ENABLE_WIFI && ENABLE_MQTT && is_wifi_connected){
// publishToMQTTServer(SOUND_CHARACTERISTIC_UUID, sound_sensor_percent_value);
// }
// Send over BLE
// Not publishing this since only 7 characteristics are supported by a service.
// We will only use it to toggle the light.
// if(ENABLE_BLE && ENABLE_BLE_PERIPHERAL){
// writeBLECharacteristicValue(SOUND_CHARACTERISTIC_UUID, sound_sensor_percent_value);
// }
// Update the last read to now.
sensor_last_read = current_millis;
// And set the next sensor to read.
sensor_to_read = AMBIENT_LIGHT_SENSOR;
}else if(!ENABLE_SOUND_SENSOR){
// For dev if any sensor is disabled, don't read but move to the next one.
sensor_to_read = AMBIENT_LIGHT_SENSOR;
}
/********** AMBIENT LIGHT SENSOR **********/
// Read data if sensor is enabled and interval since last read has elapsed.
// We will be receiving the digital and analog values.
if(ENABLE_AMBIENT_LIGHT_SENSOR && sensor_to_read == AMBIENT_LIGHT_SENSOR && (current_millis - sensor_last_read) >= SENSOR_READ_INTERVAL){
structDigitalAnalogValues ambient_light_sensor_values = readAmbientLightSensorValues();
if(OPERATING_MODE == 'D'){
Serial.println("--- READING AMBIENT LIGHT SENSOR ---");
Serial.println("Ambient Light Sensor Digital Value: " + ambient_light_sensor_values.digital_value);
Serial.println("Ambient Light Sensor Analog Value: " + ambient_light_sensor_values.analog_value);
}
// Convert the analog value to a % value using the map function.
// We will be sending this value to MQTT and over BLE to indicate relative light intensity.
uint8_t ambient_light_sensor_percent_value = map(ambient_light_sensor_values.analog_value, 0, 1024, 0, 100);
if(OPERATING_MODE == 'D'){
Serial.println("Percent Value: " + ambient_light_sensor_percent_value);
}
// Display on LCD
if(ambient_light_sensor_values.digital_value == HIGH){
printToLCDByRow(1, "Light Detected!", true);
printToLCDByRow(2, "Light Intensity: " + String(ambient_light_sensor_percent_value) + "%", false);
}else
{
printToLCDByRow(1, "No Light Detected!", true);
}
// Turn on the light connected to the relay if the digital value goes LOW
// or if intensity is 25% or less
// And off if it goes HIGH or if intensity is more than 25%.
if(ambient_light_sensor_values.digital_value == LOW || ambient_light_sensor_percent_value <= 25){
switchRelayOn(LIGHT_RELAY);
if(OPERATING_MODE == 'D'){
Serial.println("Switching the light on!");
}
}else if(ambient_light_sensor_values.digital_value == HIGH || ambient_light_sensor_percent_value > 25){
switchRelayOff(LIGHT_RELAY);
if(OPERATING_MODE == 'D'){
Serial.println("Switching the light off!");
}
}
// Send to MQTT over WiFi (only % value)
if(ENABLE_WIFI && ENABLE_MQTT && is_wifi_connected){
publishToMQTTServer(AMBIENT_LIGHT_CHARACTERISTIC_UUID, ambient_light_sensor_percent_value);
}
// Send over BLE (only % value)
if(ENABLE_BLE && ENABLE_BLE_PERIPHERAL){
writeBLECharacteristicValue(AMBIENT_LIGHT_CHARACTERISTIC_UUID, ambient_light_sensor_percent_value);
}
// Update the last read to now.
sensor_last_read = current_millis;
// And set the next sensor to read.
sensor_to_read = SOIL_MOISTURE_SENSOR;
}else if(!ENABLE_AMBIENT_LIGHT_SENSOR){
// For dev if any sensor is disabled, don't read but move to the next one.
sensor_to_read = SOIL_MOISTURE_SENSOR;
}
/********** SOIL MOISTURE SENSOR **********/
// Read data if AMBIENT LIGHT sensor is enabled and interval since last read has elapsed.
// We will be receiving the digital and analog values.
if(ENABLE_SOIL_MOISTURE_SENSOR && sensor_to_read == SOIL_MOISTURE_SENSOR && (current_millis - sensor_last_read) >= SENSOR_READ_INTERVAL){
structDigitalAnalogValues soil_moisture_sensor_values = readSoilMoistureSensorValues();
if(OPERATING_MODE == 'D'){
Serial.println("--- READING SOIL MOISTURE SENSOR ---");
Serial.println("Soil Moisture Sensor Digital Value: " + soil_moisture_sensor_values.digital_value);
Serial.println("Soil Moisture Sensor Analog Value: " + soil_moisture_sensor_values.analog_value);
}
// Convert the analog value to a % value using the map function.
// We will be sending this value to MQTT and over BLE to indicate relative moisture level.
uint8_t soil_moisture_sensor_percent_value = map(soil_moisture_sensor_values.analog_value, 0, 1024, 0, 100);
if(OPERATING_MODE == 'D'){
Serial.println("Percent Value: " + soil_moisture_sensor_percent_value);
}
// Display on LCD
if(soil_moisture_sensor_values.digital_value == HIGH){
printToLCDByRow(1, "Soil moisture ok!", true);
}else
{
printToLCDByRow(1, "Soil Moisture Low!", true);
}
printToLCDByRow(2, "Level: " + String(soil_moisture_sensor_percent_value) + "%", false);
// Turn on the pump connected to the relay if the digital value goes LOW
// or if intensity is 25% or less
// And off if it goes HIGH or if intensity is more than 25%.
if(soil_moisture_sensor_values.digital_value == LOW || soil_moisture_sensor_percent_value <= 25){
switchRelayOn(PUMP_RELAY);
if(OPERATING_MODE == 'D'){
Serial.println("Switching the pump on!");
}
}else if(soil_moisture_sensor_values.digital_value == HIGH || soil_moisture_sensor_percent_value > 25){
switchRelayOff(PUMP_RELAY);
if(OPERATING_MODE == 'D'){
Serial.println("Switching the pump off!");
}
}
// Send to MQTT over WiFi (only % value)
if(ENABLE_WIFI && ENABLE_MQTT && is_wifi_connected){
publishToMQTTServer(SOIL_MOISTURE_CHARACTERISTIC_UUID, soil_moisture_sensor_percent_value);
}
// Send over BLE (only % value)
if(ENABLE_BLE && ENABLE_BLE_PERIPHERAL){
writeBLECharacteristicValue(SOIL_MOISTURE_CHARACTERISTIC_UUID, soil_moisture_sensor_percent_value);
}
// Update the last read to now.
sensor_last_read = current_millis;
// And set the next sensor to read.
sensor_to_read = ULTRASONIC_DISTANCE_SENSOR;
}else if(!ENABLE_SOIL_MOISTURE_SENSOR){
// For dev if any sensor is disabled, don't read but move to the next one.
sensor_to_read = ULTRASONIC_DISTANCE_SENSOR;
}
/********** ULTRASONIC DISTANCE SENSOR **********/
if(ENABLE_ULTRASONIC_DISTANCE_SENSOR && sensor_to_read == ULTRASONIC_DISTANCE_SENSOR && (current_millis - sensor_last_read) >= SENSOR_READ_INTERVAL){
// Read Ultrasonic Distance Sensor
// Read the distance continously as it is a continuously varying value in scenarios like driving.
uint8_t distance_cm = readUltrasonicDistanceSensorValue();
// Print to Serial monitor and LCD.
if(distance_cm <= 40){
if(OPERATING_MODE == 'D'){
Serial.println("--- READING ULTRASONIC DISTANCE SENSOR ---");
Serial.println("Distance (cm): " + String(distance_cm));
}
printToLCDByRow(1, "Distance: " + String(distance_cm) + " cm", true);
}else{
if(OPERATING_MODE == 'D'){
Serial.println("Distance (cm): Nothing in range");
}
printToLCDByRow(1, "Distance:", true);
printToLCDByRow(2, "Nothing in range", false);
}
// Light up the RGB LED as a visual indicator
if(distance_cm <= 20){
powerRGBLED(255, 0, 0); // Red
}else if(distance_cm > 20 && distance_cm <= 40){
powerRGBLED(5, 215, 255); // Orange
}else if(distance_cm > 40){
switchRGBLEDOff(); // Switch off
}
// Send to MQTT over WiFi
if(ENABLE_WIFI && ENABLE_MQTT && is_wifi_connected){
publishToMQTTServer(DISTANCE_CHARACTERISTIC_UUID, distance_cm);
}
// Send over BLE (only % value)
if(ENABLE_BLE && ENABLE_BLE_PERIPHERAL){
writeBLECharacteristicValue(DISTANCE_CHARACTERISTIC_UUID, distance_cm);
}
// Update the last read to now.
sensor_last_read = current_millis;
// And set the next sensor to read.
sensor_to_read = PIR_MOTION_SENSOR;
}else if(!ENABLE_ULTRASONIC_DISTANCE_SENSOR){
// For dev if any sensor is disabled, don't read but move to the next one.
sensor_to_read = PIR_MOTION_SENSOR;
}
/********** PIR MOTION SENSOR **********/
// Process data if sensor is enabled and interval since last read has elapsed.
// Since this is an interrupt triggered read a global variable is set, just process that.
if(ENABLE_PIR_MOTION_SENSOR && sensor_to_read == PIR_MOTION_SENSOR && (current_millis - sensor_last_read) >= SENSOR_READ_INTERVAL){
if(OPERATING_MODE == 'D'){
Serial.println("--- READING PIR MOTION SENSOR ---");
Serial.println("PIR Motion Value: " + pir_motion_sensor_value);
}
// Display on LCD
if(pir_motion_sensor_value == HIGH){
printToLCDByRow(1, "Motion Detected!", true);
}else
{
printToLCDByRow(1, "No Motion Detected!", true);
}
// Turn on the light connected to the relay if the value goes HIGH (motion detected)
// and off if it goes LOW (no motion detected)
if(pir_motion_sensor_value == HIGH){
switchRelayOn(LIGHT_RELAY);
if(OPERATING_MODE == 'D'){
Serial.println("Switching the light on!");
}
}else if(pir_motion_sensor_value == LOW){
switchRelayOff(LIGHT_RELAY);
if(OPERATING_MODE == 'D'){
Serial.println("Switching the light off!");
}
}
// Send to MQTT over WiFi (only analog value)
// Send to MQTT over WiFi
if(ENABLE_WIFI && ENABLE_MQTT && is_wifi_connected){
if(pir_motion_sensor_value == HIGH){
publishToMQTTServer(MOTION_CHARACTERISTIC_UUID, 1);
}else{
publishToMQTTServer(MOTION_CHARACTERISTIC_UUID, 0);
}
}
// Send over BLE (only analog value)
if(ENABLE_BLE && ENABLE_BLE_PERIPHERAL){
// For binary indicator we will be using a Detected parameter with values of Y or N.
// Since the characteristic type is BLEInt, see if we want to use BLEString.
if(pir_motion_sensor_value == HIGH){
writeBLECharacteristicValue(MOTION_CHARACTERISTIC_UUID, 1);
}else{
writeBLECharacteristicValue(MOTION_CHARACTERISTIC_UUID, 0);
}
}
// Update the last read to now.
sensor_last_read = current_millis;
// And set the next sensor to read.
sensor_to_read = DHT_SENSOR;
}else if(!ENABLE_PIR_MOTION_SENSOR){
// For dev if any sensor is disabled, don't read but move to the next one.
sensor_to_read = RTC_TIME; // Not a sensor exactly but set and display the time once every read cycle.
}
// Process data if sensor is enabled and interval since last read has elapsed.
// Since this is an interrupt triggered read a global variable is set, just process that.
if(ENABLE_RTC_TIME && sensor_to_read == RTC_TIME && (current_millis - sensor_last_read) >= SENSOR_READ_INTERVAL){
// Call setup in a loop once every minute so it keeps the time updated to the minute.
// setRTCTime();
// If the board has been running the time should be accurate so so no need to set in a loop.
String date_time = getRTCTime();
if(OPERATING_MODE == 'D'){
Serial.println(date_time);
}
printToLCDByRow(1, date_time, true);
}
// All functions below need to run in a contiuous loop without delay to keep connections alive.
if(ENABLE_WIFI && ENABLE_MQTT){
// This function checks if connected and connects if not.
// Also it is required to call the MQTT client loop() function in the main loop.
// Hence this function is not required to be called in the setup()
// This is the function defined in the MQTT sketch file called in the main loop here.
// This is needed since the MQTT client object is created and is in scope in that file.
keepaliveMQTTConnection();
}
// The Arduino board will be the peripheral. The IoT App will the central.
// So this will not be required.
// if(ENABLE_BLE && ENABLE_BLE_CENTRAL){
// scanForPeripherals();
// }
if(ENABLE_BLE && ENABLE_BLE_PERIPHERAL){
BLEPoll();
}
// General delay in the main loop.
// delay(1); // milliseconds
}