ESP32 and ArduinoBLE Server

Hardware: ESP-WROOM-32 (Arduino IDE board esp32 by Espressif: DOIT ESP32 DEVKIT V1), ADXL345 Accelerometer
Software libraries: ADXL345_WE, BLEDevice, BLEUtils, BLEServer

I am trying to make a leveler for my Jeep and am using the ADXL345. I can calculate the heights needed to raise the corners of the Jeep. This part working.
I'd like to use a BLE Server on the ESP32-WROOM-32 to advertise these so I can connect with my phone through an app.
I've used the example Examples->ESP32 BLE Arduino->BLE_server as the basis for this project. I've successfully compiled and uploaded this example to the ESP32 board and connected to the server via my phone.
I've set up my BLE server the same way as in the example, putting everything in the same code locations (setup() declarations in my setup() location, globals in the global section, ...) The trouble I'm having is when I go to write the data to the characteristic in the loop(), I'm getting the following error: 'FP_Characteristic' was not declared in this scope. FP_Characteristic is declared in setup() but I need to update it in loop(). I've tried moving everything above setup() with no success.

How do I update the value in the FP_Characteristic in the loop() section? Thanks.

Jeep_Leveler.ino code below
/***************************************************************************
* Jeep_Leveler.ino
*
* Using the ADXL345 to read orientation of the Jeep.
* Will output to BLE on phone for ease of use.
*
* Please note the ADXL345 "forgets" calibration data when reset or repowered.
* You might consider to save them to the EEPROM
*  
* Further information can be found on: 
* https://wolles-elektronikkiste.de/adxl345-teil-1 (German)
* https://wolles-elektronikkiste.de/en/adxl345-the-universal-accelerometer-part-1 (English)
* 
***************************************************************************/
//ADXL345
#include <Wire.h>
#include <ADXL345_WE.h>
#define ADXL345_I2CADDR 0x53  // 0x1D if SDO = HIGH
//BLE
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

#define SERVICE_UUID        "749bff6f-d5a5-4f65-a4a0-c306f74db32d"
#define FrontPassenger_UUID "273843cd-3f63-449b-a069-66f3ee2a6846" //<---Add more once working

/* There are several ways to create your ADXL345 object:
 * ADXL345_WE myAcc = ADXL345_WE()                -> uses Wire / I2C Address = 0x53
 * ADXL345_WE myAcc = ADXL345_WE(ADXL345_I2CADDR) -> uses Wire / ADXL345_I2CADDR
 * ADXL345_WE myAcc = ADXL345_WE(&wire2)          -> uses the TwoWire object wire2 / ADXL345_I2CADDR
 * ADXL345_WE myAcc = ADXL345_WE(&wire2, ADXL345_I2CADDR) -> all together
 */
ADXL345_WE myAcc = ADXL345_WE(ADXL345_I2CADDR);

//Wheelbase and track of JKU is 118.4"x62.9". Need to take this as input from the Web BLE page
float track = 62.9;
float wheelbase = 118.4;
float hypotenuse = sqrt(pow(track,2) + pow(wheelbase, 2));
bool SERIAL_OUTPUT = true;  //set to true for output to the serial console. false is for final compile
bool CALIBRATION = false;   //set to false so that we don't calibrate on a non-flat surface
bool RAW_ANGLE = true; //set to false to turn off raw angle output to serial monitor

// BLEDevice::init("Jeep Leveler ESP32");
// BLEServer *pServer = BLEDevice::createServer();
// BLEService *pService = pServer->createService(SERVICE_UUID);
// BLECharacteristic *FP_Characteristic = pService->createCharacteristic(
//                                         FrontPassenger_UUID,
//                                         BLECharacteristic::PROPERTY_READ
//                                       );
// BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();

float calcHeightCartesian(double angle, float leg) {
  return leg * sin(angle);
}

float calcHeightSpherical(char* orientation, float theta, float phi, float rho){
  return rho * cos(theta);
}

void setup() {
  if (SERIAL_OUTPUT) {
    Wire.begin();
    Serial.begin(115200);
    delay(500);
    Serial.println("Jeep JKU Leveler - Dirk Freeman");
    Serial.println();
    if (!myAcc.init()) {
      Serial.println("ADXL345 not connected!");
    }
     Serial.println("Starting Jeep Leveler BLE server");
  }

  BLEDevice::init("Jeep Leveler ESP32");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *FP_Characteristic = pService->createCharacteristic(
                                          FrontPassenger_UUID,
                                          BLECharacteristic::PROPERTY_READ |
                                          BLECharacteristic::PROPERTY_WRITE
                                        );
  
  FP_Characteristic->setValue("Jeep Leveler");
  pService->start();
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();
  Serial.println("FP_Characteristic defined. Read it in the nRF Connect app!!!");

  /* Add your min and max raw values you found with ADXL345_calibration.ino.  
    The order is: setCorrFactors(min x, max x, min y, max y, min z, max z).
    setCorrFactors calibrates the slope and assumes the zero point 
    is (min+max)/2. You have to add the setCorrFactors function to all sketches 
    in which you want to use it.
*/
  //myAcc.setCorrFactors(-266.0, 285.0, -268.0, 278.0, -291.0, 214.0); //original values from example
  myAcc.setCorrFactors(-254.0, 270.0, -260.0, 255.0, -291.0, 246);  //these are the calibration values for my ADXL345

  /* In this next step the offset for angles is corrected to get quite precise corrected 
    angles x and y up to ~60°. The additional offsetCorrection is only for corrected 
    angle measurements, not for pitch and roll. The procedure just ensures to start at 0°.
*/
  if (SERIAL_OUTPUT && CALIBRATION) {
    Serial.println("Position your ADXL345 flat and don't move it");
    delay(2000);
    myAcc.measureAngleOffsets();
    Serial.println("....done");
  }

  /* Choose the data rate         Hz
    ADXL345_DATA_RATE_3200    3200
    ADXL345_DATA_RATE_1600    1600
    ADXL345_DATA_RATE_800      800
    ADXL345_DATA_RATE_400      400
    ADXL345_DATA_RATE_200      200
    ADXL345_DATA_RATE_100      100
    ADXL345_DATA_RATE_50        50
    ADXL345_DATA_RATE_25        25
    ADXL345_DATA_RATE_12_5      12.5  
    ADXL345_DATA_RATE_6_25       6.25
    ADXL345_DATA_RATE_3_13       3.13
    ADXL345_DATA_RATE_1_56       1.56
    ADXL345_DATA_RATE_0_78       0.78
    ADXL345_DATA_RATE_0_39       0.39
    ADXL345_DATA_RATE_0_20       0.20
    ADXL345_DATA_RATE_0_10       0.10
*/
  myAcc.setDataRate(ADXL345_DATA_RATE_50);
  if (SERIAL_OUTPUT) {
    Serial.print("Data rate: ");
    Serial.print(myAcc.getDataRateAsString());

    /* Choose the measurement range
    ADXL345_RANGE_16G    16g     
    ADXL345_RANGE_8G      8g     
    ADXL345_RANGE_4G      4g   
    ADXL345_RANGE_2G      2g
*/
    myAcc.setRange(ADXL345_RANGE_2G);
    Serial.print("  /  g-Range: ");
    Serial.println(myAcc.getRangeAsString());
    Serial.println();
  }
}

void loop() {
  //xyzFloat g = myAcc.getGValues();
  xyzFloat corrAngles = myAcc.getCorrAngles();
  float frontPassenger, rearPassenger, rearDriver, frontDriver;
  float angleX, angleY, angleZ;
  char buffer[7];
  char* FP_raise_str = "Raise FP: ";
  std::string FP_string = dtostrf(frontPassenger, 6, 2, buffer);
  
  // Converting degrees to radians for calcHeightCartesianCartesianCartesian()
  angleX = PI * (corrAngles.x) / 180;
  angleY = PI * (corrAngles.y) / 180;
  angleZ = PI * (corrAngles.z) / 180;

  if (SERIAL_OUTPUT && RAW_ANGLE) {
    Serial.print("Angle x = ");
    Serial.print((180 / PI) * angleX);  //output is in degrees
    Serial.print("  |  Angle y = ");
    Serial.print((180 / PI) * angleY);
    Serial.print("  |  Angle z = ");
    Serial.println((180 / PI) * angleZ);
  }

  /* Calculate distance to raise/lower vehicle*/
  if (angleY < 0) {
    frontPassenger = calcHeightCartesian(-angleY, track);
    FP_Characteristic->setValue(FP_string);
    if (SERIAL_OUTPUT) {
      Serial.print("Raise FP ");
      Serial.print(frontPassenger);
      Serial.print("  : ");
    }
  } else {
    frontPassenger = calcHeightCartesian(angleY, track);
    FP_Characteristic->setValue(FP_string);
    if (SERIAL_OUTPUT) {
      Serial.print("Lower FP ");
      Serial.print(frontPassenger);
      Serial.print("  : ");
    }
  }

  if (angleX < 0) {
    rearDriver = calcHeightCartesian(-angleX, wheelbase);
    if (SERIAL_OUTPUT) {
      Serial.print("Raise RD ");
      Serial.print(rearDriver);
      Serial.print("  : ");
    }
  } else {
    rearDriver = calcHeightCartesian(angleX, wheelbase);
    if (SERIAL_OUTPUT) {
      Serial.print("Lower RD ");
      Serial.print(rearDriver);
      Serial.print("  : ");
    }
  }

/*  if (angleZ < 0) {
    rearPassenger = calcHeightCartesian(90+angleZ, sqrt(pow(wheelbase,2)+pow(track,2)));
    if (SERIAL_OUTPUT) {
      Serial.print("Raise RP ");
      Serial.print(rearPassenger);
      Serial.print("  : ");
    }
  } else {
    rearPassenger = calcHeightCartesian(90-angleZ, sqrt(pow(wheelbase,2)+pow(track,2)));
    if (SERIAL_OUTPUT) {
      Serial.print("Lower RP ");
      Serial.print(rearPassenger);
      Serial.print("  : ");
    }
  }
*/


  /* Pitch and roll use corrected slope, but no additional offset. 
    All axes are considered for calculation. 
*/
/*  float pitch = myAcc.getPitch();
  float roll  = myAcc.getRoll();

  if (SERIAL_OUTPUT) {
    Serial.print("Pitch   = "); 
    Serial.print(pitch); 
    Serial.print("  |  Roll    = "); 
    Serial.println(roll); 
    Serial.println();
  }
 */ 
  delay(1000);
}

The error message you’re encountering, “‘FP_Characteristic’ was not declared in this scope,” suggests that the FP_Characteristic variable is not accessible within the loop() function. To address this, we’ll need to make sure that the characteristic is declared at a higher scope so that it can be accessed both in setup() and loop(). California Health Insurance

// Declare the characteristic globally
BLECharacteristic FP_Characteristic;

void setup() {
// Initialize BLE and other setup tasks
// ...

// Initialize the characteristic
FP_Characteristic = pService->createCharacteristic(BLE_UUID_FP_CHARACTERISTIC, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);
FP_Characteristic.setValue("Initial Value");

}

void loop() {
// Update the characteristic value (e.g., based on sensor data)
// ...
// Example: Update with a new value
FP_Characteristic.setValue("New Value");

// Other loop tasks
// ...

}

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