Building an Android display to report BLE data

OK, so I finally got my data to be sent to my Android using LightBlue software by Punch Through and I can actually read it. Accept I have to select seperate pages and read one value at a time and manually translate the data from hex to Little Endian. That's OK except I need to be doing this while driving a car. There are only 4 variables to be displayed. I would like to find a way of getting them displayed as shown below without me having to touch the Android at all. I don't want to be texting while driving.

It appears that I may have to build an Android App to do this. Or is there a way to do it within LightBlue. The LightBlue web page seems to go well over my head.

image

The current output from LightBlue looks like this. Where I can select any of the 4 last variables and read the data with the default data displayed as hex.

2 questions?

  1. Can I get LightBlue to give me a more appropriate display
  2. If I need to develop an Android app what is the recommended software to get to do this. Free is preferred but not required.

The code I am using is this:

[code]
// Not this program uses a watchdog timmer.
// It is required to reset the Arduino by two presses of the reset button and setting available com ports prior to upload.
// After upload the com port needs to be reset.

// Define Global Constants /////////////////////////////////////////////////////////////////

const int RadPin = A0;                        // Radiator Input Thermister
const int CndPin = A1;                        // Condenser Input Thermister
const int AuxPin = A2;                        // Auxilary Input Not used at this time
const int FanPin = 9;                         // Set Fan pin
const int LED1Pin = 7;                        // Set Cooling Fan LED
const int LED2Pin = 6;                        // Set Condenser Fan LED
const int LED3Pin = 5;                        // Set Aux Fan FED

const unsigned long WDT = 30;                 // Watch Dog Timer max time seconds This must be greater than the time requird to complete a cycle

const int frequency = 10.0;                   // Set fan frequency
const int NumberOfSamples = 20;               // Sent number of data samples for averaging.
const int BlinkTimeOnTest  = 2000;            // Blink time on period for initial circuit test
const int BlinkTimeOn      = 500;             // Blink time on period
const int BlinkTimeOff     = 500;             // Blink time off period

// 10 bit temperature equivolents for radiator sensor Delphi 12146312
const int Rad0   = 8;      // - 20°C equivolent Sensor assumed open.
const int Rad20  = 444;    //85C
const int Rad30  = 466;    //88C
const int Rad40  = 489;    //91C
const int Rad50  = 512;    //94C
const int Rad60  = 536;    //97C
const int Rad70  = 560;    //100C
const int Rad80  = 584;    //103C
const int Rad90  = 608;    //106C
const int Rad100 = 668;    //115C This is an emergency mode either coolant is too hot or senser is shorted. Set duty cycle to 0 to activate emergency mode

// 10 bit temperature equivolents for condenser sensor Litlefuse USP7766
const int Cnd0   = 19;     //-30C Sensor Test point
const int Cnd20  = 391;    //40C
const int Cnd30  = 440;    //45C
const int Cnd40  = 489;    //50C
const int Cnd50  = 537;    //55C
const int Cnd60  = 583;    //60C
const int Cnd70  = 627;    //65C
const int Cnd80  = 668;    //70C
const int Cnd90  = 706;    //75C
const int Cnd100 = 849;    //100C Sensor Test Point

// 10 bit temperature equivolents for temp sensor Delphi 25036751
const int Aux0   = 8;      //-20C Sensor Test Point
const int Aux20  = 452;    //85C
const int Aux30  = 474;    //88C
const int Aux40  = 496;    //91C
const int Aux50  = 519;    //94C
const int Aux60  = 543;    //97C
const int Aux70  = 567;    //100C
const int Aux80  = 591;    //103C
const int Aux90  = 614;    //106C
const int Aux100 = 733;    //125C Sensor Test Point

#define _PWM_LOGLEVEL_                2
#define USING_MICROS_RESOLUTION       true    //false 
#define HW_TIMER_INTERVAL_US          20L         
#define PRINT_INTERVAL                15000L      // Interval of time ms for printing to the serial moniter
#define UPDATE_CHECK_INTERVAL_MS      15000L      // Interval of time for fan to run befor checking sensors and re adjusting fan speed

// Initialize Global Variables ///////////////////////////////////////////////////////////////////

int RadVals [NumberOfSamples + 1];
int CndVals [NumberOfSamples + 1];
int AuxVals [NumberOfSamples + 1];

int RadValAvg = 0;
int CndValAvg = 0;
int AuxValAvg = 0;

int RadSpeed = 10;
int CndSpeed = 10;
int AuxSpeed = 10;

int RadTemp;
int CndTemp;
int AuxTemp;

int FanSpeed = 10;            // Set fan to 10% PWM = off

uint32_t startMicros = 0;

// You can assign pins here. Be careful to select good pin to use or crash
uint32_t PWM_Pin    = FanPin;

// Channel number used to identify associated channel
int channelNum;

//////////////////////////////////////////////////////

#if !( ARDUINO_ARCH_NRF52840 && TARGET_NAME == ARDUINO_NANO33BLE )
  #error This code is designed to run on nRF52-based Nano-33-BLE boards using mbed-RTOS platform! Please check your Tools->Board setting.
#endif

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "nRF52_MBED_Slow_PWM.h"     // https://github.com/khoih-prog/nRF52_MBED_Slow_PWM
#include <ArduinoBLE.h>

// For mbed nRF52, you can only select NRF52 Hardware Timer NRF_TIMER_3-NRF_TIMER_4 (3 to 4)
// If you select the already-used NRF_TIMER_0-2, it'll be auto modified to use NRF_TIMER_3

// Init NRF52 timer NRF_TIMER3
NRF52_MBED_Timer ITimer(NRF_TIMER_3);

// Init nRF52_Slow_PWM, each can service 16 different ISR-based PWM channels
NRF52_MBED_Slow_PWM ISR_PWM;

///////////////////////////////////////////////////////////////////////// Define the Temperature Service for BLE
BLEService TempService("53436b3f-5f91-474b-963e-8b09b170c670");        //*** BLEService Class Any Hex Name 128-bit UUID in String format *********************************************************

// Define Temperature and Fan Speed Characteristics
BLEUnsignedIntCharacteristic RadLevelChar("694d181e-4421-47f3-9653-c4d6bb295a07",  // standard 128-bit characteristic UUID *******************************
    BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes
BLEUnsignedIntCharacteristic CndLevelChar("0407dd37-ae29-4ec7-ab40-a83898d610df",  // standard 128-bit characteristic UUID *******************************
    BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes
BLEUnsignedIntCharacteristic AuxLevelChar("ad43db8f-e3e6-4025-b745-43f2100f27e1",  // standard 128-bit characteristic UUID *******************************
    BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes
BLEUnsignedIntCharacteristic FanSpeedChar("8ed03f79-29c0-46d5-a2ca-bfddd629347e",  // standard 128-bit characteristic UUID *******************************
    BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes

////////////////////////////////////////////////////////////////////////////////////
void TimerHandler()
{ 
  ISR_PWM.run();
}

////////////////////////////////////////////////////////////////////////////////////
void printData(const int& index = 0)      // Subroutine to print each pin value to the serial monitor
                                          // Note this subroutine must be declared befor it is called?
{
  PWM_LOGINFO3("Rad(", index, ") input = ", RadVals[index]);
  PWM_LOGINFO3("Cnd(", index, ") input = ", CndVals[index]);
  PWM_LOGINFO3("Aux(", index, ") input = ", AuxVals[index]);
}

////////////////////////////////////////////////////////////////////////////////////
void printAvg()                           // Subroutine to print the average values to the serial monitor
                                          // Not this subroutine must be declared befor it is called?
{
  PWM_LOGWARN1("RadAvg = ", RadValAvg);
  PWM_LOGWARN1("CndAvg = ", CndValAvg);
  PWM_LOGWARN1("AuxAvg = ", AuxValAvg);
}


////////////////////////////////////////////////////////////////////////////////////
void setup() 
{
  // put your setup code here, to run once:
  pinMode(RadPin, INPUT);
  pinMode(LED1Pin, OUTPUT);
  pinMode(LED2Pin, OUTPUT);
  pinMode(LED3Pin, OUTPUT);
  pinMode(FanPin, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);

  //Configure WDT.
  NRF_WDT->CONFIG         = 0x01;         // Configure WDT to run when CPU is asleep
  NRF_WDT->CRV            = WDT*32769;    // CRV = WDT *(32768 + 1)
  NRF_WDT->RREN           = 0x01;         // Enable the RR[0] reload register
  NRF_WDT->TASKS_START    = 1;            // Start WDT       
    
  NRF_WDT->RR[0] = WDT_RR_RR_Reload;      // Reset WDT
  Serial.println("Watchdog iniialized and Set *************************************************************");  
                          
  Serial.begin(115200);           
  // while (!Serial);                        // Comment this out prior to installation

  delay(200); 

  Serial.print(F("\nStarting Car_Fan_Control using ")); Serial.println(BOARD_NAME);
  Serial.println(NRF52_MBED_SLOW_PWM_VERSION);
  
  digitalWrite(LED_BUILTIN, HIGH);

  // Interval in microsecs
  if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_US, TimerHandler))
  {
    startMicros = micros();
    Serial.print(F("Starting ITimer OK, micros() = ")); Serial.println(startMicros);
  }
  else
    Serial.println(F("Can't set ITimer. Select another freq. or timer"));

  channelNum = ISR_PWM.setPWM(PWM_Pin, frequency, FanSpeed);  // During setup FanSpeed will be set to initialized value of 10 = off.
  
  ReadAveragSensorsData();          // Read all the sensors and find the averages
  CalcFanSpeed();                   // Call the CalcFanSpeed routine
  StartUpBlink();                   // Call the blink sensor StartUpBlink subroutine to test all sensors
  SetUpBLE();                       // Call the SetUpBLE routine
  
  Serial.println("Setup Complete *************************************************************"); Serial.println();
}
   
////////////////////////////////////////////////////////////////////////////////////
void loop(){

  // wait for a Bluetooth® Low Energy central
  BLEDevice central = BLE.central();

  // if a central is connected to the peripheral:
  
  static unsigned long update_timeout = 0;
  static bool LED_status = HIGH;

  // Take reading every update_timeout ms.
  if ( (millis() > update_timeout) && (millis() > UPDATE_CHECK_INTERVAL_MS) )
  {   
    printData(); // Print every update_timeout ms.
    LED_status = !LED_status;
    digitalWrite(LED_BUILTIN, LED_status);
    ReadAveragSensorsData();        // Read all the sensors and find the averages
    CalcFanSpeed();                 // Call read sensors subroutine to calculate fan speed and print values to serial moniter
    CalculateTemperatures();        // Calculate the thermister temperatures
    BlinkSpeed();                   // Call blink test to blink out speeds  
    Serial.print("millis() = "); Serial.println(millis());
    NRF_WDT->RR[0] = WDT_RR_RR_Reload; // Reset WDT
    Serial.println("Watchdog Reset *************************************************************");  
    update_timeout = millis() + UPDATE_CHECK_INTERVAL_MS;
    
    if (central) {
      Serial.print("Connected to central: ");
      // print the central's BT address:
      Serial.println(central.address());
      // turn on the LED to indicate the connection:
      digitalWrite(LED_BUILTIN, HIGH);
      updateTemperatures();
    }
    
    // when the central disconnects, turn off the LED:
    digitalWrite(LED_BUILTIN, LOW);
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());

  }
}

////////////////////////////////////////////////////////////////////////////////////
void ReadAveragSensorsData() // Subroutine to read each pin and sum them
{
  int index = 0;

  RadValAvg = 0;
  CndValAvg = 0;
  AuxValAvg = 0;
     
  do 
  {
    // Read al data points

  RadVals[index]  = analogRead(RadPin);
  CndVals[index]  = analogRead(CndPin);
  AuxVals[index]  = analogRead(AuxPin);

  // sum all data points
  RadValAvg += RadVals [index];
  CndValAvg += CndVals[index];
  AuxValAvg += AuxVals [index];

    printData(index);               //Call the printData subroutine to print each reading to the serial monitor.

    index = index + 1;

  } while (index < NumberOfSamples);

  // Find Average of all data points
  RadValAvg  = RadValAvg  / NumberOfSamples;
  CndValAvg  = CndValAvg  / NumberOfSamples;
  AuxValAvg  = AuxValAvg  / NumberOfSamples;

  printAvg();                       //Call the printAvg function to print the average data to the serial monitor.

}

////////////////////////////////////////////////////////////////////////////////////
void CalcFanSpeed()                  // Subroutine to do 1 cycle of reading the temperature data
{

  // Find the speed levels required by each sensor Not only rad temperature can initiate emergency mode.
  if (RadValAvg < Rad0) RadSpeed = 0;           // Open sensor assumed fan will run in emergency mode at 100%
  if (RadValAvg < Rad20 and RadValAvg >= Rad0) RadSpeed = 10;   // 10% duty cycle = fan off
  if (RadValAvg < Rad30 and RadValAvg >= Rad20) RadSpeed = 20;
  if (RadValAvg < Rad40 and RadValAvg >= Rad30) RadSpeed = 30;
  if (RadValAvg < Rad50 and RadValAvg >= Rad40) RadSpeed = 40;
  if (RadValAvg < Rad60 and RadValAvg >= Rad50) RadSpeed = 50;
  if (RadValAvg < Rad70 and RadValAvg >= Rad60) RadSpeed = 60;
  if (RadValAvg < Rad80 and RadValAvg >= Rad70) RadSpeed = 70;
  if (RadValAvg < Rad90 and RadValAvg >= Rad80) RadSpeed = 80;
  if (RadValAvg < Rad100 and RadValAvg >= Rad90) RadSpeed = 90;
  if (RadValAvg >= Rad100) RadSpeed = 100;        // Set PWM duty cycle to 0 for emergency mode

  if (CndValAvg < Cnd20) CndSpeed = 10;   // 10% duty cycle = fan off
  if (CndValAvg < Cnd30 and CndValAvg >= Cnd20) CndSpeed = 20;
  if (CndValAvg < Cnd40 and CndValAvg >= Cnd30) CndSpeed = 30;
  if (CndValAvg < Cnd50 and CndValAvg >= Cnd40) CndSpeed = 40;
  if (CndValAvg < Cnd60 and CndValAvg >= Cnd50) CndSpeed = 50;
  if (CndValAvg >= Cnd60) CndSpeed = 60;                // Condensor is limited to 60%

  if (AuxValAvg < Aux20) AuxSpeed = 10;   // 10% duty cycle = fan off
  if (AuxValAvg < Aux30 and AuxValAvg >= Aux20) AuxSpeed = 20;
  if (AuxValAvg < Aux40 and AuxValAvg >= Aux30) AuxSpeed = 30;
  if (AuxValAvg < Aux50 and AuxValAvg >= Aux40) AuxSpeed = 40;
  if (AuxValAvg < Aux60 and AuxValAvg >= Aux50) AuxSpeed = 50;
  if (AuxValAvg < Aux70 and AuxValAvg >= Aux60) AuxSpeed = 60;
  if (AuxValAvg < Aux80 and AuxValAvg >= Aux70) AuxSpeed = 70;
  if (AuxValAvg < Aux90 and AuxValAvg >= Aux80) AuxSpeed = 80;
  if (AuxValAvg >= Aux90) AuxSpeed = 90;
  
  // find the sensor with the highest speed requirment or set emergency mode
  if (RadSpeed == 100|| RadSpeed == 0){   
    FanSpeed = 0;                         // Emergency mode rad too hot or shorted sensor = 100, sensor open = 0
  }
  else {
    FanSpeed = max(RadSpeed, CndSpeed); // find the highest
    FanSpeed = max(FanSpeed, AuxSpeed);  // This is the duty Cycle
  }
  
  PWM_LOGWARN1("Fan Speed  = ", FanSpeed);

  //write the PWM value to the pwm output pin
  PWM_LOGWARN5("Freq = ", frequency, ", FanSpeed % = ", FanSpeed, ", Pin = ", FanPin);

  if (!ISR_PWM.modifyPWMChannel(channelNum, PWM_Pin, frequency, FanSpeed))
  {
    Serial.print(F("modifyPWMChannel error"));
  }
}

////////////////////////////////////////////////////////////////////////////////////
void StartUpBlink()                          // Blink LEDs at startup to test sensors are in range
{
  // Sensor one time test on startup test, Blink lights for each sensor in range.

  if (analogRead(RadPin) >= Rad0 && analogRead(RadPin) <= Rad100) {
    digitalWrite(LED1Pin, HIGH); // turn the LED on 
  }

  if (analogRead(CndPin) >= Cnd0 && analogRead(CndPin) <= Cnd100) {
    digitalWrite(LED2Pin, HIGH); // turn the LED on
  }
  
  if (analogRead(AuxPin) >= Aux0 && analogRead(RadPin) <= Rad100) {
    digitalWrite(LED3Pin, HIGH);  // turn the LED on
  }
  
  delay(BlinkTimeOnTest);       // Time to leave LEDs on
  digitalWrite(LED1Pin, LOW);   // turn the LED off 
  digitalWrite(LED2Pin, LOW);   // turn the LED off
  digitalWrite(LED3Pin, LOW);   // turn the LED off
}

////////////////////////////////////////////////////////////////////////////////////
void BlinkSpeed()                               // Blink LEDs to indicate speed called by each sensor
{
  int CountRadOn  = 0;    // Counter for number of radiator blinks on
  int CountCndOn  = 0;    // Counter for number of condenser blinks on
  int CountAuxOn  = 0;    // Counter for number of Aux blinks on

  int CountRadOff = 0;    // Counter for number of radiator blinks off
  int CountCndOff = 0;    // Counter for number of condenser blinks off
  int CountAuxOff = 0;    // Counter for number of Aux blinks off
  
  int RadBlinks   = 0;    // Initialise number of blinks based on radiator temp
  int CndBlinks   = 0;    // Initialise number of blinks based on Condenser temp
  int AuxBlinks   = 0;    // Initialise number of blinks based on Aux temp
  int MaxBlinks   = 0;    // Maximum number of blinks for all channels
  
  int index = 0;
  
  RadBlinks = RadSpeed/10;      // Number of Blinks Based on Rad Temp
  CndBlinks = CndSpeed/10;      // Number of Blinks Based on Cnd Temp
  AuxBlinks = AuxSpeed/10;      // Number of Blinks Based on Aux Temp
  MaxBlinks = max(RadBlinks, CndBlinks);
  MaxBlinks = max(MaxBlinks, AuxBlinks);    // Find the total number of blinks required
    
  do {                                      // Do the blink loop until the max number of blinks has occured.
     
      CountRadOn = CountRadOn + 1;
      CountCndOn = CountCndOn + 1;
      CountAuxOn = CountAuxOn + 1;
      if (CountRadOn <= RadBlinks) {
        digitalWrite(LED1Pin, HIGH); // turn the LED on 
      }      
      if (CountCndOn <= CndBlinks) {
        digitalWrite(LED2Pin, HIGH); // turn the LED on 
      }      
      if (CountAuxOn <= AuxBlinks) {
        digitalWrite(LED3Pin, HIGH); // turn the LED on 
      }

      delay(BlinkTimeOn);           // Time to leave LEDs on
      digitalWrite(LED1Pin, LOW);   // turn the LED off 
      digitalWrite(LED2Pin, LOW);   // turn the LED off
      digitalWrite(LED3Pin, LOW);   // turn the LED off
      delay(BlinkTimeOff);          // Time to leave LEDs on
           
    index = index + 1;
  } while (index < MaxBlinks);
}
  
////////////////////////////////////////////////////////////////////////////////////
  void SetUpBLE() {
  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");

    while (1);
  }

  /* Set a local name for the Bluetooth® Low Energy device
     This name will appear in advertising packets
     and can be used by remote devices to identify this Bluetooth® Low Energy device
     The name can be changed but maybe be truncated based on space left in advertisement packet
  */

    BLE.setLocalName("Testing 123"); //******************************************************************************
    BLE.setAdvertisedService(TempService); // add the service UUID
    TempService.addCharacteristic(RadLevelChar); // add the radiator level characteristic
    TempService.addCharacteristic(CndLevelChar); // add the condenser level characteristic
    TempService.addCharacteristic(AuxLevelChar); // add the aux level characteristic
    TempService.addCharacteristic(FanSpeedChar); // add the fan Speed characteristic
    
    BLE.addService(TempService);  // Add the Temperature service
    RadLevelChar.writeValue(0);   // set initial value for this characteristic
    CndLevelChar.writeValue(0);   // set initial value for this characteristic
    AuxLevelChar.writeValue(0);   // set initial value for this characteristic
    FanSpeedChar.writeValue(0);   // set initial value for this characteristic

  // Start advertising Bluetooth® Low Energy.  It will start continuously transmitting Bluetooth® Low Energy
  // advertising packets and will be visible to remote Bluetooth® Low Energy central devices
  // until it receives a new connection

  BLE.advertise();  // start advertising

  Serial.println("Bluetooth® device active, waiting for connections...");

  } 

////////////////////////////////////////////////////////////////////////////////////////
  void updateTemperatures() {
  // Read the current voltage level on each analog input pin.
  //   This is used here to simulate the charge level of temperaturs.

  Serial.print("Rad Level % is now: "); Serial.println(RadTemp);
  Serial.print("Cnd Level % is now: "); Serial.println(CndTemp);
  Serial.print("Aux Level % is now: "); Serial.println(AuxTemp);
  Serial.print("Fan Speed % is now: "); Serial.println(FanSpeed);

  RadLevelChar.writeValue(RadTemp);            // update the Radiator level characteristics
  CndLevelChar.writeValue(CndTemp);            // update the Condenser level characteristics
  AuxLevelChar.writeValue(AuxTemp);            // update the Aux level characteristics
  FanSpeedChar.writeValue(FanSpeed);            // update the Aux level characteristics
  
  }

 ////////////////////////////////////////////////////////////////////////////////////////////////
  void CalculateTemperatures() {
  //// Defining 6th order polynomial coefficients
  
  double RadCoeff0 = -3.191109E+01;
  double RadCoeff1 =  1.333142E+00;
  double RadCoeff2 = -9.388659E-03;
  double RadCoeff3 =  3.502677E-05;
  double RadCoeff4 = -6.643350E-08;
  double RadCoeff5 =  6.164271E-11;
  double RadCoeff6 = -2.214795E-14;

  double CndCoeff0 = -4.330212E+01;
  double CndCoeff1 =  7.697340E-01;
  double CndCoeff2 = -4.329864E-03;
  double CndCoeff3 =  1.423127E-05;
  double CndCoeff4 = -2.456664E-08;
  double CndCoeff5 =  2.111208E-11;
  double CndCoeff6 = -7.068046E-15;

  double AuxCoeff0 = -3.210410E+01;
  double AuxCoeff1 =  1.316881E+00;
  double AuxCoeff2 =  1.316881E+00;
  double AuxCoeff3 =  3.414067E-05;
  double AuxCoeff4 = -6.438080E-08;
  double AuxCoeff5 =  5.940511E-11;
  double AuxCoeff6 = -2.122449E-14;


  //Calculate temperatures
  
  RadTemp = RadCoeff0 + RadCoeff1*RadValAvg + RadCoeff2*RadValAvg*RadValAvg + RadCoeff3*RadValAvg*RadValAvg*RadValAvg + RadCoeff4*RadValAvg*RadValAvg*RadValAvg*RadValAvg + RadCoeff5*RadValAvg*RadValAvg*RadValAvg*RadValAvg*RadValAvg + RadCoeff6*RadValAvg*RadValAvg*RadValAvg*RadValAvg*RadValAvg*RadValAvg;
  CndTemp = CndCoeff0 + CndCoeff1*CndValAvg + CndCoeff2*CndValAvg*CndValAvg + CndCoeff3*CndValAvg*CndValAvg*CndValAvg + CndCoeff4*CndValAvg*CndValAvg*CndValAvg*CndValAvg + CndCoeff5*CndValAvg*CndValAvg*CndValAvg*CndValAvg*CndValAvg + CndCoeff6*CndValAvg*CndValAvg*CndValAvg*CndValAvg*CndValAvg*CndValAvg;
  AuxTemp = AuxCoeff0 + AuxCoeff1*AuxValAvg + AuxCoeff2*AuxValAvg*AuxValAvg + AuxCoeff3*AuxValAvg*AuxValAvg*AuxValAvg + AuxCoeff4*AuxValAvg*AuxValAvg*AuxValAvg*AuxValAvg + AuxCoeff5*AuxValAvg*AuxValAvg*AuxValAvg*AuxValAvg*AuxValAvg + AuxCoeff6*AuxValAvg*AuxValAvg*AuxValAvg*AuxValAvg*AuxValAvg*AuxValAvg; 
  
  }
[/code]
1 Like

Hi.
MIT App Inventor is a popular tool for building android apps. It's free, web based and uses blocks. It would not be hard to build a small app to display the data received via Bluetooth.

Not in my experience with using in on an Android phone.

If you are going to write a custom app then you can more easily send all the data in a single characteristic.

Will check it out. Thank You.

I guess my next thing to learn is how to build an app. Thanks

MIT App Inventor is not hard to learn. Plenty of examples to follow. I view it as a natural extension to my Arduino projects. It can show any data from your sketch and allow you to send commands to your sketch.

Not as easy as it sounds but plugging along. I can see myself getting carried away and putting bar graphs of temperature etc.

Thanks

1 Like

That didn't take you long. Did you find any examples using BLE?

I found a good example of how to get connected. But its not working yet.

Got a thread up on the MIT Inventor forum. I will get it sooner or later.

I can't interpret that error message. Some are like that.

Did you install the BLE extension? I see it needs Android 5.0 or higher.

I now see you must have imported the BLE etension or you would not have been able to make the BLE calls.

Someone in the MIT AI forum will have the answer for you.

Yes, I have no idea how to debug without seeing the underlying code. Hopefully someone will reply.

One thing I did notice is that the software said it works with Windows XP and Windows 7. It did not mention Windows 10 like I'm using. Not sure if that's the problem or if they just never got around to updating the compatibility list?

I see you've made some progress.

I've never had success with the Companion so don't use it. I load the compiled app into the phone and test it there. Taking the Companion out of the equation might remove errors in some cases. Just a thought.

If you don't get responses in the IoT category, you might like to post a query in the General Discussion category (will get more views).

Yes. The Companion is working fine now. The problem was trying to use the emulator. No errors with the Companion, but the emulator is what was causing those problems.

But I apparently may have destroyed two Nano 33 BLE's.

The first time I was able to get the Nano to connect with the MIT Inventor app, It appeared to connect successfully was the last time. I could not connect again. Then I tried connecting with with LightBlue software, which I have been using successfully all along and could not connect with that either.

I tried a new Nano 33 BLE with LightBlue first and was able to connect. I then tried the new Nano with the MIT software and successfully connected 1 time and now cant connect with either the MIT software or the LightBlue.

I tried doing a double press reset and re loading the sketch but no difference.

Any Ideas?

The MIT project is still a work in progress that looks like these 4 pages:




The Arduino Test Code

[code]
const int RadPin = A0;      // Radiator Input Thermister
const int CndPin = A1;      // Condenser Input Thermister
const int AuxPin = A2;      // Auxilary Input Not used at this time
const int FanPin = 9;       // Set Fan pin
const long Period = 10000;  // Recheck period

long previousMillis = 0;    // last time the temperature levels were checked, in ms

                    /*
                      Temperatur Monitor

                      This example creates a Bluetooth® Low Energy peripheral with the standard Temperature service and
                      level characteristic. Pins A0, A1 and A2 are used to calculate the temperatures of 3 sensors.
                      The data is calculated by the time set in the constant Period.

                      The circuit:
                      - Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
                        Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.

                      You can use a generic Bluetooth® Low Energy central app, like LightBlue (iOS and Android) or
                      nRF Connect (Android), to interact with the services and characteristics
                      created in this sketch.

                      This example code is in the public domain.
                    */

#include <ArduinoBLE.h>

// Define the Temperature Service
BLEService TempService("53436b3f-5f91-474b-963e-8b09b170c670");        //*** BLEService Class Any Hex Name 128-bit UUID in String format *********************************************************

// Define Temperature Level Characteristics as BLEUnsignedIntCharacteristic, BLEUnsignedCharCharacteristic will not work.

// Note define Characteristics and  
BLEUnsignedIntCharacteristic RadLevelChar("694d181e-4421-47f3-9653-c4d6bb295a07",  // standard 128-bit characteristic UUID *******************************
    BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes
BLEUnsignedIntCharacteristic CndLevelChar("0407dd37-ae29-4ec7-ab40-a83898d610df",  // standard 128-bit characteristic UUID *******************************
    BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes
BLEUnsignedIntCharacteristic AuxLevelChar("ad43db8f-e3e6-4025-b745-43f2100f27e1",  // standard 128-bit characteristic UUID *******************************
    BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes

void setup() {
  Serial.begin(9600);    // initialize serial communication
  //while (!Serial);

  pinMode(LED_BUILTIN, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected

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

    while (1);
  }

  /* Set a local name for the Bluetooth® Low Energy device
     This name will appear in advertising packets
     and can be used by remote devices to identify this Bluetooth® Low Energy device
     The name can be changed but maybe be truncated based on space left in advertisement packet
  */

  BLE.setLocalName("Testing 123"); //******************************************************************************

    BLE.setAdvertisedService(TempService); // add the service UUID
    TempService.addCharacteristic(RadLevelChar); // add the radiator level characteristic
    TempService.addCharacteristic(CndLevelChar); // add the condenser level characteristic
    TempService.addCharacteristic(AuxLevelChar); // add the aux level characteristic
    BLE.addService(TempService);  // Add the Temperature service
    RadLevelChar.writeValue(0);   // set initial value for this characteristic
    CndLevelChar.writeValue(0);   // set initial value for this characteristic
    AuxLevelChar.writeValue(0);   // set initial value for this characteristic

  // Start advertising Bluetooth® Low Energy.  It will start continuously transmitting Bluetooth® Low Energy
  // advertising packets and will be visible to remote Bluetooth® Low Energy central devices
  // until it receives a new connection

  BLE.advertise();  // start advertising

  //Serial.println("Bluetooth® device active, waiting for connections...");
}


  void loop() {
  // wait for a Bluetooth® Low Energy central
  BLEDevice central = BLE.central();

  // if a central is connected to the peripheral:
  if (central) {
    Serial.print("Connected to central: ");
    // print the central's BT address:
    Serial.println(central.address());
    // turn on the LED to indicate the connection:
    digitalWrite(LED_BUILTIN, HIGH);

    // check the temperature levels every Period (ms)
    // while the central is connected:
    while (central.connected()) {
      long currentMillis = millis();
      // if Period ms have passed, check the temperature levels:
      if (currentMillis - previousMillis >= Period) {
        previousMillis = currentMillis;
        updateTemperatures();
      }
    }
    // when the central disconnects, turn off the LED:
    digitalWrite(LED_BUILTIN, LOW);
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
  }
  }

  void updateTemperatures() {
  // Read the current voltage level on each analog input pin.
  //   This is used here to simulate the charge level of temperaturs.

  int Rad = analogRead(RadPin);
  int Cnd = analogRead(CndPin);
  int Aux = analogRead(AuxPin);
/*
  int RadLevel = map(Rad, 0, 1023, 0, 100);
  int CndLevel = map(Cnd, 0, 1023, 0, 100);
  int AuxLevel = map(Aux, 0, 1023, 0, 100);
 */  
  
  int RadLevel = Rad;
  int CndLevel = Cnd;
  int AuxLevel = Aux;
  
  
  Serial.print("Rad Level % is now: "); Serial.println(RadLevel);
  Serial.print("Cnd Level % is now: "); Serial.println(CndLevel);
  Serial.print("Aux Level % is now: "); Serial.println(AuxLevel);

  RadLevelChar.writeValue(RadLevel);            // update the Radiator level characteristics
  CndLevelChar.writeValue(CndLevel);            // update the Condenser level characteristics
  AuxLevelChar.writeValue(AuxLevel);            // update the Aux level characteristics
  }
[/code]

I don't think I can help you with the BLE problem. I've never used one -- I use the plain Nano and a HC-05 Bluetooth module. On the AI side I import the Bluetooth extension. BLE is clearly more complex than plain BT.

Are you able to run sketches on the Nano BLEs? That is, sketches that don't use BT.

Perhaps it's some configuration change in the BLEs that has occurred rather than physical damage.

I'm surprised no-one on the MIT AI forum has responded to your post. There are people in the Arduino forum who know BLE.

With a foot in each camp, ie, Arduino & MIT AI, you'll have to adjudicate as to in which camp the problem sits. There don't seem to be many people in the forums of each with good skills in both.

Nothing else seems to be effected on the Nano. I can run other sketches. And when using BLE it will show the sketch on the Android but when trying to connect, it just times out.

I will be ordering some HC-05 modules before proceeding any further. I will probably get some cheep clones until I get this figured out. At this point things can get expensive fast.

I did start a new thread on the MIT forum but no response as of yet.

I don't understand that. The sketch is your program on the Nano BLE. How can it show on the Android?

I suppose you can use an HC-05 connected to the Nano BLE, redundant as it seems. I think you'll find it less complicated. Do you need the low energy feature? I buy the cheap products.

Yes, I've been following (I'm NissanCedric). Try posting in the General Discussion area. You'll get more views. They're not as fussy about being in the correct subject area or double posting as the Arduino moderators (bless 'em).

The Android device can't physically hurt your Nano BLE, I would think. But maybe some configuration parameter got changed. It's one for the BLE experts, but they're not responding. They're out there.

An Android phones after version 4.3 can deal with BLE. Both LightBlue and nrfConnect make apps for Android which work well with the Nano 33 BLE. These apps don't have flexible output configurations for the data read from the Nano 33 and @mb107 is trying to display all three characteristics on on screen.

Ok. I guess I'm reading the description given too literally.

How can the OP diagnose this problem?

Sketch is not the right word. The "Testing 123" Title characteristic is what shows up on the pick list when scanning. I'm not sure what you call that. But it means to me that the BLE is somewhat working. It just will not connect.

I don't need BLE as the system is powered by the car. But it does work at least if I buy a new one and use the LightBlue software.

I'm not sure if I had only 1 or two successful connects on the first board. After I got it connected I added the purple calls into this section. I'm not sure if these calls are correct for what I'm trying to do. I was just trying to copy other peoples code. I may have had 1 successful connect after adding those purple calls. But I cant picture this damaging anything?

I cant picture the Android damaging the device, but its two devices that will suddenly no longer connect after a first successful connection? I'm wondering if there is a factory reset procedure that may be more than the double push of the reset button?

image