DrGee
Published

YADL: Yet Another Data Logger

Use a Nano 33 IoT or a MKR WiFi 1010 to access a TI SensorTag to easily build a powerful BLE data logger.

IntermediateShowcase (no instructions)15,326
YADL: Yet Another Data Logger

Things used in this project

Hardware components

Arduino Nano 33 IoT
Arduino Nano 33 IoT
or use an Arduino MKR WiFi 1010
×1
Arduino MKR WiFi 1010
Arduino MKR WiFi 1010
or use an Arduino NANO 33 IoT
×1
CC2650STK SensorTag Kit
Texas Instruments CC2650STK SensorTag Kit
×1
MikroE SPI SD card module
or use a generic SPI SD card module
×1
1.3" IIC I2C Serial 128x64 SSH1106 OLED LCD Display
or compatabile
×1

Hand tools and fabrication machines

Breadboard, 830 Tie Points
Breadboard, 830 Tie Points
Servo Motor, Premium Male/Male Jumper Wires
Servo Motor, Premium Male/Male Jumper Wires

Story

Read more

Schematics

Wiring Diagram

Use these connections for either the NANO 33 IOT or MKR 1010 board to the SPI SD card module and the OLED LCD display.

Code

YADL v1.0R

Arduino
Complete Program Code for the Data Logger
//*********************************************************************************
// YADL SensorTag Data Logger v1.0R [DrG]
//  ** This software is offered strictly as is with no guarantees or warranties. **
//  ** - USE IT AT YOUR OWN RISK!                                                **
//*********************************************************************************
//
// Uses:
// WiFiNINA v1.40
// RTCZero 1.6.0
// ArduinoBLE v1.1.1
// SD v1.2.3
// U8g2 (U8x8) v2.26.14
//
// Arduino IDE v1.8.10
//
// Hardware:
// MKR1010 / NANO 33 IOT (both have been tested)
// microSD card (both generics and MicroElectronika click board tested)
// HiLetgo 1.3" I2C monochrome OLED (others should work with modification)
//
// Note: Replace the code entries below with your network info:
// char ssid[] = "XXXXXXXXXX";
// char pass[] = "XXXXXXXXXX";
//
// Note: set GMT (with DST if needed) in code entry:
// const int GMT =XX
//
// #includes
#include <WiFiNINA.h>
#include <RTCZero.h>
#include <ArduinoBLE.h>
#include <SPI.h>
#include <SD.h>
#include <U8x8lib.h>
#include <avr/dtostrf.h> // needed for MKR1010

//#define DEBUG  // uncomment this line for serial monitor output

RTCZero rtc;
BLEDevice peripheral;
File SDF;

U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE);

// Global structure to hold the sensor data
struct DATA {
  float tem;     // HDC1000 temperature F
  float hum;     // HDC1000 relative humidity %RH
  float bptemp;  // BMP 280 die temperature F
  float bp;      // BMP 280 barometric pressure in hectoPascals (1 hPa = 100 Pa)
  float li;      // OPT3001 lux
  float temd;    // TMP007 die temperature F
  float temo;    // TMP007 object temperature F
};

typedef struct DATA DATA;
DATA SensorData;

// for SensorTag sensors
uint8_t sensorOn = 1;
uint8_t sensorOff = 0;

// lcd vars
char degree[] = {0xb0, 0x00};
char percent[] = {0x25, 0x00};
char p_buffer[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

// clock change catcher
int lastmin;

// for RTC
unsigned long epoch;
int numberOfTries = 0, maxTries = 6;

int status = WL_IDLE_STATUS;  // WiFiNINA use

// Common user-changeable switches
const int GMT = -4; //change this to adapt it to your time zone
byte SDswitch = 1;  // SDswitch 1=ON (write to SD) or 0 (Do not write to SD)
char fname[] = "STDATA.txt"; // data log file Name

//period defines the length of time between measurements in milliseconds
// note that this does not includes delays for sensor reads (~8.7 sec)
long period = 600000L; // 10 minutes
//long period = 5000L;  // 5 sec for testing

char ssid[] = "";   // your network SSID (name)
char pass[] = "";   // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;             // your network key Index number (needed only for WEP)

// SensorTag characteristic definitions
// BMP280
BLECharacteristic BPConCharacteristic;
BLECharacteristic BPValCharacteristic;
// OPT3001
BLECharacteristic OPTConCharacteristic;
BLECharacteristic OPTValCharacteristic;
// TMP007
BLECharacteristic IRTConCharacteristic;
BLECharacteristic IRTValCharacteristic;
// HDC1000
BLECharacteristic HUMConCharacteristic;
BLECharacteristic HUMValCharacteristic;
//------------------------------------------------------------------

void setup() {
  u8x8.begin(); // start lcd driver, will clear display
  u8x8.setFont(u8x8_font_amstrad_cpc_extended_f); // 8 X 8 font
  u8x8.drawString(0, 0, "YADL starting...");
#ifdef DEBUG
  Serial.begin(9600);
  delay(5000);  // delay for user to open the serial monitor
  Serial.println("YADL MKR1010/NANO IOT 33 SensorTag Data Logger");
  Serial.println();
#endif
  // check the SD card
  if (SDswitch == 1) {
    if (!SD.begin(4)) {
      u8x8.drawString(0, 2 , "No SD card!");
      u8x8.drawString(0, 3 , "Terminal Error!");
#ifdef DEBUG
      Serial.println("SD Card initialization failed!");
#endif
      while (1);
    }
    else {
      u8x8.drawString(0, 2 , "SD card found. ");
      delay(2000);    // to let user know
      u8x8.drawString(0, 2 , "               ");
#ifdef DEBUG
      Serial.println("SD Card found");
#endif
    }
  }
  else {
    u8x8.drawString(0, 2 , "No SD card");
    u8x8.drawString(0, 3 , "option");
    delay(2000);    // to let user know
    u8x8.drawString(0, 2 , "          ");
    u8x8.drawString(0, 3 , "      ");
#ifdef DEBUG
    Serial.println("No SD Card option");
#endif
  }
  delay(2000);    // to let user know about sd card
  // check if the WiFi module works
  if (WiFi.status() == WL_NO_SHIELD) {
#ifdef DEBUG
    Serial.println("WiFi shield not present");
#endif
    u8x8.drawString(0, 1 , "NO WiFi!");
    u8x8.drawString(0, 2 , "Terminal Error!");
    // don't continue:
    while (true);
  }

  // attempt to connect to WiFi network:
  u8x8.drawString(0, 2 , "Connecting.....");
  while ( status != WL_CONNECTED) {
#ifdef DEBUG
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
#endif
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);
    delay(10000); // wait 10 seconds for connection:
  }
  u8x8.drawString(0, 3 , "Connected!     ");
#ifdef DEBUG
  printWiFiStatus(); // you're connected now, so print out the status:
#endif
  rtc.begin();
  do {
    epoch = WiFi.getTime();
    numberOfTries++;
  }
  while ((epoch == 0) && (numberOfTries < maxTries));

  if (numberOfTries == maxTries) {
    u8x8.drawString(0, 4 , "NTP Unreachable");
    u8x8.drawString(0, 5 , "TERMINAL ERROR!");
#ifdef DEBUG
    Serial.print("NTP unreachable!!");
#endif
    while (1);
  }
  else {
    u8x8.drawString(0, 4 , "Got NTP Epoch  ");
    epoch = epoch + (GMT * 3600UL); // adjust offset for TZ/DST
    rtc.setEpoch(epoch);
#ifdef DEBUG
    Serial.print("Epoch received: ");
    Serial.print(epoch);
    Serial.print(" ");
    printP02D(rtc.getHours());
    Serial.print(":");
    printP02D(rtc.getMinutes());
    Serial.print(":");
    printP02D(rtc.getSeconds());
    Serial.print(" ");
    Serial.print(rtc.getDay());
    Serial.print("/");
    Serial.print(rtc.getMonth());
    Serial.print("/");
    Serial.print(rtc.getYear());
    Serial.println();
#endif
    WiFi.end();
    delay(15000);
    u8x8.drawString(0, 5 , "WiFi Ended     ");
    u8x8.drawString(0, 6 , "Starting BLE   ");
    delay(2000); // to see it on the screen
#ifdef DEBUG
    Serial.println("WiFi.end executed");
#endif
  }
  // Try to initialize BLE
  if (!BLE.begin()) {
    Serial.println("Terminal Error: Could not start BLE!");
    u8x8.clear();
    u8x8.drawString(0, 0 , "BLE Start Fail");
    u8x8.drawString(0, 1 , "Terminal Error!");
    while (1);
  }
  BLE.scan();
  u8x8.clear();
  u8x8.drawString(0, 0 , "Scanning......");
}
//------------------------------------------------------------------
void loop() {
  long lastMillis = 0;  // for period test
  long nowMillis = 0;   // for period test

  // check if a peripheral has been discovered
  peripheral = BLE.available();
  if (peripheral) {
    // discovered a peripheral, print out address and local name
#ifdef DEBUG
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.println("' ");
#endif
    if (peripheral.localName() == "CC2650 SensorTag") {
      BLE.stopScan(); // stop scanning
      // connect to the peripheral
      u8x8.drawString(0, 1 , "Connecting....");
#ifdef DEBUG
      Serial.print("Connecting to SensorTag ...");
#endif
      if (peripheral.connect()) {
        u8x8.drawString(0, 2 , "Connected.....");
#ifdef DEBUG
        Serial.println("Connected...");
#endif
        do_discovery(peripheral);
        // Note: we do not subscribe to any services because we are not using notify
        u8x8.clear();
        print_screenT();
#ifdef DEBUG
        Serial.println("Reading sensors...");
        Serial.println();
#endif
      }
      else {
        u8x8.drawString(0, 2 , "Scanning......");
#ifdef DEBUG
        Serial.println(" scanning");
#endif
      }
    }
    // main while connected loop
    while (peripheral.connected()) {
      read_BP(peripheral);
      read_OPT(peripheral);
      read_IRT(peripheral);
      read_HUM(peripheral);
      if (SDswitch) write_SDdata(); // write data to sd card
      // screen for debug no print here as well
#ifdef DEBUG
      print_data();
#endif
      print_screenValues();
      printclockD(1); // Update sensor clock
      printclockD(2); // update current clock
      lastmin = rtc.getMinutes();
      lastMillis = millis();
      // stay here until the period is up
      // update current time here
      while ( ( (nowMillis = millis()) - lastMillis) <= period) {
        // need to update the clock here
        if (lastmin != rtc.getMinutes()) {
          lastmin = rtc.getMinutes();
          printclockD(2); // update current clock
        }
      }
    }
    // peripheral disconnected, start scanning again
    u8x8.clear();
    u8x8.drawString(0, 2 , "Scanning......");
#ifdef DEBUG
    Serial.println(" - rescan...");
#endif
    BLE.scan();
  }
}
//------------------------------------------------------------------

// BLE SensorTag routines
void do_discovery(BLEDevice peripheral) {
  // discover the peripheral's attributes that we want
  // barometric
#ifdef DEBUG
  Serial.print("Discovering attributes for Barometric Pressure service ...");
#endif
  if (peripheral.discoverService("f000aa40-0451-4000-b000-000000000000")) {
#ifdef DEBUG
    Serial.println("discovered");
#endif
    BPConCharacteristic = peripheral.characteristic("f000aa42-0451-4000-b000-000000000000");
    BPValCharacteristic = peripheral.characteristic("f000aa41-0451-4000-b000-000000000000");
  }
  else  {
#ifdef DEBUG
    Serial.println("ERROR: Barometric Pressure service discovery failed.");
#endif
    peripheral.disconnect();
    return;
  }
  // discover the peripheral's attributes that we want
  // optical sensor
#ifdef DEBUG
  Serial.print("Discovering attributes for Luxometer service ...");
#endif
  if (peripheral.discoverService("f000aa70-0451-4000-b000-000000000000")) {
#ifdef DEBUG
    Serial.println("discovered");
#endif
    OPTConCharacteristic = peripheral.characteristic("f000aa72-0451-4000-b000-000000000000");
    OPTValCharacteristic = peripheral.characteristic("f000aa71-0451-4000-b000-000000000000");
  }
  else  {
#ifdef DEBUG
    Serial.println("Error: Luxometer service discovery failed.");
#endif
    peripheral.disconnect();
    return;
  }
  // IR
#ifdef DEBUG
  Serial.print("Discovering attributes for Infrared service ...");
#endif
  if (peripheral.discoverService("f000aa00-0451-4000-b000-000000000000")) {
#ifdef DEBUG
    Serial.println("discovered");
#endif
    IRTConCharacteristic = peripheral.characteristic("f000aa02-0451-4000-b000-000000000000");
    IRTValCharacteristic = peripheral.characteristic("f000aa01-0451-4000-b000-000000000000");
  }
  else  {
#ifdef DEBUG
    Serial.println("Error: Infrared service discovery failed.");
#endif
    peripheral.disconnect();
    return;
  }
  // humidity
#ifdef DEBUG
  Serial.print("Discovering attributes for Humidity service ...");
#endif
  if (peripheral.discoverService("f000aa20-0451-4000-b000-000000000000")) {
#ifdef DEBUG
    Serial.println("discovered");
#endif
    HUMConCharacteristic = peripheral.characteristic("f000aa22-0451-4000-b000-000000000000");
    HUMValCharacteristic = peripheral.characteristic("f000aa21-0451-4000-b000-000000000000");
  }
  else  {
#ifdef DEBUG
    Serial.println("Error: Humidity service discovery failed.");
#endif
    peripheral.disconnect();
    return;
  }
}

// Sensor reads
void read_BP(BLEDevice peripheral) {
  uint8_t holdvalues[6];

  if (peripheral.connected()) {
    // wake up the sensor
    BPConCharacteristic.writeValue(sensorOn);
    delay(1200); // wait for the sensor to do a read
    BPValCharacteristic.readValue(holdvalues, 6);
    unsigned long rawbptemp = (holdvalues[2] * 65536) + (holdvalues[1] * 256) + holdvalues[0];
    unsigned int rawbp = (holdvalues[5] * 65536) + (holdvalues[4] * 256) + holdvalues[3];
    // sleep sensor
    BPConCharacteristic.writeValue(sensorOff);
    // calculate temperature and pressure final values
    float bptemp = ((double)rawbptemp / 100.0);
    bptemp = ((bptemp * 9.0) / 5.0) + 32.0; // convert to F - comment out to leave at C
    float bp = ((double)rawbp / 100.0);
    // save into the structure
    SensorData.bp = bp;
    SensorData.bptemp = bptemp;
  }
  else {
#ifdef DEBUG
    Serial.println(" *not connected* ");
#endif
  }
}

void read_OPT(BLEDevice peripheral) {
  // in this version the characteristic's value is read directly
  // into rawlux and then processed. No array is used.

  uint16_t rawlux;

  if (peripheral.connected()) {
    // wake up the sensor
    OPTConCharacteristic.writeValue(sensorOn);
    delay(1200); // wait for the sensor to do a read
    OPTValCharacteristic.readValue(rawlux);
    OPTConCharacteristic.writeValue(sensorOff); // sleep sensor
    // calculate lux final value
    unsigned int m = rawlux & 0x0FFF;
    unsigned int e = (rawlux & 0xF000) >> 12;
    float lux = (m * (0.01 * pow(2.0, e)));
    // save into the structure
    SensorData.li = lux;
  }
  else {
#ifdef DEBUG
    Serial.println(" *not connected* ");
#endif
  }
}

void read_IRT(BLEDevice peripheral) {
  uint8_t holdvalues[4];

  if (peripheral.connected()) {
    // wake up the sensor
    IRTConCharacteristic.writeValue((uint8_t) 0x01);
    delay(1200); // wait for the sensor to do a read
    IRTValCharacteristic.readValue(holdvalues, 4);
    unsigned int rawobj = (holdvalues[0]) + (holdvalues[1] * 256);
    unsigned int rawamb = (holdvalues[2]) + (holdvalues[3] * 256);
    IRTConCharacteristic.writeValue(sensorOff); // sleep sensor
    // calculate final temperature values
    const float SCALE_LSB = 0.03125;
    int it = (int)( rawobj >> 2);
    float IRTo = ( (float)it) * SCALE_LSB;
    IRTo = ( (IRTo * 9.0) / 5.0 ) + 32.0; // convert to F - comment out to leave at C
    it = (int)(rawamb >> 2);
    float IRTa = (float)it * SCALE_LSB;
    IRTa = ( (IRTa * 9.0) / 5.0) + 32.0; // convert to F - comment out to leave at C
    // save into the structure
    SensorData.temd = IRTa;
    SensorData.temo = IRTo;
  }
  else {
#ifdef DEBUG
    Serial.println(" *not connected* ");
#endif
  }
}

void read_HUM(BLEDevice peripheral) {
  uint8_t holdvalues[4]; // hold the characteristic's bytes

  if (peripheral.connected()) {
    // wake up sensor
    HUMConCharacteristic.writeValue(sensorOn);
    delay(1200); // wait for the sensor to do a read
    HUMValCharacteristic.readValue(holdvalues, 4);
    HUMConCharacteristic.writeValue(sensorOff); // sleep sensor
    unsigned int rawtem = (holdvalues[0]) + (holdvalues[1] * 256);
    unsigned int rawhum = (holdvalues[2]) + (holdvalues[3] * 256);
    // calculate final temperature and relative humidity values
    float temp = (rawtem / 65536.0) * 165.0 - 40.0;
    temp = ((temp * 9.0) / 5.0) + 32.0; // convert to F - comment out to leave at C
    float hum = ((double)rawhum / 65536.0) * 100.0;
    // save into the structure
    SensorData.tem = temp;
    SensorData.hum = hum;
  }
  else {
#ifdef DEBUG
    Serial.println(" *not connected* ");
#endif
  }
}

// Print serial and screen and write SD routines
void print_data() {
  // Print the data to the serial moniter
  // NOTE: the time vars could be slightly different then the SD card
  // since they are two different routines but the Serial prints are
  // mainly for debugging

  String separator = ", ";
  // Data Line as follow (with comma separator):
  // epoch day, month, year, hours, minutes, seconds, HDC1000 temp, HDC1000 hum,
  // BMP280 pressure, BMP280 tem, OPT3001 light (lux), TMP007 temp, TMP0007 object temp
#ifdef DEBUG
  Serial.print(rtc.getEpoch());
  Serial.print(separator);
  Serial.print(rtc.getDay());
  Serial.print(separator);
  Serial.print(rtc.getMonth());
  Serial.print(separator);
  Serial.print(rtc.getYear());
  Serial.print(separator);
  printP02D(rtc.getHours());
  Serial.print(separator);
  printP02D(rtc.getMinutes());
  Serial.print(separator);
  printP02D(rtc.getSeconds());
  Serial.print(separator);
  Serial.print(SensorData.tem);
  Serial.print(separator);
  Serial.print(SensorData.hum);
  Serial.print(separator);
  Serial.print(SensorData.bp);
  Serial.print(separator);
  Serial.print(SensorData.bptemp);
  Serial.print(separator);
  Serial.print(SensorData.li);
  Serial.print(separator);
  Serial.print(SensorData.temo);
  Serial.print(separator);
  Serial.print(SensorData.temd);
  Serial.println();
  // end of data line
#endif
}

void write_SDdata() {
  // Write the data to the SD card
  String separator = ", ";

  // Data Line as follow (with comma separator):
  // epoch day, month, year, hours, minutes, seconds, HDC1000 temp, HDC1000 hum,
  // BMP280 pressure, BMP280 tem, OPT3001 light (lux), TMP007 temp, TMP0007 object temp
  // open the file
  SDF = SD.open(fname, FILE_WRITE);
  if (!SDF) {
    // terminal error if we can't open the SD File (we already initialized)
    u8x8.clearDisplay();
    u8x8.drawString(0, 2 , "SD Card    ");
    u8x8.drawString(0, 3 , "Terminal Error!");
#ifdef DEBUG
    Serial.println("SD card write failure!");
#endif
    while (1);
  }
  else {
    // write the separator-delimited data line
    // comment out what you don't want e.g.,
    // epoch, day,mon,year,hour,min,sec, HDC tem, HDC hum, AP, BMP tem, Illum, TMP obj Tem, TMP tem
    SDF.print(rtc.getEpoch());
    SDF.print(separator);
    SDF.print(rtc.getDay());
    SDF.print(separator);
    SDF.print(rtc.getMonth());
    SDF.print(separator);
    SDF.print(rtc.getYear());
    SDF.print(separator);
    SDF.print(rtc.getHours());
    SDF.print(separator);
    SDF.print(rtc.getMinutes());
    SDF.print(separator);
    SDF.print(rtc.getSeconds());
    SDF.print(separator);
    SDF.print(SensorData.tem);
    SDF.print(separator);
    SDF.print(SensorData.hum);
    SDF.print(separator);
    SDF.print(SensorData.bp);
    SDF.print(separator);
    SDF.print(SensorData.bptemp);
    SDF.print(separator);
    SDF.print(SensorData.li);
    SDF.print(separator);
    SDF.print(SensorData.temo);
    SDF.print(separator);
    SDF.print(SensorData.temd);
    SDF.println();  // Windows cr/lf
    SDF.close();
  }
}

void print_screenT() {
  // print the LCD template
  u8x8.setFont(u8x8_font_px437wyse700a_2x2_f);   // large for Tem/Hum
  u8x8.drawString(0, 0, "T:");
  u8x8.drawUTF8(14, 0, degree);
  u8x8.drawString(0, 2, "H:");
  u8x8.drawUTF8(14, 2, percent);
  // back to smaller font for tyhe rest
  u8x8.setFont(u8x8_font_amstrad_cpc_extended_f);
  u8x8.drawString(0, 5, "AP:");
  //u8x8.drawString(0, 5, "BP:    0123 hPa");
  u8x8.setCursor(10, 5);
  u8x8.print(" hPa");
  u8x8.drawString(0, 6, "IL:");
  u8x8.setCursor(10, 6);
  u8x8.print(" lux");
  // alternative times current left
  u8x8.drawString(0, 7, "00:00");
  u8x8.drawString(11, 7, "00:00");
}

void print_screenValues() {
  float Dtem, Dhum, Dap, Dli;
  // call this *after* sensor structure has been updated
  // first update the logged time? need small font
  u8x8.setFont(u8x8_font_px437wyse700a_2x2_f);   // large for Tem/Hum
  // temperature
  // sensor error check NOTE: read values will be printed to screen and SD
  Dtem = SensorData.tem;
  if (Dtem > 999.9) Dtem = 999.9;
  if (Dtem < -99.9) Dtem = -99.9;
  dtostrf(Dtem, 5, 1, p_buffer); // convert to 5 chars 1 after decimal
  u8x8.setCursor(4, 0);
  u8x8.print(p_buffer);
  //u8x8.drawUTF8(14, 0, degree); degree sign has been done in
  // humidity
  // sensor error check
  Dhum = SensorData.hum;
  if (Dhum > 100.0) Dhum = 100.0;
  if (Dhum < 0.0) Dhum = 0.0;
  dtostrf(Dhum, 5, 1, p_buffer); // convert to 5 chars 1 after decimal
  u8x8.setCursor(4, 2);
  u8x8.print(p_buffer);
  //u8x8.drawUTF8(14, 2, percent);  already done in template print
  // back to smaller font for tyhe rest
  u8x8.setFont(u8x8_font_amstrad_cpc_extended_f);
  // barometric pressure
  // sensor error check
  Dap = SensorData.bp;
  if (Dap < 750.0) Dap = 000.0;
  if (Dap > 1200.0) Dap = 9999.9;
  dtostrf(Dap, 7, 1, p_buffer); // convert to 7 chars 1 after decimal
  u8x8.setCursor(3, 5);
  u8x8.print(p_buffer);
  // Illuminance
  // sensor error check
  Dli = SensorData.li;
  if (Dli > 99999.9) Dli = 99999.9;
  if (Dli < 0.0) Dli = 0;
  dtostrf(Dli, 7, 1, p_buffer); // convert to 7 chars 1 after decimal
  u8x8.setCursor(3, 6);
  u8x8.print(p_buffer);
}

void printclockD(byte side) {
  // print the HH:SS of the current clock on the right or left side of the LCD
  // must be in a small font! (could do this as a switch case)
int hourT,minT;

  switch (side) {
    case 1: //left side
      u8x8.setCursor(0, 7);
      hourT = rtc.getHours();
      if (hourT < 10) { // pad hours <10
        u8x8.drawString(0, 7 , "0");
        u8x8.setCursor(1, 7);
        u8x8.print(hourT);
      }
      else {
        u8x8.print(hourT);
      }
      // note the ':' is from the template
      u8x8.setCursor(3, 7);
      minT = rtc.getMinutes();
      if (minT < 10) { // pad seconds <10
        u8x8.drawString(3, 7 , "0");
        u8x8.setCursor(4, 7);
        u8x8.print(minT);
      }
      else {
        u8x8.print(minT);
      }
      break;
    case 2: // right side
      u8x8.setCursor(11, 7);
      hourT = rtc.getHours();
      if (hourT < 10) { // pad hours <10
        u8x8.drawString(11, 7 , "0");
        u8x8.setCursor(12, 7);
        u8x8.print(hourT);
      }
      else {
        u8x8.print(hourT);
      }
      // note the ':' is from the template
      u8x8.setCursor(14, 7);
      minT = rtc.getMinutes();
      if (minT < 10) { // pad secondss <10
        u8x8.drawString(14, 7 , "0");
        u8x8.setCursor(15, 7);
        u8x8.print(minT);
      }
      else {
        u8x8.print(minT);
      }
      break;
    default:  // can add other options
      // statements
      break;
  }
}

void printWiFiStatus() {
  // note: this will only be called if DEBUG is defines
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

void printP02D(int number) {
  if (number < 10) Serial.print('0');
  Serial.print(number);
}

// End of code

YADL_V1_0R

Arduino
Complete program code for the data logger
//*********************************************************************************
// YADL SensorTag Data Logger v1.0R [DrG]
//  ** This software is offered strictly as is with no guarantees or warranties. **
//  ** - USE IT AT YOUR OWN RISK!                                                **
//*********************************************************************************
//
// Uses:
// WiFiNINA v1.40
// RTCZero 1.6.0
// ArduinoBLE v1.1.1
// SD v1.2.3
// U8g2 (U8x8) v2.26.14
//
// Arduino IDE v1.8.10
//
// Hardware:
// MKR1010 / NANO 33 IOT (both have been tested)
// microSD card (both generics and MicroElectronika click board tested)
// HiLetgo 1.3" I2C monochrome OLED (others should work with modification)
//
// Note: Replace the code entries below with your network info:
// char ssid[] = "XXXXXXXXXX";
// char pass[] = "XXXXXXXXXX";
//
// Note: set GMT (with DST if needed) in code entry:
// const int GMT =XX
//
// #includes
#include <WiFiNINA.h>
#include <RTCZero.h>
#include <ArduinoBLE.h>
#include <SPI.h>
#include <SD.h>
#include <U8x8lib.h>
#include <avr/dtostrf.h> // needed for MKR1010

//#define DEBUG  // uncomment this line for serial monitor output

RTCZero rtc;
BLEDevice peripheral;
File SDF;

U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE);

// Global structure to hold the sensor data
struct DATA {
  float tem;     // HDC1000 temperature F
  float hum;     // HDC1000 relative humidity %RH
  float bptemp;  // BMP 280 die temperature F
  float bp;      // BMP 280 barometric pressure in hectoPascals (1 hPa = 100 Pa)
  float li;      // OPT3001 lux
  float temd;    // TMP007 die temperature F
  float temo;    // TMP007 object temperature F
};

typedef struct DATA DATA;
DATA SensorData;

// for SensorTag sensors
uint8_t sensorOn = 1;
uint8_t sensorOff = 0;

// lcd vars
char degree[] = {0xb0, 0x00};
char percent[] = {0x25, 0x00};
char p_buffer[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

// clock change catcher
int lastmin;

// for RTC
unsigned long epoch;
int numberOfTries = 0, maxTries = 6;

int status = WL_IDLE_STATUS;  // WiFiNINA use

// Common user-changeable switches
const int GMT = -2; //change this to adapt it to your time zone
byte SDswitch = 1;  // SDswitch 1=ON (write to SD) or 0 (Do not write to SD)
char fname[] = "STDATA.txt"; // data log file Name

//period defines the length of time between measurements in milliseconds
// note that this does not includes delays for sensor reads (~8.7 sec)
long period = 600000L; // 10 minutes
//long period = 5000L;  // 5 sec for testing

char ssid[] = "";   // your network SSID (name)
char pass[] = "";   // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;             // your network key Index number (needed only for WEP)

// SensorTag characteristic definitions
// BMP280
BLECharacteristic BPConCharacteristic;
BLECharacteristic BPValCharacteristic;
// OPT3001
BLECharacteristic OPTConCharacteristic;
BLECharacteristic OPTValCharacteristic;
// TMP007
BLECharacteristic IRTConCharacteristic;
BLECharacteristic IRTValCharacteristic;
// HDC1000
BLECharacteristic HUMConCharacteristic;
BLECharacteristic HUMValCharacteristic;
//------------------------------------------------------------------

void setup() {
  u8x8.begin(); // start lcd driver, will clear display
  u8x8.setFont(u8x8_font_amstrad_cpc_extended_f); // 8 X 8 font
  u8x8.drawString(0, 0, "YADL starting...");
#ifdef DEBUG
  Serial.begin(9600);
  delay(5000);  // delay for user to open the serial monitor
  Serial.println("YADL MKR1010/NANO IOT 33 SensorTag Data Logger");
  Serial.println();
#endif
  // check the SD card
  if (SDswitch == 1) {
    if (!SD.begin(4)) {
      u8x8.drawString(0, 2 , "No SD card!");
      u8x8.drawString(0, 3 , "Terminal Error!");
#ifdef DEBUG
      Serial.println("SD Card initialization failed!");
#endif
      while (1);
    }
    else {
      u8x8.drawString(0, 2 , "SD card found. ");
      delay(2000);    // to let user know
      u8x8.drawString(0, 2 , "               ");
#ifdef DEBUG
      Serial.println("SD Card found");
#endif
    }
  }
  else {
    u8x8.drawString(0, 2 , "No SD card");
    u8x8.drawString(0, 3 , "option");
    delay(2000);    // to let user know
    u8x8.drawString(0, 2 , "          ");
    u8x8.drawString(0, 3 , "      ");
#ifdef DEBUG
    Serial.println("No SD Card option");
#endif
  }
  delay(2000);    // to let user know about sd card
  // check if the WiFi module works
  if (WiFi.status() == WL_NO_SHIELD) {
#ifdef DEBUG
    Serial.println("WiFi shield not present");
#endif
    u8x8.drawString(0, 1 , "NO WiFi!");
    u8x8.drawString(0, 2 , "Terminal Error!");
    // don't continue:
    while (true);
  }

  // attempt to connect to WiFi network:
  u8x8.drawString(0, 2 , "Connecting.....");
  while ( status != WL_CONNECTED) {
#ifdef DEBUG
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
#endif
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);
    delay(10000); // wait 10 seconds for connection:
  }
  u8x8.drawString(0, 3 , "Connected!     ");
#ifdef DEBUG
  printWiFiStatus(); // you're connected now, so print out the status:
#endif
  rtc.begin();
  do {
    epoch = WiFi.getTime();
    numberOfTries++;
  }
  while ((epoch == 0) && (numberOfTries < maxTries));

  if (numberOfTries == maxTries) {
    u8x8.drawString(0, 4 , "NTP Unreachable");
    u8x8.drawString(0, 5 , "TERMINAL ERROR!");
#ifdef DEBUG
    Serial.print("NTP unreachable!!");
#endif
    while (1);
  }
  else {
    u8x8.drawString(0, 4 , "Got NTP Epoch  ");
    epoch = epoch + (GMT * 3600UL); // adjust offset for TZ/DST
    rtc.setEpoch(epoch);
#ifdef DEBUG
    Serial.print("Epoch received: ");
    Serial.print(epoch);
    Serial.print(" ");
    printP02D(rtc.getHours());
    Serial.print(":");
    printP02D(rtc.getMinutes());
    Serial.print(":");
    printP02D(rtc.getSeconds());
    Serial.print(" ");
    Serial.print(rtc.getDay());
    Serial.print("/");
    Serial.print(rtc.getMonth());
    Serial.print("/");
    Serial.print(rtc.getYear());
    Serial.println();
#endif
    WiFi.end();
    delay(15000);
    u8x8.drawString(0, 5 , "WiFi Ended     ");
    u8x8.drawString(0, 6 , "Starting BLE   ");
    delay(2000); // to see it on the screen
#ifdef DEBUG
    Serial.println("WiFi.end executed");
#endif
  }
  // Try to initialize BLE
  if (!BLE.begin()) {
    Serial.println("Terminal Error: Could not start BLE!");
    u8x8.clear();
    u8x8.drawString(0, 0 , "BLE Start Fail");
    u8x8.drawString(0, 1 , "Terminal Error!");
    while (1);
  }
  BLE.scan();
  u8x8.clear();
  u8x8.drawString(0, 0 , "Scanning......");
}
//------------------------------------------------------------------
void loop() {
  long lastMillis = 0;  // for period test
  long nowMillis = 0;   // for period test

  // check if a peripheral has been discovered
  peripheral = BLE.available();
  if (peripheral) {
    // discovered a peripheral, print out address and local name
#ifdef DEBUG
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.println("' ");
#endif
    if (peripheral.localName() == "CC2650 SensorTag") {
      BLE.stopScan(); // stop scanning
      // connect to the peripheral
      u8x8.drawString(0, 1 , "Connecting....");
#ifdef DEBUG
      Serial.print("Connecting to SensorTag ...");
#endif
      if (peripheral.connect()) {
        u8x8.drawString(0, 2 , "Connected.....");
#ifdef DEBUG
        Serial.println("Connected...");
#endif
        do_discovery(peripheral);
        // Note: we do not subscribe to any services because we are not using notify
        u8x8.clear();
        print_screenT();
#ifdef DEBUG
        Serial.println("Reading sensors...");
        Serial.println();
#endif
      }
      else {
        u8x8.drawString(0, 2 , "Scanning......");
#ifdef DEBUG
        Serial.println(" scanning");
#endif
      }
    }
    // main while connected loop
    while (peripheral.connected()) {
      read_BP(peripheral);
      read_OPT(peripheral);
      read_IRT(peripheral);
      read_HUM(peripheral);
      if (SDswitch) write_SDdata(); // write data to sd card
      // screen for debug no print here as well
#ifdef DEBUG
      print_data();
#endif
      print_screenValues();
      printclockD(1); // Update sensor clock
      printclockD(2); // update current clock
      lastmin = rtc.getMinutes();
      lastMillis = millis();
      // stay here until the period is up
      // update current time here
      while ( ( (nowMillis = millis()) - lastMillis) <= period) {
        // need to update the clock here
        if (lastmin != rtc.getMinutes()) {
          lastmin = rtc.getMinutes();
          printclockD(2); // update current clock
        }
      }
    }
    // peripheral disconnected, start scanning again
    u8x8.clear();
    u8x8.drawString(0, 2 , "Scanning......");
#ifdef DEBUG
    Serial.println(" - rescan...");
#endif
    BLE.scan();
  }
}
//------------------------------------------------------------------

// BLE SensorTag routines
void do_discovery(BLEDevice peripheral) {
  // discover the peripheral's attributes that we want
  // barometric
#ifdef DEBUG
  Serial.print("Discovering attributes for Barometric Pressure service ...");
#endif
  if (peripheral.discoverService("f000aa40-0451-4000-b000-000000000000")) {
#ifdef DEBUG
    Serial.println("discovered");
#endif
    BPConCharacteristic = peripheral.characteristic("f000aa42-0451-4000-b000-000000000000");
    BPValCharacteristic = peripheral.characteristic("f000aa41-0451-4000-b000-000000000000");
  }
  else  {
#ifdef DEBUG
    Serial.println("ERROR: Barometric Pressure service discovery failed.");
#endif
    peripheral.disconnect();
    return;
  }
  // discover the peripheral's attributes that we want
  // optical sensor
#ifdef DEBUG
  Serial.print("Discovering attributes for Luxometer service ...");
#endif
  if (peripheral.discoverService("f000aa70-0451-4000-b000-000000000000")) {
#ifdef DEBUG
    Serial.println("discovered");
#endif
    OPTConCharacteristic = peripheral.characteristic("f000aa72-0451-4000-b000-000000000000");
    OPTValCharacteristic = peripheral.characteristic("f000aa71-0451-4000-b000-000000000000");
  }
  else  {
#ifdef DEBUG
    Serial.println("Error: Luxometer service discovery failed.");
#endif
    peripheral.disconnect();
    return;
  }
  // IR
#ifdef DEBUG
  Serial.print("Discovering attributes for Infrared service ...");
#endif
  if (peripheral.discoverService("f000aa00-0451-4000-b000-000000000000")) {
#ifdef DEBUG
    Serial.println("discovered");
#endif
    IRTConCharacteristic = peripheral.characteristic("f000aa02-0451-4000-b000-000000000000");
    IRTValCharacteristic = peripheral.characteristic("f000aa01-0451-4000-b000-000000000000");
  }
  else  {
#ifdef DEBUG
    Serial.println("Error: Infrared service discovery failed.");
#endif
    peripheral.disconnect();
    return;
  }
  // humidity
#ifdef DEBUG
  Serial.print("Discovering attributes for Humidity service ...");
#endif
  if (peripheral.discoverService("f000aa20-0451-4000-b000-000000000000")) {
#ifdef DEBUG
    Serial.println("discovered");
#endif
    HUMConCharacteristic = peripheral.characteristic("f000aa22-0451-4000-b000-000000000000");
    HUMValCharacteristic = peripheral.characteristic("f000aa21-0451-4000-b000-000000000000");
  }
  else  {
#ifdef DEBUG
    Serial.println("Error: Humidity service discovery failed.");
#endif
    peripheral.disconnect();
    return;
  }
}

// Sensor reads
void read_BP(BLEDevice peripheral) {
  uint8_t holdvalues[6];

  if (peripheral.connected()) {
    // wake up the sensor
    BPConCharacteristic.writeValue(sensorOn);
    delay(1200); // wait for the sensor to do a read
    BPValCharacteristic.readValue(holdvalues, 6);
    unsigned long rawbptemp = (holdvalues[2] * 65536) + (holdvalues[1] * 256) + holdvalues[0];
    unsigned int rawbp = (holdvalues[5] * 65536) + (holdvalues[4] * 256) + holdvalues[3];
    // sleep sensor
    BPConCharacteristic.writeValue(sensorOff);
    // calculate temperature and pressure final values
    float bptemp = ((double)rawbptemp / 100.0);
    bptemp = ((bptemp * 9.0) / 5.0) + 32.0; // convert to F - comment out to leave at C
    float bp = ((double)rawbp / 100.0);
    // save into the structure
    SensorData.bp = bp;
    SensorData.bptemp = bptemp;
  }
  else {
#ifdef DEBUG
    Serial.println(" *not connected* ");
#endif
  }
}

void read_OPT(BLEDevice peripheral) {
  // for this sensor the characteristic's value is read directly
  // into rawlux and then processed. No array is used.

  uint16_t rawlux;

  if (peripheral.connected()) {
    // wake up the sensor
    OPTConCharacteristic.writeValue(sensorOn);
    delay(1200); // wait for the sensor to do a read
    OPTValCharacteristic.readValue(rawlux);
    OPTConCharacteristic.writeValue(sensorOff); // sleep sensor
    // calculate lux final value
    unsigned int m = rawlux & 0x0FFF;
    unsigned int e = (rawlux & 0xF000) >> 12;
    float lux = (m * (0.01 * pow(2.0, e)));
    // save into the structure
    SensorData.li = lux;
  }
  else {
#ifdef DEBUG
    Serial.println(" *not connected* ");
#endif
  }
}

void read_IRT(BLEDevice peripheral) {
  uint8_t holdvalues[4];

  if (peripheral.connected()) {
    // wake up the sensor
    IRTConCharacteristic.writeValue((uint8_t) 0x01);
    delay(1200); // wait for the sensor to do a read
    IRTValCharacteristic.readValue(holdvalues, 4);
    unsigned int rawobj = (holdvalues[0]) + (holdvalues[1] * 256);
    unsigned int rawamb = (holdvalues[2]) + (holdvalues[3] * 256);
    IRTConCharacteristic.writeValue(sensorOff); // sleep sensor
    // calculate final temperature values
    const float SCALE_LSB = 0.03125;
    int it = (int)( rawobj >> 2);
    float IRTo = ( (float)it) * SCALE_LSB;
    IRTo = ( (IRTo * 9.0) / 5.0 ) + 32.0; // convert to F - comment out to leave at C
    it = (int)(rawamb >> 2);
    float IRTa = (float)it * SCALE_LSB;
    IRTa = ( (IRTa * 9.0) / 5.0) + 32.0; // convert to F - comment out to leave at C
    // save into the structure
    SensorData.temd = IRTa;
    SensorData.temo = IRTo;
  }
  else {
#ifdef DEBUG
    Serial.println(" *not connected* ");
#endif
  }
}

void read_HUM(BLEDevice peripheral) {
  uint8_t holdvalues[4]; // hold the characteristic's bytes

  if (peripheral.connected()) {
    // wake up sensor
    HUMConCharacteristic.writeValue(sensorOn);
    delay(1200); // wait for the sensor to do a read
    HUMValCharacteristic.readValue(holdvalues, 4);
    HUMConCharacteristic.writeValue(sensorOff); // sleep sensor
    unsigned int rawtem = (holdvalues[0]) + (holdvalues[1] * 256);
    unsigned int rawhum = (holdvalues[2]) + (holdvalues[3] * 256);
    // calculate final temperature and relative humidity values
    float temp = (rawtem / 65536.0) * 165.0 - 40.0;
    temp = ((temp * 9.0) / 5.0) + 32.0; // convert to F - comment out to leave at C
    float hum = ((double)rawhum / 65536.0) * 100.0;
    // save into the structure
    SensorData.tem = temp;
    SensorData.hum = hum;
  }
  else {
#ifdef DEBUG
    Serial.println(" *not connected* ");
#endif
  }
}

// Print serial and screen and write SD routines
void print_data() {
  // Print the data to the serial moniter
  // NOTE: the time vars could be slightly different than the SD card
  // since they are two different routines but the Serial prints are
  // mainly for debugging

  String separator = ", ";
  // Data Line as follow (with comma separator):
  // epoch day, month, year, hours, minutes, seconds, HDC1000 temp, HDC1000 hum,
  // BMP280 pressure, BMP280 tem, OPT3001 light (lux), TMP007 object temp, TMP007 temp
#ifdef DEBUG
  Serial.print(rtc.getEpoch());
  Serial.print(separator);
  Serial.print(rtc.getDay());
  Serial.print(separator);
  Serial.print(rtc.getMonth());
  Serial.print(separator);
  Serial.print(rtc.getYear());
  Serial.print(separator);
  printP02D(rtc.getHours());
  Serial.print(separator);
  printP02D(rtc.getMinutes());
  Serial.print(separator);
  printP02D(rtc.getSeconds());
  Serial.print(separator);
  Serial.print(SensorData.tem);
  Serial.print(separator);
  Serial.print(SensorData.hum);
  Serial.print(separator);
  Serial.print(SensorData.bp);
  Serial.print(separator);
  Serial.print(SensorData.bptemp);
  Serial.print(separator);
  Serial.print(SensorData.li);
  Serial.print(separator);
  Serial.print(SensorData.temo);
  Serial.print(separator);
  Serial.print(SensorData.temd);
  Serial.println();
  // end of data line
#endif
}

void write_SDdata() {
  // Write the data to the SD card
  String separator = ", ";

  // Data Line as follow (with comma separator):
  // epoch day, month, year, hours, minutes, seconds, HDC1000 temp, HDC1000 hum,
  // BMP280 pressure, BMP280 tem, OPT3001 light (lux), TMP007 temp, TMP0007 object temp
  // open the file
  SDF = SD.open(fname, FILE_WRITE);
  if (!SDF) {
    // terminal error if we can't open the SD File (we already initialized)
    u8x8.clearDisplay();
    u8x8.drawString(0, 2 , "SD Card    ");
    u8x8.drawString(0, 3 , "Terminal Error!");
#ifdef DEBUG
    Serial.println("SD card write failure!");
#endif
    while (1);
  }
  else {
    // write the separator-delimited data line
    // comment out what you don't want e.g.,
    // epoch, day,mon,year,hour,min,sec, HDC tem, HDC hum, AP, BMP tem, Illum, TMP obj Tem, TMP tem
    SDF.print(rtc.getEpoch());
    SDF.print(separator);
    SDF.print(rtc.getDay());
    SDF.print(separator);
    SDF.print(rtc.getMonth());
    SDF.print(separator);
    SDF.print(rtc.getYear());
    SDF.print(separator);
    SDF.print(rtc.getHours());
    SDF.print(separator);
    SDF.print(rtc.getMinutes());
    SDF.print(separator);
    SDF.print(rtc.getSeconds());
    SDF.print(separator);
    SDF.print(SensorData.tem);
    SDF.print(separator);
    SDF.print(SensorData.hum);
    SDF.print(separator);
    SDF.print(SensorData.bp);
    SDF.print(separator);
    SDF.print(SensorData.bptemp);
    SDF.print(separator);
    SDF.print(SensorData.li);
    SDF.print(separator);
    SDF.print(SensorData.temo);
    SDF.print(separator);
    SDF.print(SensorData.temd);
    SDF.println();  // Windows cr/lf
    SDF.close();
  }
}

void print_screenT() {
  // print the LCD template
  u8x8.setFont(u8x8_font_px437wyse700a_2x2_f);   // large for Tem/Hum
  u8x8.drawString(0, 0, "T:");
  u8x8.drawUTF8(14, 0, degree);
  u8x8.drawString(0, 2, "H:");
  u8x8.drawUTF8(14, 2, percent);
  // back to smaller font for tyhe rest
  u8x8.setFont(u8x8_font_amstrad_cpc_extended_f);
  u8x8.drawString(0, 5, "AP:");
  //u8x8.drawString(0, 5, "BP:    0123 hPa");
  u8x8.setCursor(10, 5);
  u8x8.print(" hPa");
  u8x8.drawString(0, 6, "IL:");
  u8x8.setCursor(10, 6);
  u8x8.print(" lux");
  // alternative times current left
  u8x8.drawString(0, 7, "00:00");
  u8x8.drawString(11, 7, "00:00");
}

void print_screenValues() {
  float Dtem, Dhum, Dap, Dli;
  // call this *after* sensor structure has been updated
  // first update the logged time? need small font
  u8x8.setFont(u8x8_font_px437wyse700a_2x2_f);   // large for Tem/Hum
  // temperature
  // sensor error check NOTE: read values will be printed to screen and SD
  Dtem = SensorData.tem;
  if (Dtem > 999.9) Dtem = 999.9;
  if (Dtem < -99.9) Dtem = -99.9;
  dtostrf(Dtem, 5, 1, p_buffer); // convert to 5 chars 1 after decimal
  u8x8.setCursor(4, 0);
  u8x8.print(p_buffer);
  //u8x8.drawUTF8(14, 0, degree); degree sign has been done in
  // humidity
  // sensor error check
  Dhum = SensorData.hum;
  if (Dhum > 100.0) Dhum = 100.0;
  if (Dhum < 0.0) Dhum = 0.0;
  dtostrf(Dhum, 5, 1, p_buffer); // convert to 5 chars 1 after decimal
  u8x8.setCursor(4, 2);
  u8x8.print(p_buffer);
  //u8x8.drawUTF8(14, 2, percent);  already done in template print
  // back to smaller font for tyhe rest
  u8x8.setFont(u8x8_font_amstrad_cpc_extended_f);
  // barometric pressure
  // sensor error check
  Dap = SensorData.bp;
  if (Dap < 750.0) Dap = 000.0;
  if (Dap > 1200.0) Dap = 9999.9;
  dtostrf(Dap, 7, 1, p_buffer); // convert to 7 chars 1 after decimal
  u8x8.setCursor(3, 5);
  u8x8.print(p_buffer);
  // Illuminance
  // sensor error check
  Dli = SensorData.li;
  if (Dli > 99999.9) Dli = 99999.9;
  if (Dli < 0.0) Dli = 0;
  dtostrf(Dli, 7, 1, p_buffer); // convert to 7 chars 1 after decimal
  u8x8.setCursor(3, 6);
  u8x8.print(p_buffer);
}

void printclockD(byte side) {
  // print the HH:SS of the current clock on the right or left side of the LCD
  // must be in a small font! (could do this as a switch case)
int hourT,minT;

  switch (side) {
    case 1: //left side
      u8x8.setCursor(0, 7);
      hourT = rtc.getHours();
      if (hourT < 10) { // pad hours <10
        u8x8.drawString(0, 7 , "0");
        u8x8.setCursor(1, 7);
        u8x8.print(hourT);
      }
      else {
        u8x8.print(hourT);
      }
      // note the ':' is from the template
      u8x8.setCursor(3, 7);
      minT = rtc.getMinutes();
      if (minT < 10) { // pad seconds <10
        u8x8.drawString(3, 7 , "0");
        u8x8.setCursor(4, 7);
        u8x8.print(minT);
      }
      else {
        u8x8.print(minT);
      }
      break;
    case 2: // right side
      u8x8.setCursor(11, 7);
      hourT = rtc.getHours();
      if (hourT < 10) { // pad hours <10
        u8x8.drawString(11, 7 , "0");
        u8x8.setCursor(12, 7);
        u8x8.print(hourT);
      }
      else {
        u8x8.print(hourT);
      }
      // note the ':' is from the template
      u8x8.setCursor(14, 7);
      minT = rtc.getMinutes();
      if (minT < 10) { // pad secondss <10
        u8x8.drawString(14, 7 , "0");
        u8x8.setCursor(15, 7);
        u8x8.print(minT);
      }
      else {
        u8x8.print(minT);
      }
      break;
    default:  // can add other options
      // statements
      break;
  }
}

void printWiFiStatus() {
  // note: this will only be called if DEBUG is defines
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

void printP02D(int number) {
  if (number < 10) Serial.print('0');
  Serial.print(number);
}

// End of code

Credits

DrGee

DrGee

0 projects • 5 followers

Comments