Motor Speed Increment Step by Step

Hi
I hope that you are doing good.

I am using a joystick to wirelessly control two motors; when I move the joystick in the forward direction or any other direction then it runs with a full speed. I want to do an increment in my motor speed so when I move the joystick then it should run and increases the speed step by step with respect to the joystick movement. Please tell me how to do it ...

Here is the code that I m using

int VRx=A1; // ANALOG READING FOR LEFT AND RIGHT MOVEMENT FOR X-AXIS
int VRy=A0; // ANALOG READING FOR UPWARD AND DOWNWARD MOVEMENT FOR Y-AXIS
int Sw=2; //
float Aval; //VALUE OF VOLTAGE AT A1PORT
float Bval; //VALUE OF VOLTAGE AT A0 PORT
unsigned int MAXIMUM = 1023; //MAXIMUM RESOLUTION
unsigned int MID = 512;
unsigned int MAX = 1023;





void setup() {

Serial.begin(4800);
pinMode(VRx,INPUT);
pinMode(VRy,INPUT);
pinMode(Sw,INPUT);

}
 
void loop() {


 unsigned long tempA=0; // MOTOR A motor speed value start from zero
 unsigned long tempA1=0; //FORMULA
 unsigned long tempA2=0; //FORMULA
  Aval=analogRead(VRx);
 tempA = Aval;
 Serial.println (tempA);
 
 Serial.println(" JOYSTICK NEUTRAL POSITION");
 Serial.print("VRX: ");
 Serial.print(analogRead(VRx));
 Serial.print(" | ");
 Serial.print("VRY: ");
 Serial.print(analogRead(VRy));
 Serial.println(" | ");
 

 
 unsigned long tempB=0;  // MOTOR B motor speed value start from zero
 unsigned long tempB1=0; // Formula
 unsigned long tempB2=0; // Formula
 Bval=analogRead(VRy);
 tempB = Bval;
 Serial.println (tempB);

 

 //FORWARD DONE SUCCESSFULLY
 //===========================================================================//
 if ((tempB>550) && (tempA>450 && tempA<550)){                     
  tempB1 = (((tempB-MID)*100)/MID);
  char st[20]; // Send command to the buffer Vx as a statement for motor A
  char st1[20]; // Send command  Vy as a statement for motor B
 sprintf(st,"<A+%03lu>",tempB1);
 sprintf(st1,"<B+%03lu>",tempB1);
 Serial.println (st);
 Serial.println (st1);
}


 //BACKWARD DONE SUCCESSFULLY
 //===========================================================================//
 if ((tempB<450) && (tempA>450 && tempA<550)){                     
 tempB1= (((MID - tempB)*100)/MID);
  char st[20];
  char st1[20];
 sprintf(st,"<A-%03lu>",tempB1);
 sprintf(st1,"<B-%03lu>",tempB1);
 Serial.println (st);
 Serial.println (st1);

 }

 //NEUTRAL DONE SUCCESSFULLY
 //===========================================================================//
 if ((tempB>450 && tempB<550) && (tempA>450 && tempA<550)){         
  char st[20];
 Serial.println ("<A+000>");
 Serial.println ("<B+000>");
  }

//PURE LEFT MOVEMENT MOTOR // DONE SUCCESSFULLY
//===========================================================================//
if ((tempA<450) && (tempB>450 && tempB<550)){ 
  tempA1=(((MID-tempA)*100)/MID);                
 char st[20];
 char st1[20];
 sprintf(st1,"<B+%03lu>",tempA1);
 Serial.println (st1);
 }

 //PURE RIGHT MOVEMENT MOTOR // DONE SUCCESSFULLY
//===========================================================================//
 if ((tempA>550) && (tempB>450 && tempB<550))
  {
    tempA1 = (((tempA-MID)*100)/MID);
    
  char st[20];
 char st1[20];
 sprintf(st,"<A+%03lu>",tempA1);
 Serial.println (st);
 }


// FORWARD RIGHT MOVEMENT BOTH MOTORS; LEFT MOTOR SPEED IS HIGH AND RIGHT MOTOR SPEED IS LOW //DONE SUCCESSFULLY
//=============================================================================================================//
 if ((tempA>550) && tempB>550)
  {                                                           
  tempA1 = ((tempB * 100)/MAX);
  tempB1 = (((tempA - MID)*100)/(MAX - MID));
  tempB2 = (tempA1 -  ((tempB1 * tempA1)/100));  
  char st[20];
  char st1[20];
 sprintf(st,"<A+%03lu>",tempA1);
 sprintf(st1,"<B+%03lu>",tempB2);
 Serial.println (st);
 Serial.println (st1);
 }

// FORWARD LEFT MOVEMENT BOTH MOTORS; LEFT MOTOR SPEED IS LOW AND RIGHT MOTOR SPEED IS HIGH //DONE SUCCESSFULLY
  //==========================================================================================================//
 if ((tempA<450) && (tempB>550))
 { 
  tempB1=((tempB * 100)/ MAX );                         
  tempA1 = (100 - ((tempA * 100)/(MID)));
  tempA2 = (tempB1 -  ((tempA1 * tempB1)/100));
  char st[20];
  char st1[20];
 sprintf(st,"<A+%03lu>",tempA2);
 sprintf(st1,"<B+%03lu>",tempB1);
 Serial.println (st);
 Serial.println (st1);

 }



// REVERSE RIGHT MOVEMENT BOTH MOTORS; LEFT MOTOR SPEED IS HIGH (MOVING ANTICLOCKWISE) AND RIGHT MOTOR SPEED IS LOW (MOVING CLOCKWISE)
//====================================================================================================================================//

if (tempA>550 && tempB<450)
  {                                          
  tempA1 = (((MID - tempB) * 100) / (MID) );
  tempB1 = (((tempA - MID)*100)/(MAX - MID));
  tempB2 = (tempA1 - ((tempB1 * tempA1)/100 ));
  char st[20];
  char st1[20];
 sprintf(st,"<A-%03lu>",tempA1);
 sprintf(st1,"<B-%03lu>",tempB2);
 Serial.println (st);
 Serial.println (st1);

 }


// REVERSE LEFT MOVEMENT BOTH MOTORS; LEFT MOTOR SPEED IS LOW (MOVING CLOCKWISE) AND RIGHT MOTOR SPEED IS HIGH (MOVING ANTICLOCKWISE)
// ===================================================================================================================================//

 if (tempA<450 && tempB<450)                    
  {                                                            
  
  tempB1= (((MID - tempB) * 100)/(MID));
  tempA1= (100 - ((tempA * tempB1)/(MID)));
  tempA2= (tempB1 - ((tempA1 * tempB1)/100));
  char st[20];
  char st1[20];
 sprintf(st,"<A-%03lu>",tempA2);
 sprintf(st1,"<B-%03lu>",tempB1);
 Serial.println (st);
 Serial.println (st1);

 }


}

Hello, and thank you for using code tags.

It's not clear what you want help with. Your code does not control motors, only prints some values to serial monitor. I think these numbers represent the desired motor speeds?

tempB1 = (((tempB-MID)*100)/MID);

Do code lines, like the one above, fail to achieve the speed increment you need? If not, please describe in more detail what you see on serial monitor and what you expected to see.

When showing output from Serial monitor, please copy the text and paste it into your post between code tags.

Here is the actual code in the receiving section of the two motors.

#include <Servo.h>
const int m_1 = 5;
const int m_2 = 6;
const int LED = 13;
String strID = "";
//String GPSmessage = "";
//String DEPmessage = ""; // message buffer
//bool msgEOL = false; // EOL flag
//bool depEOL = false;
int BaudRate = 4800;
Servo ESC_1; // create servo object to control the ESC 1
Servo ESC_2; // create servo object to control the ESC 2
#define FWD 0
#define BWD 1

unsigned long TimeoutTimer = 0;

//BATTERY READINGS VARIABLES
const int Battery = A0;
float Voltage = 0.0; //input battery voltage
float Voltage1 = 0.0; //output voltage for analog pin A0
float R1 = 1590; // R1 =47k ohms and 27k ohms resistors
float R2 = 1000; // R2 =10k ohms resistor 
int readValue = 0;
long previousMillis_battery = 0;
byte Bat_start_timer = 0;
int battery_wait;
unsigned long currentMillis = 0; // VALID FOR ALL FUNCTIONS(COUNTER)

//BATTERY FUNCTION
void battery()
{
 readValue = analogRead(Battery);
 Voltage1 = readValue * (5.0 / 1023.0); 
 Voltage = Voltage1 / (R2/(R1+R2));
 if(Bat_start_timer == 0) battery_wait = 2000;
 if(currentMillis - previousMillis_battery > battery_wait) {
       Serial.print("$ABC,"); Serial.print(Voltage); Serial.println("V\n");
  previousMillis_battery = currentMillis;
    battery_wait = 2000; Bat_start_timer = 1; }

} // battery FUNCTION END

unsigned int FORWARD = 2000;
unsigned int NEUTRAL = 1500;
unsigned int REVERSE = 1000;

unsigned int APwm = NEUTRAL;
unsigned int BPwm = NEUTRAL;

boolean ADirection = FWD;
boolean BDirection = FWD;
unsigned int AVelocity = 0; // CURRENT VELOCITY OF M1 in 0-100%
unsigned int BVelocity = 0; // CURRENT VELOCITY OF M2 in 0-100%

String inputString = "";
int TaskNumber = 0;

uint32_t msgTimeout = 0ul;
uint32_t timeNow;

unsigned int GetValue(void)// fetch three digit number value from received string and convert to INTEGER
{
  unsigned int Val = 0;
  Val = (inputString[3] - 48) * 100;
  Val = Val + (inputString[4] - 48) * 10;
  Val = Val + (inputString[5] - 48);
  return (Val);
}




void setup()
{
  Serial.begin(BaudRate); //RX0 for radiolink controlling two motors
  ESC_1.attach(m_1);// (pin, min pulse width, max pulse width in microseconds)
  ESC_2.attach(m_2);// (pin, min pulse width, max pulse width in microseconds)
  pinMode(LED, OUTPUT);
  pinMode(Battery, INPUT);
  Serial.println("ABC System Started");
  ESC_1.writeMicroseconds(APwm);
  ESC_2.writeMicroseconds(BPwm);

}



boolean AFwdFlag = 0; //makes sure that the serial only prints once the state
boolean BFwdFlag = 0; //makes sure that the serial only prints once the state



void loop()
{

 currentMillis = millis(); // to monitor voltages on a serial monitor 
  battery();  // battery function recall



  
  
  
serialEvent();

  timeNow = millis();

if( TaskNumber == 0 )
    {
        //if we've gone 5-seconds...
        if( (timeNow - msgTimeout) >= 5000ul )
        {
            //then all stop
            ESC_1.writeMicroseconds(NEUTRAL); 
            ESC_2.writeMicroseconds(NEUTRAL); 
            digitalWrite(LED, HIGH );  //<---- add this line

        }//if
        
    }//if

if( TaskNumber )
    {
        //each pass where we see a non-zero task #, reset the msgTimeout value
        msgTimeout = millis();
        digitalWrite(LED, LOW );  

  if(TaskNumber==1) Serial.println("OK");
  if(TaskNumber==2 || TaskNumber==4) {ESC_1.writeMicroseconds(NEUTRAL); }
  if(TaskNumber==3 || TaskNumber==4) {ESC_2.writeMicroseconds(NEUTRAL);}
  if(TaskNumber==5 || TaskNumber==7) {
                      if(ADirection==FWD) { APwm= NEUTRAL + (((FORWARD-NEUTRAL)/100)*AVelocity); ESC_1.writeMicroseconds(APwm); AFwdFlag=1; }
                      else {
                              if(AFwdFlag==1)
                               {
                                ESC_1.writeMicroseconds(NEUTRAL);delay(100);
                                ESC_1.writeMicroseconds(REVERSE);delay(100); 
                                ESC_1.writeMicroseconds(NEUTRAL);delay(100);
                                AFwdFlag=0;
                               } 
                              APwm= NEUTRAL - (((NEUTRAL-REVERSE)/100)*AVelocity); ESC_1.writeMicroseconds(APwm);  
                           }
                     } 


  if(TaskNumber==6 || TaskNumber==7) {
                      if(BDirection==FWD) { BPwm= NEUTRAL + (((FORWARD-NEUTRAL)/100)*BVelocity); ESC_2.writeMicroseconds(BPwm); BFwdFlag=1; }
                      else {
                              if(AFwdFlag==1)
                               {
                                ESC_2.writeMicroseconds(NEUTRAL);delay(100);
                                ESC_2.writeMicroseconds(REVERSE);delay(100); 
                                ESC_2.writeMicroseconds(NEUTRAL);delay(100);
                                BFwdFlag=0;
                               } 
                              BPwm= NEUTRAL - (((NEUTRAL-REVERSE)/100)*BVelocity); ESC_2.writeMicroseconds(BPwm);  
                           }
                     } 

 
  TaskNumber=0;
  
}

}



void serialEvent() { //radiolink for controlling two motors by command Serial port 0 

  while (Serial.available()) {

    char inChar = (char)Serial.read();
    inputString += inChar;

    if (inChar == '\r' || inChar == 10)
    {
      
      if(inputString[0]=='<') 
      {

        if(inputString[1]=='A' && inputString[2]=='T' && inputString[3]=='>' ) TaskNumber=1; // AT

        if(inputString[2]=='N' && inputString[3]=='>' )
        {
          if ( inputString[1] == 'A') TaskNumber = 2; // Set Motor A to Neutral
          if ( inputString[1] == 'B') TaskNumber = 3; // Set Motor B to Neutral
          if ( inputString[1] == 'C') TaskNumber = 4; // Set Both Motors to Neutral
        }
    
        if(inputString[6]=='>' )
        {
          
          if ( inputString[1] == 'A') { 
            if(inputString[2]=='+') ADirection=FWD; else ADirection=BWD; 
            AVelocity=GetValue(); 
            TaskNumber=5;
          }  
          
          if ( inputString[1] == 'B') { 
            if(inputString[2]=='+') BDirection=FWD; else BDirection=BWD; 
            BVelocity=GetValue(); 
            TaskNumber=6;
          }  
                    
          if ( inputString[1] == 'C'){ 
            if(inputString[2]=='+') { ADirection=FWD; BDirection=FWD;} 
            else {ADirection=BWD; BDirection=BWD;} 
            AVelocity=GetValue();
            BVelocity=GetValue(); 
            TaskNumber=7;
          }  
          
        }
  
      }
      inputString = "";
    }
  }
}

yes it shows the values on the percentage on the serial monitor with respect to the values changes with the motor speed according to the joystick movement.

APwm= NEUTRAL - (((NEUTRAL-REVERSE)/100)*AVelocity);

if AVelocity represents the position of the joystick as a percentage (i.e. 0-100) then APwm can change it's value from min to max in one step.

AVelocity could be used to determine when APwm is simply inc/decremented

#define Dead    5
    if (Dead < AVelocity)
        APwm++;
    else if (-Dead > AVelocity)
        APwm--

or it could be somewhat scaled (assuming AVelocity is signed)

#define Dead    5
    APwm += AVelocity / 5;
1 Like

Do you represent #Dead 5 as a Neutral ? Sorry to asked because I'm learning ...

okay, let me try it first :slight_smile:

DeadBand
couldn't think of it at the time

I tried your code but It could not be successful ...

There are some changes that I made but still not successful ..

#include <Servo.h>
const int m_1 = 5;
const int m_2 = 6;
const int LED = 13;
String strID = "";

int BaudRate = 4800;
Servo ESC_1; // create servo object to control the ESC 1
Servo ESC_2; // create servo object to control the ESC 2
#define FWD 0
#define BWD 1

#define Dead 5

unsigned long TimeoutTimer = 0;

//BATTERY READINGS VARIABLES
const int Battery = A0;
float Voltage = 0.0; //input battery voltage
float Voltage1 = 0.0; //output voltage for analog pin A0
float R1 = 1590; // R1 =47k ohms and 27k ohms resistors
float R2 = 1000; // R2 =10k ohms resistor
int readValue = 0;
long previousMillis_battery = 0;
byte Bat_start_timer = 0;
int battery_wait;
unsigned long currentMillis = 0; // VALID FOR ALL FUNCTIONS(COUNTER)

//BATTERY FUNCTION
void battery()
{
  readValue = analogRead(Battery);
  Voltage1 = readValue * (5.0 / 1023.0);
  Voltage = Voltage1 / (R2 / (R1 + R2));
  if (Bat_start_timer == 0) battery_wait = 2000;
  if (currentMillis - previousMillis_battery > battery_wait) {
    Serial.print("$ABC,"); Serial.print(Voltage); Serial.println("V\n");
    previousMillis_battery = currentMillis;
    battery_wait = 2000; Bat_start_timer = 1;
  }

} // battery FUNCTION END

unsigned int FORWARD = 2000;
unsigned int NEUTRAL = 1500;
unsigned int REVERSE = 1000;

unsigned int APwm = NEUTRAL;
unsigned int BPwm = NEUTRAL;

boolean ADirection = FWD;
boolean BDirection = FWD;
unsigned int AVelocity = 0; // CURRENT VELOCITY OF M1 in 0-100%
unsigned int BVelocity = 0; // CURRENT VELOCITY OF M2 in 0-100%

unsigned int NewValueA = AVelocity;
unsigned int NewValueB = BVelocity;


String inputString = "";
int TaskNumber = 0;

uint32_t msgTimeout = 0ul;
uint32_t timeNow;

unsigned int GetValue(void)// fetch three digit number value from received string and convert to INTEGER
{
  unsigned int Val = 0;
  Val = (inputString[3] - 48) * 100;
  Val = Val + (inputString[4] - 48) * 10;
  Val = Val + (inputString[5] - 48);
  return (Val);
}




void setup()
{
  Serial.begin(BaudRate); //RX0 for radiolink controlling two motors
  ESC_1.attach(m_1);// (pin, min pulse width, max pulse width in microseconds)
  ESC_2.attach(m_2);// (pin, min pulse width, max pulse width in microseconds)
  pinMode(LED, OUTPUT);
  pinMode(Battery, INPUT);
  Serial.println("ABC System Started");
  ESC_1.writeMicroseconds(APwm);
  ESC_2.writeMicroseconds(BPwm);

}



boolean AFwdFlag = 0; //makes sure that the serial only prints once the state
boolean BFwdFlag = 0; //makes sure that the serial only prints once the state



void loop()
{

  currentMillis = millis(); // to monitor voltages on a serial monitor
  battery();  // battery function recall






  serialEvent();

  timeNow = millis();

  if ( TaskNumber == 0 )
  {
    //if we've gone 5-seconds...
    if ( (timeNow - msgTimeout) >= 5000ul )
    {
      //then all stop
      ESC_1.writeMicroseconds(NEUTRAL);
      ESC_2.writeMicroseconds(NEUTRAL);
      digitalWrite(LED, HIGH );  //<---- add this line

    }//if

  }//if

  if ( TaskNumber )
  {
    //each pass where we see a non-zero task #, reset the msgTimeout value
    msgTimeout = millis();
    digitalWrite(LED, LOW );

    if (TaskNumber == 1) Serial.println("OK");
    if (TaskNumber == 2 || TaskNumber == 4) {
      ESC_1.writeMicroseconds(NEUTRAL);
    }
    if (TaskNumber == 3 || TaskNumber == 4) {
      ESC_2.writeMicroseconds(NEUTRAL);
    }
    if (TaskNumber == 5 || TaskNumber == 7) {
      if (ADirection == FWD) {
        APwm = NEUTRAL + (((FORWARD - NEUTRAL) / 100) * AVelocity);
        ESC_1.writeMicroseconds(APwm);
        if (NewValueA =! APwm)
        {
          if (NewValueA > APwm)
          {
            APwm++;
            } 
        }
        AFwdFlag = 1;
      }
      
      else {
        if (AFwdFlag == 1)
        {
          ESC_1.writeMicroseconds(NEUTRAL); delay(100);
          ESC_1.writeMicroseconds(REVERSE); delay(100);
          ESC_1.writeMicroseconds(NEUTRAL); delay(100);
          AFwdFlag = 0;
        }
        APwm = NEUTRAL - (((NEUTRAL - REVERSE) / 100) * AVelocity);
        ESC_1.writeMicroseconds(APwm);

              APwm--;
         
   }
    
    }
    


    if (TaskNumber == 6 || TaskNumber == 7) {
      if (BDirection == FWD) {
        BPwm = NEUTRAL + (((FORWARD - NEUTRAL) / 100) * BVelocity);
        ESC_2.writeMicroseconds(BPwm);
        if (NewValueB =! BPwm)
        {
          if (NewValueB > BPwm)
          {
            BPwm++;
            } 
        }

        BFwdFlag = 1;
      }
      else {
        if (AFwdFlag == 1)
        {
          ESC_2.writeMicroseconds(NEUTRAL); delay(100);
          ESC_2.writeMicroseconds(REVERSE); delay(100);
          ESC_2.writeMicroseconds(NEUTRAL); delay(100);
          BFwdFlag = 0;
        }
        BPwm = NEUTRAL - (((NEUTRAL - REVERSE) / 100) * BVelocity);
        ESC_2.writeMicroseconds(BPwm);
        BPwm--;
      }
    }


    TaskNumber = 0;

  }

}



void serialEvent() { //radiolink for controlling two motors by command Serial port 0

  while (Serial.available()) {

    char inChar = (char)Serial.read();
    inputString += inChar;

    if (inChar == '\r' || inChar == 10)
    {

      if (inputString[0] == '<')
      {

        if (inputString[1] == 'A' && inputString[2] == 'T' && inputString[3] == '>' ) TaskNumber = 1; // AT

        if (inputString[2] == 'N' && inputString[3] == '>' )
        {
          if ( inputString[1] == 'A') TaskNumber = 2; // Set Motor A to Neutral
          if ( inputString[1] == 'B') TaskNumber = 3; // Set Motor B to Neutral
          if ( inputString[1] == 'C') TaskNumber = 4; // Set Both Motors to Neutral
        }

        if (inputString[6] == '>' )
        {

          if ( inputString[1] == 'A') {
            if (inputString[2] == '+') ADirection = FWD; else ADirection = BWD;
            AVelocity = GetValue();
            TaskNumber = 5;
          }

          if ( inputString[1] == 'B') {
            if (inputString[2] == '+') BDirection = FWD; else BDirection = BWD;
            BVelocity = GetValue();
            TaskNumber = 6;
          }

          if ( inputString[1] == 'C') {
            if (inputString[2] == '+') {
              ADirection = FWD;
              BDirection = FWD;
            }
            else {
              ADirection = BWD;
              BDirection = BWD;
            }
            AVelocity = GetValue();
            BVelocity = GetValue();
            TaskNumber = 7;
          }

        }

      }
      inputString = "";
    }
  }
}

THESE CHANGES I MADE

these aren't the changes i suggested

why are you comparing the joystick input, AVelocity to the output, APwm, especially after have already set APwm