Motor Speed Controlling via ASCII Commands Using Arduino MEGA 2560

Greetings ...

I hope that you are good

I am using two brushless motors to control the speed wirelessly using a half duplex radio module with arduino mega 2560.

The speed is control by giving commands like <C+010> for both motors with 10 percent speed, <A+010> to run motor A similarly <B+010> to run motor B.

Please see the following problems that I am facing right now

First Problem:
by using this command " <C+010>" I manage to run both motors successfully but when the motors stop then again when I tried to run both motors with the same command then it could not be run again. I tried to change the command then it runs; Please tell me How is it possible to to run it again with the same command? Repeat command is not working

//Please skip the second Problem
Second Problem:
I tried to run both motors with this command "<A+010><B+010>" enter on a serial monitor but only one motor is running while another motor does not; I want to run two motors at the same time with this command "<A+010><B+010>". Please tell me ...

Third Problem:
I implement the timer of two seconds such that if there will be no command after a signal lost then both motors would stop immediately after 2 seconds. Did I implement it in a correct way ?

Fourth Problem:
With this command <C+001>, the motors could not be run at 1, 2, 3 and percent duty cycles, it started from 5 percent <C+005>,<C+006>,....to onwards duty cycle in a forward direction and , ,......to onwards in a reverse direction . Is it possible to run those motors starts from one percent duty cycle <C+001>..... so on and ,..... so on in the both directions?

Fifth Problem:
Did I implement an increment and decrement functions for both the motors in a correct way?

Thank you so much

Here is the code

// ONLY FOR MOTORS VIA COMMANDS ON A SERIAL MONITOR

#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

// 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 = 1581; // R1 1581, 1597
float R2 = 1000; // R2 1000, 1000
int readValue = 0;
long previousMillis_battery = 0;
byte Bat_start_timer = 0;
//int battery_wait = 0;
unsigned long battery_wait = 0;
unsigned long currentMillis = 0; // VALID FOR ALL FUNCTIONS(COUNTER)

// OLD 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 = 60000;
  if (currentMillis - previousMillis_battery > battery_wait) {
    Serial.print("$ABC,"); Serial.print(Voltage); Serial.print("V"); Serial.print('\n');

    previousMillis_battery = currentMillis;
    battery_wait = 60000;
    Bat_start_timer = 1;
  }
  currentMillis = millis(); // to monitor/print voltages on a serial monitor

} // 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;

String String1;
String inputString1 = "";         // a String to hold incoming data
boolean NewDataFlag1 = 0;
unsigned int Serial1Timeout = 0;
bool String1Complete = false;

int CurrentAPwm = NEUTRAL;
int CurrentBPwm = NEUTRAL;

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
  Serial3.begin(BaudRate); // user local
  Serial1.begin(BaudRate); // gps sensor port
  Serial2.begin(BaudRate); // dep sensor port

  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() {

  // battery-send
  static int runit;
  if (runit == 1000) {
    battery();
    runit = 0;
  }
  runit++;

// timer of 2 seconds
  timeNow = millis();
  serialEvent();

  if (TaskNumber == 0) {
    //  if we've gone 2-seconds...
    if ((timeNow - msgTimeout) >= 2000ul)
    {
      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);
        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);
      }//ELSE
    }

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

      }
      else {
        if (BFwdFlag == 1) //A
        {
          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);
      }//ELSE
    }
    TaskNumber = 0;
  }

  // MOTORS INCREMENT AND DECREMENT FUNCTION
  if (APwm > CurrentAPwm)
  {
    CurrentAPwm ++;
    ESC_1.writeMicroseconds(CurrentAPwm);

  }
  if (APwm < CurrentAPwm)
  {
    CurrentAPwm --;
    ESC_1.writeMicroseconds(CurrentAPwm);
  }
  if (BPwm > CurrentBPwm)
  {
    CurrentBPwm ++;
    ESC_2.writeMicroseconds(CurrentBPwm);

  }
  if (BPwm < CurrentBPwm)
  {
    CurrentBPwm --;
    ESC_2.writeMicroseconds(CurrentBPwm);
  } //end

} //FUNCTION ENDS






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

  while (Serial.available()) {
    //    timeNow = millis();
    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 = "";
    }
  }
}

your command processing seems complicated and should be tested independently for reliable operation

consider pcRead() which i put into almost all my code for debugging. reading a numeric first and recognizing a single char command last makes things easier

// pcRead - debugging using serial monitor

const char version [] = "PcRead 201114a";

int debug = 0;

// ---------------------------------------------------------
// toggle output bit
int
readString (
    char *s,
    int   maxChar )
{
    int  n = 0;

    Serial.print ("> ");
    do {
        if (Serial.available()) {
            int c    = Serial.read ();

            if ('\n' == c)
                break;

            s [n++] = c;
            if (maxChar == n)
                break;
        }
    } while (true);

    return n;
}

// -----------------------------------------------------------------------------
// process single character commands from the PC
#define MAX_CHAR  10
char s [MAX_CHAR] = {};

int  analogPin = 0;

void
pcRead (void)
{

    static int  val = 0;

    if (Serial.available()) {
        int c = Serial.read ();

        switch (c)  {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            val = c - '0' + (10 * val);
            break;

        case 'A':
            analogPin = val;
            Serial.print   ("analogPin = ");
            Serial.println (val);
            val = 0;
            break;

        case 'D':
            debug ^= 1;
            break;

        case 'I':
            pinMode (val, INPUT);
            Serial.print   ("pinMode ");
            Serial.print   (val);
            Serial.println (" INPUT");
            val = 0;
            break;

        case 'O':
            pinMode (val, OUTPUT);
            Serial.print   ("pinMode ");
            Serial.print   (val);
            Serial.println (" OUTPUT");
            val = 0;
            break;

        case 'P':
            pinMode (val, INPUT_PULLUP);
            Serial.print   ("pinMode ");
            Serial.print   (val);
            Serial.println (" INPUT_PULLUP");
            val = 0;
            break;


        case 'a':
            Serial.print   ("analogRead: ");
            Serial.println (analogRead (val));
            val = 0;
            break;

        case 'c':
            digitalWrite (val, LOW);
            Serial.print   ("digitalWrite: LOW  ");
            Serial.println (val);
            val = 0;
            break;

        case 'p':
#if !defined(ARDUINO_ARCH_ESP32)
            analogWrite (analogPin, val);
            Serial.print   ("analogWrite: pin ");
            Serial.print   (analogPin);
            Serial.print   (", ");
            Serial.println (val);
            val = 0;
#endif
            break;

        case 'r':
            Serial.print   ("digitalRead: pin ");
            Serial.print   (val);
            Serial.print   (", ");
            Serial.println (digitalRead (val));
            val = 0;
            break;

        case 's':
            digitalWrite (val, HIGH);
            Serial.print   ("digitalWrite: HIGH ");
            Serial.println (val);
            val = 0;
            break;

        case 't':
            Serial.print   ("pinToggle ");
            Serial.println (val);
            digitalWrite (val, ! digitalRead (val));
            val = 0;
            break;

        case 'v':
            Serial.print ("\nversion: ");
            Serial.println (version);
            break;

        case '\n':          // ignore
            break;

        case '"':
            while ('\n' != Serial.read ())     // discard linefeed
                ;

            readString (s, MAX_CHAR-1);
            Serial.println (s);
            break;

        case '?':
            Serial.println ("\npcRead:\n");
            Serial.println ("    [0-9] append to #");
            Serial.println ("    A # - set analog pin #");
            Serial.println ("    D # - set debug to #");
            Serial.println ("    I # - set pin # to INPUT");
            Serial.println ("    O # - set pin # to OUTPUT");
            Serial.println ("    P # - set pin # to INPUT_PULLUP");
            Serial.println ("    a # - analogRead (pin #)");
            Serial.println ("    c # - digitalWrite (pin #, LOW)");
            Serial.println ("    p # -- analogWrite (analogPin, #)");
            Serial.println ("    r # - digitalRead (pin #)");
            Serial.println ("    s   - digitalWrite (pin #, HIGH)");
            Serial.println ("    t   -- toggle pin # output");
            Serial.println ("    v   - print version");
            Serial.println ("    \"   - read string");
            Serial.println ("    ?   - list of commands");
            break;

        default:
            Serial.print ("unknown char ");
            Serial.println (c,HEX);
            break;
        }
    }
}

// -----------------------------------------------------------------------------
void
loop (void)
{
    pcRead ();
}

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

    Serial.println (version);
#if defined(ARDUINO_ARCH_ESP32)
    Serial.println ("esp32");
#endif
}

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