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.).