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);
}