Motor works via serial monitor, but not via BLE - ESP32

I use a DC controller DRV8871 and an ESP32. The connections are perfect because the motor starts forward and reverse.

First I'll give a bit of context:
I use the ESP32 BLE, it works fine to send and receive data. I also use the serial monitor readout to send data to the ESP32.

When I send a command via serial monitor it reads perfectly, if I indicate 4 it goes forward, if I indicate 5 it goes backwards, if indoc 6 it stops, all perfect.

If I connect via bluetooth, the same thing works. EVERYTHING WORKS, except the change of direction of the motor. That is, in one direction it works fine, but not the other.

Here my code:

// Actuadores
#define MOTORS_IN1 32
#define MOTORS_IN2 33
int reposition = 0;

// Bluetooth
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
int data_blue = 0;
BLEServer *pServer = NULL;
BLECharacteristic *pCharacteristic;

bool deviceConnected = false;
bool oldDeviceConnected = false;

float data_0;
int data_1;
int battery;

const int LED = 2;
float txValue = 0;
const int readPin = 32; // Use GPIO number. See ESP32 board pinouts

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID_TX "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"

//ESP32 AnalogWrite
#include <analogWrite.h>

//Receive data serial
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;

// Bluetooth
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
      BLEDevice::startAdvertising();
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();
      if (rxValue.length() > 0) {
        //Serial.print("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++) {
          Serial.print(rxValue[i]);
        }
        Serial.println();
        // Control via bluetooth
        // Adelante
        if (rxValue.find("4") != -1) {
          newData = true;
          data_blue = 4;
        }
        // Atrás
        if (rxValue.find("5") != -1) {
          newData = true;
          data_blue = 5;
        }
        // Parar
        if (rxValue.find("6") != -1) {
          newData = true;
          data_blue = 6;
        }
      }
    }
};

void setup() {
  Serial.begin(115200);

  // Indicaciones para el control
  Serial.println("Adelante - 4");
  Serial.println("Atrás - 5");
  Serial.println("Parar - 6");

  pinMode(MOTORS_IN1, OUTPUT);
  pinMode(MOTORS_IN2, OUTPUT);

  // Bluetooth
  pinMode(LED, OUTPUT);
  // Create the BLE Device
  BLEDevice::init("Adam");
  // 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
                    );
  // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
  // Create a BLE Descriptor
  pCharacteristic->addDescriptor(new BLE2902());
  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 a client connection to notify...");
}
  
void loop() {
  recvWithEndMarker();
  microControl();
  notifyData();
  checkToReconnect();
}

void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;
  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();
    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0';
      ndx = 0;
      newData = true;
    }
  }
}


void stopMotors() {
  Serial.println("Stop");  
  digitalWrite (MOTORS_IN1, LOW);
  analogWrite (MOTORS_IN2, 0);
}

void adelanteMotors() {
  Serial.println("Adelante");
  digitalWrite(MOTORS_IN1, HIGH);
  analogWrite(MOTORS_IN2, 0);
}

void atrasMotors() {
  Serial.println("Atrás");
  digitalWrite(MOTORS_IN1, LOW);
  analogWrite(MOTORS_IN2, 255);
}

void microControl() {
  state_1 = digitalRead(end_1);
  state_2 = digitalRead(end_2);

  if (newData == true) {
    // Adelante
    if (receivedChars[0] == '4' || data_blue == 4) {
      adelanteMotors();
    }
    // Atrás
    if (receivedChars[0] == '5' || data_blue == 5) {
      atrasMotors();
    }
    // Parar
    if (receivedChars[0] == '6' || data_blue == 6) {
      stopMotor();
      stopMotors();
    }
    newData = false;
    data_blue = 0;
  }
}

void checkToReconnect() { //added
  // disconnected so advertise
  if (!deviceConnected && oldDeviceConnected) {
    delay(500); // give the bluetooth stack the chance to get things ready
    pServer->startAdvertising(); // restart advertising
    Serial.println("Disconnected: start advertising");
    oldDeviceConnected = deviceConnected;
  }
  // connected so reset boolean control
  if (deviceConnected && !oldDeviceConnected) {
    // do stuff here on connecting
    Serial.println("Reconnected");
    oldDeviceConnected = deviceConnected;
  }
}

void notifyData() {
  // Notify changed value
  if (deviceConnected) {
    txValue = analogRead(readPin) / 3.456; // This could be an actual sensor reading!
    //convert float txvalue to string
    char data_0[8]; // make sure this is big enuffz
    dtostrf(txValue, 1, 2, data_0);

    data_1 = 1;
    battery = 49;

    String str = "";
    str += data_0;
    str += ",";
    str += data_1;
    str += ",";
    str += battery;
    
    pCharacteristic->setValue((char*)str.c_str());
    pCharacteristic->notify();

    //Serial.println("*** Sent Value: ");
    //Serial.println(data_0);
    //Serial.println(data_1);
    //Serial.println(battery);
    //Serial.println(" ***");

    // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
  }
  delay(500);
}


The important code snippets are where it says:
class MyCallbacks: public BLECharacteristicCallbacks {

That is used to receive from bluetooth.

...and void microControl() {
This is used to receive the data from the serial monitor.

You can see that void microControl() { has sends to functions.

The function that fails ONLY WITH BLUETOOTH is
adelanteMotors();

void adelanteMotors() {
  Serial.println("Adelante");
  digitalWrite(MOTORS_IN1, HIGH);
  analogWrite(MOTORS_IN2, 0);
}

If I press 5 it sends me to the function atrasMotors(); and it works perfectly.

void atrasMotors() {
  Serial.println("Atrás");
  digitalWrite(MOTORS_IN1, LOW);
  analogWrite(MOTORS_IN2, 255);
}

(That last one works fine.).

With the simple fact that I connect to Bluetooth, the void adelanteMotors() stops working.

void adelanteMotors() {
  Serial.println("Adelante");
  digitalWrite(MOTORS_IN1, HIGH);
  analogWrite(MOTORS_IN2, 0);
}

Please help.

Like I said, everything works fine except that. I have not the slightest idea why it happens.

Note: when I say that it stops working, or that it doesn't work... I mean that it stops working even in the serial monitor.

That is, I do the following:

  1. I access serial monitor, send 4, it works, send 5, it works.
  2. I access bluetooth from the smartphone, I close the app or leave it open (it doesn't matter if I close or if I don't do anything, just by connecting).
  3. I access the same serial monitor window, send 4 doesn't work, send 5 works.
  4. I open and close serial monitor (reboot), I send 4 and it works, I send 5 and it works.

the code presented in the first post will not even compile, e.g.

sketch_mar24e:170:3: error: 'state_1' was not declared in this scope
   state_1 = digitalRead(end_1);
   ^
sketch_mar24e:170:25: error: 'end_1' was not declared in this scope
   state_1 = digitalRead(end_1);
                         ^
sketch_mar24e:171:3: error: 'state_2' was not declared in this scope
   state_2 = digitalRead(end_2);
   ^
sketch_mar24e:171:25: error: 'end_2' was not declared in this scope
   state_2 = digitalRead(end_2);
                         ^
sketch_mar24e:184:17: error: 'stopMotor' was not declared in this scope
       stopMotor();

what ESP board are you using

Try adding two more lines:

    }
    newData = false;
    data_blue = 0;
    receivedChars[0] = '\0';
    ndx = 0;
  }

I think the problem is that when input from the BLE interface sets the 'newData' flag you are going to look at the first character of 'receivedChars' as well as 'data_blue'. If that character is a valid command (left over from previous serial input) it is going to be executed along with the 'data_blue' command.

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