Hi all!
I'm pretty new around programming even though I did some small projects with Arduino. Now I'm trying to make a program for getting data from the ESP32 over BLE based on two different sketches, one for the scale with HX711_ADC and other for RX/TX data from the phone over BLE.
Using both programs separately work fine so I tried to implement both into the same program and this is the result:
- ESP32 advertisement
- Connect to ESP32 on my phone with nRF Connect
-=== Calibration from Monitor Serial (only from my PC)======= -> This I need to do it from the App - Start receiving data on the App and also on my Monitor Serial
I can send all kind of data from the App to the ESP32 and I see it on the Monitor Serial but I'm dying trying to understand why the commands I sent from my phone do not calibrate the scale, any help would be more than welcome, Thanks!!
Code:
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
int txValue = 0;
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
#define LED_BUILTIN 2
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
Serial.println("=====START=RECEIVE=====");
Serial.print("Received Value from App: ");
for (int i = 0; i < rxValue.length(); i++) {
Serial.print(rxValue[i]);
}
Serial.println();
//Do stuff based on the command received from the app
if (rxValue.find("1") != -1) {
Serial.println("Turning ON!");
digitalWrite(LED_BUILTIN, HIGH);
}
else if (rxValue.find("0") != -1) {
Serial.println("Turning OFF!");
digitalWrite(LED_BUILTIN, LOW);
}
Serial.println();
Serial.println("=====END=RECEIVED=====");
}
}
};
#include <HX711_ADC.h>
#include <EEPROM.h>
//HX711 constructor (dout pin, sck pin):
HX711_ADC LoadCell(26, 25);
int eepromAdress = 0;
long t;
void calibrate() {
Serial.println("***");
Serial.println("Start calibration:");
Serial.println("It is assumed that the mcu was started with no load applied to the load cell.");
Serial.println("Now, place your known mass on the loadcell,");
Serial.println("then send the weight of this mass (i.e. 100.0) from serial monitor.");
float m = 0;
boolean f = 0;
while (f == 0) {
LoadCell.update();
if (Serial.available() > 0) {
m = Serial.parseFloat();
if (m != 0) {
Serial.print("Known mass is: ");
Serial.println(m);
f = 1;
}
else {
Serial.println("Invalid value");
}
}
}
float c = LoadCell.getData() / m;
LoadCell.setCalFactor(c);
Serial.print("Calculated calibration value is: ");
Serial.print(c);
Serial.println(", use this in your project sketch");
f = 0;
Serial.print("Save this value to EEPROM adress ");
Serial.print(eepromAdress);
Serial.println("? y/n");
while (f == 0) {
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 'y') {
#if defined(ESP8266)
EEPROM.begin(512);
#endif
EEPROM.put(eepromAdress, c);
#if defined(ESP8266)
EEPROM.commit();
#endif
EEPROM.get(eepromAdress, c);
Serial.print("Value ");
Serial.print(c);
Serial.print(" saved to EEPROM address: ");
Serial.println(eepromAdress);
f = 1;
}
else if (inByte == 'n') {
Serial.println("Value not saved to EEPROM");
f = 1;
}
}
}
Serial.println("End calibration");
Serial.println("For manual edit, send 'c' from serial monitor");
Serial.println("***");
}
void changeSavedCalFactor() {
float c = LoadCell.getCalFactor();
boolean f = 0;
Serial.println("***");
Serial.print("Current value is: ");
Serial.println(c);
Serial.println("Now, send the new value from serial monitor, i.e. 696.0");
while (f == 0) {
if (Serial.available() > 0) {
c = Serial.parseFloat();
if (c != 0) {
Serial.print("New calibration value is: ");
Serial.println(c);
LoadCell.setCalFactor(c);
f = 1;
}
else {
Serial.println("Invalid value, exit");
return;
}
}
}
f = 0;
Serial.print("Save this value to EEPROM adress ");
Serial.print(eepromAdress);
Serial.println("? y/n");
while (f == 0) {
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 'y') {
#if defined(ESP8266)
EEPROM.begin(512);
#endif
EEPROM.put(eepromAdress, c);
#if defined(ESP8266)
EEPROM.commit();
#endif
EEPROM.get(eepromAdress, c);
Serial.print("Value ");
Serial.print(c);
Serial.print(" saved to EEPROM address: ");
Serial.println(eepromAdress);
f = 1;
}
else if (inByte == 'n') {
Serial.println("Value not saved to EEPROM");
f = 1;
}
}
}
Serial.println("End change calibration value");
Serial.println("***");
}
void setup() {
Serial.begin(9600);
//Create the BLE device
BLEDevice::init("ESP32");
//Set pinmode for the builting led (weight)
pinMode(LED_BUILTIN, OUTPUT);
//Create the BLE Server
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
//Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
//Create a BLE Characteristic
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
//BLE2902 needed to notify
pCharacteristic->addDescriptor(new BLE2902());
//Characteristic for the receiving end
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
//Start the Service
pService->start();
//Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting for a client connection to notify...");
delay(10);
Serial.println();
Serial.println("Starting...");
LoadCell.begin();
long stabilisingtime = 2000; // tare preciscion can be improved by adding a few seconds of stabilising time
LoadCell.start(stabilisingtime);
if (LoadCell.getTareTimeoutFlag()) {
Serial.println("Tare timeout, check MCU>HX711 wiring and pin designations");
}
else {
LoadCell.setCalFactor(1.0); // user set calibration value (float)
Serial.println("Startup + tare is complete");
}
while (!LoadCell.update());
calibrate();
}
void loop() {
//update() should be called at least as often as HX711 sample rate; >10Hz@10SPS, >80Hz@80SPS
//longer delay in sketch will reduce effective sample rate (be carefull with delay() in the loop)
LoadCell.update();
//get smoothed value from the data set
if (deviceConnected) {
txValue = LoadCell.getData();
//Conversion of txValue
char txString[8];
dtostrf(txValue, 1, 2, txString);
//Setting the value to the characteristic
pCharacteristic->setValue(txString);
//Notifying the connected client
pCharacteristic->notify();
Serial.println("Sent value: " + String(txString));
delay(50);
}
//receive from serial terminal
if (Serial.available() > 0) {
float i;
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay();
else if (inByte == 'c') changeSavedCalFactor();
}
//check if last tare operation is complete
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
}
}