Running Motor When Serial Command If Statement Triggers not working

I have connected an Arduino to a raspberry pi so that a specific event is triggered when I send a signal(in this case a number). When I send a number with the script and tell it just to print in serial monitor it works, when I try and just have it run the motors on start it works fine, however when combining the two: having it run a specific command if a particular number is received nothing happens. If anyone could point to the flaw here, I would be very grateful. I have even connected the if statement to toggle the onboard LED, and that works but when connecting it with the motor nothing happens.
Code:

#include <Arduino.h>

const byte MOTOR_A = 3;  // Motor 2 Interrupt Pin - INT 1 - Right Motor
const byte MOTOR_B = 2;  // Motor 1 Interrupt Pin - INT 0 - Left Motor
 
// Constant for steps in disk
const float stepcount = 20.00;  // 20 Slots in disk, change if different
 
// Constant for wheel diameter
const float wheeldiameter = 66.10; // Wheel diameter in millimeters, change if different
const float gear_ratio = 34;
const float PPR = 12;

// Integers for pulse counters
volatile int counter_A = 0;
volatile int counter_B = 0;
 
 
// Motor A
 
int enA = 10;
int in1 = 9;
int in2 = 8;
 
// Motor B
 
int enB = 5;
int in3 = 7;
int in4 = 6;
 
// Interrupt Service Routines
 
// Motor A pulse count ISR
void ISR_countA()  
{
  counter_A++;  // increment Motor A counter value
} 
 
// Motor B pulse count ISR
void ISR_countB()  
{
  counter_B++;  // increment Motor B counter value
}
 
// Function to convert from centimeters to steps
int CMtoSteps(float cm) 
{
  float circumference = (wheeldiameter * 3.14) / 10; // Calculate wheel circumference in cm
  
  return int(cm * gear_ratio * PPR / circumference); 
 
}
 
// Function to Move Forward
void MoveForward(int steps, int mspeed) 
{
   counter_A = 0;  //  reset counter A to zero
   counter_B = 0;  //  reset counter B to zero
   
   // Set Motor A forward
   digitalWrite(in1, HIGH);
   digitalWrite(in2, LOW);
 
   // Set Motor B forward
   digitalWrite(in3, HIGH);
   digitalWrite(in4, LOW);
   
   // Go forward until step value is reached
   while (steps > counter_A or steps > counter_B) {
   
    if (steps > counter_A) {
    analogWrite(enA, mspeed);
    } else {
    analogWrite(enA, 0);
    }
    if (steps > counter_B) {
    analogWrite(enB, mspeed);
    } else {
    analogWrite(enB, 0);
    }
   }
    
  // Stop when done
  analogWrite(enA, 0);
  analogWrite(enB, 0);
  counter_A = 0;  //  reset counter A to zero
  counter_B = 0;  //  reset counter B to zero 
 
}
 
// Function to Move in Reverse
void MoveReverse(int steps, int mspeed) 
{
   counter_A = 0;  //  reset counter A to zero
   counter_B = 0;  //  reset counter B to zero
   
   // Set Motor A reverse
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
 
  // Set Motor B reverse
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
   
   // Go in reverse until step value is reached
   while (steps > counter_A && steps > counter_B) {
   
    if (steps > counter_A) {
    analogWrite(enA, mspeed);
    } else {
    analogWrite(enA, 0);
    }
    if (steps > counter_B) {
    analogWrite(enB, mspeed);
    } else {
    analogWrite(enB, 0);
    }
    }
    
  // Stop when done
  analogWrite(enA, 0);
  analogWrite(enB, 0);
  counter_A = 0;  //  reset counter A to zero
  counter_B = 0;  //  reset counter B to zero 
 
}
 
// Function to Spin Right
void SpinRight(int steps, int mspeed) 
{
   counter_A = 0;  //  reset counter A to zero
   counter_B = 0;  //  reset counter B to zero
   
   // Set Motor A reverse
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
 
  // Set Motor B forward
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
   
   // Go until step value is reached
   while (steps > counter_A && steps > counter_B) {
   
    if (steps > counter_A) {
    analogWrite(enA, mspeed);
    } else {
    analogWrite(enA, 0);
    }
    if (steps > counter_B) {
    analogWrite(enB, mspeed);
    } else {
    analogWrite(enB, 0);
    }
   }
    
  // Stop when done
  analogWrite(enA, 0);
  analogWrite(enB, 0);
  counter_A = 0;  //  reset counter A to zero
  counter_B = 0;  //  reset counter B to zero 
 
}
 
// Function to Spin Left
void SpinLeft(int steps, int mspeed) 
{
   counter_A = 0;  //  reset counter A to zero
   counter_B = 0;  //  reset counter B to zero
   
   // Set Motor A forward
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
 
  // Set Motor B reverse
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
   
   // Go until step value is reached
   while (steps > counter_A && steps > counter_B) {
   
    if (steps > counter_A) {
    analogWrite(enA, mspeed);
    } else {
    analogWrite(enA, 0);
    }
    if (steps > counter_B) {
    analogWrite(enB, mspeed);
    } else {
    analogWrite(enB, 0);
    }
  }
    
  // Stop when done
  analogWrite(enA, 0);
  analogWrite(enB, 0);
  counter_A = 0;  //  reset counter A to zero
  counter_B = 0;  //  reset counter B to zero 
 
}
 
void setup() 
{
  Serial.begin(9600);
  // Attach the Interrupts to their ISR's
  pinMode(MOTOR_A,INPUT);
  pinMode(MOTOR_B,INPUT);
  pinMode(in1,OUTPUT);
  pinMode(in2,OUTPUT);
  pinMode(in3,OUTPUT);
  pinMode(in4,OUTPUT);
  pinMode(enA,OUTPUT);
  pinMode(enB,OUTPUT);
  
  attachInterrupt(digitalPinToInterrupt (MOTOR_A), ISR_countA, RISING);  // Increase counter A when speed sensor pin goes High
  attachInterrupt(digitalPinToInterrupt (MOTOR_B), ISR_countB, RISING);  // Increase counter B when speed sensor pin goes High

} 
 
 
void loop()
{
  delay(100);
  int compareOne = 1;
  int compareTwo = 2;
  int compareThree = 3;
  if (Serial.available() > 0){
    String stringFromSerial = Serial.readString();
    if (stringFromSerial.toInt() == compareOne){
      Serial.println("Forward");
      MoveForward(CMtoSteps(50), 255);  // Forward half a metre at 255 speed
    }
    if (stringFromSerial.toInt() == compareTwo){
       Serial.println("Spin Right");
       SpinRight(CMtoSteps(10), 255);  // Right half a metre at 255 speed
    } 
    if (stringFromSerial.toInt() == compareThree){
      Serial.println("Spin Left");
      SpinLeft(CMtoSteps(10), 255);  // Right half a metre at 255 speed
    }
    else {
      Serial.println("Not equal");
    }
  }
  Put whatever you want here!
   MoveReverse(CMtoSteps(25.4),255);  // Reverse 25.4 cm at 255 speed
}

You can not use your counter_A and counter_B variables in your main code without disabling interrupts/making a copy/re-enabling interrupts or they could become corrupted. Int variables are 2 bytes and can not be atomically read/written.

You say that the motors work just fine by themselves. Does this mean if you just make a call

MoveForward(CMtoSteps(50), 255);

that it moves 50 cm and stops correctly? Or does it run forever? I am wondering if your interrupts are actually happening or not. How are they wired up? You have the pins defined as INPUT so they will need a pull-up or pull-down resistor.

In addition to what @blh64 said (which is a major issue) look at the following while loop. Your else blocks inside the the loop will never execute because as soon as one of the loop conditions is false the while loop will exit.

   while (steps > counter_A && steps > counter_B) {
   
    if (steps > counter_A) {
    analogWrite(enA, mspeed);
    } else {
    analogWrite(enA, 0);
    }
    if (steps > counter_B) {
    analogWrite(enB, mspeed);
    } else {
    analogWrite(enB, 0);
    }
    }

Unfortunately, I did not write this code - I got it from a freelancer. I am not a c++ programmer, so any direction on how to fix this massive problem would be appreciated. It does just run infinitely, and I haven't been able to figure out why(this is obviously the reason). I have attached to the main post the wireup and the hardware I am using. Any help would be amazing!

Thanks for the point out for this, first of all, I just noticed that shouldn't it be or for the while loop instead of and? Also, how would I fix the problem with the else blocks[I am not a c++ programmer as you can probably tell :frowning: ]

If the code runs indefinitely, it is most likely due to the code not getting any interrupts so it never reaches the destination number of steps. You could verify this by printing out your counter_A and counter_B variables inside loop() every second or so...

If you are not a programmer and you got this code from a freelancer, I would suggest going back to that freelancer or posting in the forum where you hire a programmer to write code for you. This forum is for helping people who are trying/struggling with their code, not for doing it all for you.

I will try that, I am a programmer - but I hired the freelancer because I am not super adept at c++ . So the issue is I have to reset the interrupts?

No, the issue is that the interrupts are probably not happening at all. It could be because you have declared those pins as INPUT which means the encode has to drive the pin high and low and never let it float. That is probably wrong. Many encoders let it float and only actively pull it low. That is why you can configure the pin as INPUT_PULLUP.

Do you have the specs/datasheet on your encoder?

Thanks for the quick reply. Attached is the motor spec sheet[https://www.amazon.com/gp/product/B07GNFYGYQ/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1]

And how about a schematic? Who do you have it wired up to your arduino?

Wireup attached. Thanks for the help.

That schematic does not match your code. You have your encoder interrupts attached to pins 2 & 3, but the schematic shows 2 motors, and neither encoder is wired up to pin 2 or 3.

I am not sure why that is the case? 2 and 3 are pins I currently have assigned to the motor driver, which should I switch around?

The schematic you posted shows the first motor's encoders connected to A0 and A1 which are analog pins, not pins 2 & 3. How did you actually wire up your motor? I'm guessing that schematic does not match your actual wiring. What is your actual wiring?

This is the actual wiring. It is incorrect, 2 and 3 are connected to the motor driver instead of the arduino uno. i am trying to fix it, do you have a diagram of what it should be?

What is the actual wiring? Please draw out a schematic of how you have your setup wired up and post a picture.

Thanks for the assistance - I am ordering an arduino mega as the uno doesn't have enough interrupt pins. I am going to rewire for the mega, I am drawing up a diagram now, any help or suggestions would be appreciated.

You don't need interrupt pins to count the pulses. You can do it directly as well with the Uno but it does take a bit more design since your loop() code needs to execute quickly to catch all the pulses.

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