LightBlue data presentation

I just completed my first project with a NANO 33 Sense. It is a temperature-based, variable speed fan controller for my stereo cabinet. It was a blast to code and working exactly as I wanted with the exception of how the data is presented in LightBlue. After I connect my four characteristics are displayed but I have to click on each one to see their value and covert from HEX every time. I cannot figure out how to display the characteristics values on the front page and set the default data type. Any help would be greatly appreciated.

Have you forgotten something (s)?

Not sure I understand your response. I'm looking to get the values of the characteristics on the front page of LightBlue. I have to click on each and then convert from Hex. I have found screenshots of what I'm trying to do but cannot find any tutorials.

Here is my code

/*
    PWM Fan controller
    2021-03-29  GSY
*/

#include <Arduino_HTS221.h>
#include <ArduinoBLE.h>

BLEService fanService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service

// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEFloatCharacteristic  currentTempCharacteristic("C0001", BLERead | BLENotify);
BLEFloatCharacteristic  maxTempCharacteristic("C0002", BLERead);
BLEIntCharacteristic fanPercentPowerCharacteristic("C0003", BLERead | BLEWrite);
BLEIntCharacteristic bleOverRideCharacteristic("C0004", BLERead | BLEWrite);

const int pinLED = LED_BUILTIN;   // pin to use for the LED
const int pinFan_PWM_Control = 9; //ditial pin used to set PWM      --blue
const int pinFan_RPM_Control = 3; //digital pin used to read RPM    --green
const int secondDelay = 3000;     //number of seconds to determine RPS speed
const int minCabinetTemp = 85;    //temperatue the fan is enabled
const int maxCabinetTemp = 100;   //temperatue the fan reaches 100%
const int maxFanPercent = 100;    //not sure why this not always be 100
const int minFanPercent = 50;     //initial speed of the fan
const int fanStep = 10;           //round the fan to nearest percentage,  also increase the starting temperate by the first step.  This should be a small number because it will delay when the fan starts

float maxTemp = 0;                //used to store max temp, informational only
float minTemp = 0;                //used to store min temp, informational only
int fanPercentPower = 0;          //computed by temparture,  should have values between 0-100
int fanPWM = 255;                 //used to set PWM to the fan, coverts fanPercentPower to 0-255
bool firstLoop = 1;               //
bool bleOverRide = 0;
int intFanRPM_Counter = 0;        //counter used to count RPM revolutions


void setup() {
  // set PWM pin to output mode
  pinMode(pinFan_PWM_Control, OUTPUT);
  // set LED pin to output mode
  pinMode(pinLED, OUTPUT);

  Serial.begin(9600);
  //comment out while(!Serial) when ready to use,  with this line the program will not start unless the Serial Monitor is started
  //while (!Serial);        //wait for the serial monitor to start
  delay(5000);              //delay a few seconds to allow the monitor to start, not sure the process needs to wait.  May miss the first few messages
  
  if (!HTS.begin()) {
    Serial.println("Failed to initialize humidity temperature sensor!");
    while (1);
  }

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");

    while (1);
  }

  // set advertised local name and service UUID:
  BLE.setLocalName("Cabinet Fan");
  BLE.setAdvertisedService(fanService);

  //2901 seems to important because it doesn't work with other values
  BLEDescriptor currentTempDescriptor("2901", "Current Temp");
  currentTempCharacteristic.addDescriptor(currentTempDescriptor);

  BLEDescriptor maxTempDescriptor("2901", "Maximum Temp");
  maxTempCharacteristic.addDescriptor(maxTempDescriptor);

  BLEDescriptor fanPercentPowerDescriptor("2901", "Fan Power");
  fanPercentPowerCharacteristic.addDescriptor(fanPercentPowerDescriptor);

  BLEDescriptor bleOverRideDescriptor("2901", "Override Fan Power Settings");
  bleOverRideCharacteristic.addDescriptor(bleOverRideDescriptor);

  // add the characteristic to the service
  fanService.addCharacteristic(currentTempCharacteristic);
  fanService.addCharacteristic(maxTempCharacteristic);
  fanService.addCharacteristic(fanPercentPowerCharacteristic);
  fanService.addCharacteristic(bleOverRideCharacteristic);

  // add service
  BLE.addService(fanService);

  // set the initial value for the characeristic:
  currentTempCharacteristic.writeValue(0);
  maxTempCharacteristic.writeValue(0);
  fanPercentPowerCharacteristic.writeValue(maxFanPercent);
  bleOverRideCharacteristic.writeValue(0);

  // start advertising
  BLE.advertise();

  Serial.println("BLE Cabinet Fan Controller");

  //set 
  attachInterrupt(digitalPinToInterrupt(pinFan_RPM_Control), fnFanCounter, FALLING);    //I do not understand why this FALLING,  most of the examples use RISING but that didnt' work for me.
}

void loop() {
  float currentTemp = HTS.readTemperature();
  float currentMillis;
  int currentFanRPM;

  //Convert to F
  currentTemp = (currentTemp * 1.8) + 32;

  //track max & min temperatures
  if (firstLoop) {
    minTemp = currentTemp;
    maxTemp = currentTemp;
    firstLoop = 0;
  } else if (currentTemp < minTemp) {
    minTemp = currentTemp;
  } else if (currentTemp > maxTemp) {
    maxTemp = currentTemp;
  }

  //calculate the Fan speed
  if (!bleOverRide) {
    if (minTemp > 0) {
      if (currentTemp > minCabinetTemp) {
        //starting min which will probably be 50%
        fanPercentPower = (int)map((int)currentTemp, minCabinetTemp, maxCabinetTemp, minFanPercent, maxFanPercent);
      } else {
        //once the temp lowers until threshold,  disable and reset override
        fanPercentPower = 0;
      }
    } else {
      //probably never going to hit this condition
      fanPercentPower = 0;
    }
  } else {
    //read user setting
    fanPercentPower = fanPercentPowerCharacteristic.value();
  }

  if (fanPercentPower < 0) {
    //can only happen if user enters value
    fanPercentPower = 0;
  } else if (fanPercentPower > maxFanPercent) {
    //will happen if current temperature is greater than max tempature,  anything above max temperatue the fan should run at 100%
    fanPercentPower = maxFanPercent;
  }

  //convert multiple of fanStep, ie. .05, .1, .15,.....
  //perform integer division to drop the remainder  
  if (fanStep > 0) {
    //int will drop the remainder, so 24 with a step of 5 = 20
    fanPercentPower = ((int)(fanPercentPower / fanStep) ) * fanStep;
  }
  
  //convert to PWM setting
  fanPWM = (int)map(fanPercentPower, 0, 100, 0, 255);

  //set speed of fan
  analogWrite(pinFan_PWM_Control, fanPWM);

  // listen for BLE peripherals to connect:
  BLEDevice central = BLE.central();
  if (central) {
    Serial.print("Connected to central: ");
    // print the central's MAC address:
    Serial.println(central.address());

    //set values once BlueTooth is connected
    currentTempCharacteristic.writeValue(currentTemp);
    maxTempCharacteristic.writeValue(maxTemp);
    fanPercentPowerCharacteristic.writeValue(fanPercentPower);

    while (central.connected()) {
      digitalWrite(pinLED, HIGH);         // will turn the LED on

      if (bleOverRideCharacteristic.written()) {
        if (bleOverRideCharacteristic.value() == 1)  {
          bleOverRide = 1;
        } else {
          bleOverRide = 0;
        }
      }

      if (fanPercentPowerCharacteristic.written()) {
          //if FanPercent was written,  ensure override is also updated
          bleOverRide = 1;
      }

      bleOverRideCharacteristic.writeValue(bleOverRide);
    }

    digitalWrite(pinLED, LOW);         // will turn the LED off
  
    // when the central disconnects, print it out:
    Serial.print(F("Disconnected from central: "));
    Serial.println(central.address());
  } else {
    //if disconnected from BlueTooth, calculate RPM  
    currentMillis = millis() + secondDelay;
    intFanRPM_Counter = 0;
    while (currentMillis > millis()) {
        //allows time to count RPM
    }

    //covert to 1000 revs
    currentFanRPM = (int)(intFanRPM_Counter * (1000 / (float)secondDelay));     //had to convert to float to avoid integer division
    
    //guessed at 105 for the x/second. and 3000 was the documented max RPM
    currentFanRPM = map(currentFanRPM, 0, 105, 0, 3000);

    Serial.print("Temperature = " + (String)currentTemp + "°F");
    Serial.print(", Min Temp = " + (String)minTemp + "°F");
    Serial.print(", Max Temp = " + (String)maxTemp + "°F");
    Serial.print(", Fan Power = " + (String)fanPercentPower);
    Serial.print(", Fan PWM = " + (String)fanPWM);
    Serial.print(", Current RPM = " + (String)currentFanRPM);
    Serial.println("");
  }
}

void fnFanCounter() {
  intFanRPM_Counter++;
}

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.