Motor control using Bluetooth

Hello all,
I'm very new to programming and have definitively gained some respect for the people that do it on daily basis.

my end goal is to have a motor that is capable of being actuated with a BLE remote *trying classic BT for now, as i know BLE adds another level of complexity.

I would like for the motor to turn a given number of rotations when button is press and held, and return to position "0 " as soon as button is released even if it has not reached the target. I can make this program work with a physical button, but I'm encountering difficulty when trying with BT.

currently the code is able to detect the incoming signal from BT but will stop reading the encoder as soon as the first loop is finished. I am using a very crude MITinventor app to send the signal from phone.

I suspect the issue to be the interrupt() not being triggered, any help is greatly appreciated.

#define ENCA 2 
#define ENCB 0 
#define PWM 17
#define IN2 18
#define IN1 19
//#define But 22 //---
#include "BluetoothSerial.h" 
BluetoothSerial ESP_BT;

const int MaxSpeed = 255; // set Range of speed from 60-255 (60 is min required for motion)
const int Pulses = 672; // 896 pulses = 4 (224 per rotation)
volatile int posi = 0; // specify posi as volatile: 
long prevT = 0;
float eprev = 0;
float eintegral = 0;
float revolutions;
int incoming;

void setup() {
  Serial.begin(19200);
 ESP_BT.begin("Motor Control");
  pinMode(ENCA,INPUT);
  pinMode(ENCB,INPUT);
 // pinMode(But,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ENCA),readEncoder,RISING);
  
  pinMode(PWM,OUTPUT);//---
  pinMode(IN1,OUTPUT);
  pinMode(IN2,OUTPUT); 
  }

void loop() {
    incoming = ESP_BT.read();

    if(incoming == 1){
    revolutions = (Pulses/224);
    Serial.println(String("Target set to: ")+ String(revolutions,2)+ String("  Revolutions"));
    int target = Pulses;
    PIDControl(target);
    }
   else{ 
    Serial.println("Going home");
   int target = 0;
   PIDControl(target);
    }
    delay(20);

  }
void PIDControl(int target){
  float kp = 10;
  float kd = 0.025;
  float ki = 0.0;

  // time difference
  long currT = micros();
  float deltaT = ((float) (currT - prevT))/( 1.0e6 );
  prevT = currT;
  int pos = 0; 
  noInterrupts(); // disable interrupts temporarily while reading
  pos = posi;
  interrupts(); // turn interrupts back on
  // error
  int e = pos - target;
  // derivative
  float dedt = (e-eprev)/(deltaT);
  // integral
  eintegral = eintegral + e*deltaT;
  // control signal
  float u = kp*e + kd*dedt + ki*eintegral;
  // motor power
  float pwr = fabs(u);
  if( pwr > MaxSpeed ){
    pwr = MaxSpeed;
  }
  // motor direction
  int dir = 1;
  if(u<0){
    dir = -1;
  }
  // signal the motor
  setMotor(dir,pwr,PWM,IN1,IN2);
  // store previous error
  eprev = e;
  Serial.print(target);
  Serial.print(" ");
  Serial.print(pos);
  Serial.println();
 // digitalRead(But);

  }
void setMotor(int dir, int pwmVal, int pwm, int in1, int in2){
  analogWrite(pwm,pwmVal);
  if(dir == 1){
    digitalWrite(in1,HIGH);
    digitalWrite(in2,LOW);
  }
  else if(dir == -1){
    digitalWrite(in1,LOW);
    digitalWrite(in2,HIGH);
     }
  else{
    digitalWrite(in1,LOW);
    digitalWrite(in2,LOW);
  }  
  }
void readEncoder(){
  int b = digitalRead(ENCB);
  if(b > 0){
    posi++;
  }
  else{
    posi--;
  }
  }

Reading the encoder might be too slow to be inside the ISR. Just set a "flag" in your ISR that a pulse happened and process the meaning of the flag (if ENCB++ or --) in your main sketch.

1 Like

Every time through loop, you read ESP_BT.read(), even if nothing is available. This will most likely cause your "else" clause to be executed every time through loop() which mean going home.

The much more typical approach is to see if anything if available first. If it is, read it and act upon it. If nothing is available, don't do anything this iteration of loop().

1 Like

tried :

and it worked like a charm, Thanks.

You don't need that while() loop inside of loop(). Let loop() do what it was born to do :slight_smile:

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