Need Help with controlling a motor and servo independently using Serial.read()

Hello!
I really need help with my project.
I am making a Bluetooth-controlled Car/Tank.
I am using the Serial.read() to drive the car. i have created an app on mit app inventor and for the motors to spin one way it sends a "F" and for them to spin in reverse it sends a "R" so that bit is fine i know how to do that but i also have a slider to control the position of a servo (all the slider does is send a 0 up to 50) so i have "myServo.write (Serial.read());
and that doesnt work obviously because the servo is trying to go the the position "F" and "R"
i need help to make it work
any help would be awesome!
Thanks

Here is all my code :arrow_down:

#include <Servo.h> 
int Direction = 0;
int ReadVal = 0;
const int trigPin = 7; 
const int echoPin = 6; 
Servo AimServo;


long microsecondsToCentimeters(long microseconds) {
   return microseconds / 29 / 2;
}

void setup() {
  
pinMode(13, OUTPUT);
pinMode(12,OUTPUT);   
pinMode(11,OUTPUT);   
pinMode(10,OUTPUT);   
AimServo.attach(9);
Serial.begin(9600);


}


void loop() {

if(Serial.available()){
  Direction = Serial.read();
}

if(Direction == 'F'){            //move forward (all motors rotate in forward direction)
  digitalWrite(13,HIGH);
  digitalWrite(11,HIGH);
}
 
else if(Direction == 'B'){      //move reverse (all motors rotate in reverse direction)
  digitalWrite(12,HIGH);
  digitalWrite(10,HIGH);
}
 
else if(Direction == 'R'){      //turn right (left side motors rotate in forward direction, right side motors doesn't rotate)
  digitalWrite(11,HIGH);
}
 
else if(Direction == 'L'){      //turn left (right side motors rotate in forward direction, left side motors doesn't rotate)
  digitalWrite(13,HIGH);
}

else if(Direction == 'O'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);   
}

 if(ReadVal == "10"){
  AimServo.write (10);
}

else if(ReadVal == "20"){
  AimServo.write (20);
}

else if(ReadVal == "30"){
  AimServo.write (30);
}

else if(ReadVal == "40"){
  AimServo.write (40);
}

else if(ReadVal == "50"){
  AimServo.write (50);
}

long duration, cm;
pinMode(trigPin, OUTPUT);
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
cm = microsecondsToCentimeters(duration);
delay(100);

if (cm <= 10) {

digitalWrite(13,LOW);
digitalWrite(11,LOW);
delay (500);
digitalWrite(12,HIGH);
digitalWrite(10,HIGH);
delay (1000);
digitalWrite(12,LOW);
digitalWrite(10,LOW);
}


}

The single quote (') is for single characters. Double quotes (") are for multiple characters (strings).

The serial input basics tutorial shows robust and non-blocking ways to read and parse serial data.

Ok Thankyou

Also is there a way to separate numbers and letters from coming in? because my motors work but my servo doesn't move
Thanks
i also updated my code above

You are only reading one byte (character) so you won't get 20 since that is received as 2 characters. If you follow the methods in the tutorial that I linked you will end up receiving a string.

You cannot use equality (==) to compare strings. You would use the strcmp() function.

if(strcmp(receivedChars, "10") == 0)
{
     AimServo.write (10);
}

Here is your code with the example #2 from the tutorial added to read and parse the serial input. To run the motor forward just type F and enter in serial monitor. Same for reverse (B), right (R), left(L) or stop (O). To move the servo, type the number (10, 20, 30, 40, or 50) and enter.

Make sure that the Line Endings in serial monitor are set to "Both NL & CR."

#include <Servo.h>



const byte trigPin = 7;
const byte echoPin = 6;

const byte numChars = 10;
char receivedChars[numChars];
bool newData = false;

Servo AimServo;


long microsecondsToCentimeters(long microseconds)
{
   return microseconds / 29 / 2;
}

void setup()
{
   pinMode(13, OUTPUT);
   pinMode(12, OUTPUT);
   pinMode(11, OUTPUT);
   pinMode(10, OUTPUT);
   AimServo.attach(9);
   Serial.begin(9600);
   Serial.println("motor and servo control\n");
}

void loop()
{
   recvWithEndMarker();
   showNewData();
}

void showNewData()
{
   if (newData == true)
   {
      Serial.print("This just in ... ");
      Serial.println(receivedChars);

      if (receivedChars[0] == 'F')            //move forward (all motors rotate in forward direction)
      {
         Serial.println("motor forward");
         digitalWrite(13, HIGH);
         digitalWrite(11, HIGH);
      }

      else if (receivedChars[0] == 'B')      //move reverse (all motors rotate in reverse direction)
      {
         Serial.println("motor reverse");
         digitalWrite(12, HIGH);
         digitalWrite(10, HIGH);
      }

      else if (receivedChars[0] == 'R')      //turn right (left side motors rotate in forward direction, right side motors doesn't rotate)
      {
         Serial.println("motor right");
         digitalWrite(11, HIGH);
      }

      else if (receivedChars[0] == 'L')      //turn left (right side motors rotate in forward direction, left side motors doesn't rotate)
      {
         Serial.println("motor left");
         digitalWrite(13, HIGH);
      }

      else if (receivedChars[0] == 'O')
      {
         Serial.println("motor stop");
         digitalWrite(13, LOW);
         digitalWrite(12, LOW);
         digitalWrite(11, LOW);
         digitalWrite(10, LOW);
      }

      if (strcmp(receivedChars,"10") == 0)
      {
         Serial.println("servo to 10");
         AimServo.write (10);
      }

      else if (strcmp(receivedChars,"20") == 0)
      {
         Serial.println("servo to 20");
         AimServo.write (20);
      }

      else if (strcmp(receivedChars,"30") == 0)
      {
         Serial.println("servo to 30");
         AimServo.write (30);
      }

      else if (strcmp(receivedChars,"40") == 0)
      {
         Serial.println("servo to 40");
         AimServo.write (40);
      }

      else if (strcmp(receivedChars,"50") == 0)
      {
         Serial.println("servo to 50");
         AimServo.write (50);
      }

      long duration, cm;
      pinMode(trigPin, OUTPUT);
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);
      pinMode(echoPin, INPUT);
      duration = pulseIn(echoPin, HIGH);
      cm = microsecondsToCentimeters(duration);
      delay(100);

      if (cm <= 10)
      {

         digitalWrite(13, LOW);
         digitalWrite(11, LOW);
         delay (500);
         digitalWrite(12, HIGH);
         digitalWrite(10, HIGH);
         delay (1000);
         digitalWrite(12, LOW);
         digitalWrite(10, LOW);
      }
      newData = false;
   }
}

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (Serial.available() > 0 && newData == false)
   {
      rc = Serial.read();
      if (rc == '\r') // ignore carruage return
      {
         return;
      }
      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         ndx = 0;
         newData = true;
      }
   }
}

Thank youuu soooo much!!!

It Works Mostly.
it just doesn't work with my app but that's ok

sorry for being a pest im just not very good at this but i want to learn

is there a more simple way of doing this? it has a lot of things i dont understand.

is this the best way just to make it when the Arduino receives a 10, 20, 30, 40 or 50 the servo goes to that position, and when the Arduino receives a "F", "B", "L", "R" or "O" the motor spins How i have it coded (i can add the sensor code later).

Sorry for being a massive pest but i just would like to know

Thank you Very Much!!!

Also, why won't this work?
the motors move (the outputs) but the servo doesn't?
again any help would be great! :grin:

#include <Servo.h> 
int ReadVal = 0;
const int trigPin = 7; 
const int echoPin = 6; 
Servo AimServo;



long microsecondsToCentimeters(long microseconds) {
   return microseconds / 29 / 2;
}

void setup() {
  
pinMode(13, OUTPUT);
pinMode(12,OUTPUT);   
pinMode(11,OUTPUT);   
pinMode(10,OUTPUT);   
AimServo.attach(9);
Serial.begin(9600);


}


void loop() {

if(Serial.available()){
  ReadVal = Serial.read();
}

if(ReadVal == 'F'){            //move forward(all motors rotate in forward direction)
  digitalWrite(13,HIGH);
  digitalWrite(11,HIGH);
}
 
else if(ReadVal == 'B'){      //move reverse (all motors rotate in reverse direction)
  digitalWrite(12,HIGH);
  digitalWrite(10,HIGH);
}
 
else if(ReadVal == 'R'){      //turn right (left side motors rotate in forward direction, right side motors doesn't rotate)
  digitalWrite(11,HIGH);
}
 
else if(ReadVal == 'L'){      //turn left (right side motors rotate in forward direction, left side motors doesn't rotate)
  digitalWrite(13,HIGH);
}

else if(ReadVal == 'O'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);
delay (50);   
}

else if(ReadVal == '1'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);
  
AimServo.write (10);
  
}

else if(ReadVal == '2'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);

AimServo.write (20);
}

else if(ReadVal == '3'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);

AimServo.write (30);
}

else if(ReadVal == '4'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);

AimServo.write (40);
}

else if(ReadVal == '5'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);
AimServo.write (50);
}

long duration, cm;
pinMode(trigPin, OUTPUT);
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
cm = microsecondsToCentimeters(duration);
delay(100);

if (cm <= 10) {

digitalWrite(13,LOW);
digitalWrite(11,LOW);
delay (500);
digitalWrite(12,HIGH);
digitalWrite(10,HIGH);
delay (1000);
digitalWrite(12,LOW);
digitalWrite(10,LOW);
}


}

There is less complicated ways to do that, but they are not as robust and/or use code that can get a new user in trouble (String class for instance).

Best is in the eye of the beholder. A good way, yes it is. The best, not for me to say. It is the way that I would do it.

I put serial prints into your code from post # 7 and tried it. It seems to work for me. There is something wrong with your servo because the code is writing to it.

#include <Servo.h>

int ReadVal = 0;
const int trigPin = 7;
const int echoPin = 6;

Servo AimServo;

long microsecondsToCentimeters(long microseconds)
{
   return microseconds / 29 / 2;
}

void setup()
{
   pinMode(13, OUTPUT);
   pinMode(12, OUTPUT);
   pinMode(11, OUTPUT);
   pinMode(10, OUTPUT);
   AimServo.attach(9);
   Serial.begin(9600);
}

void loop()
{
   if (Serial.available())
   {
      ReadVal = Serial.read();
   }

   if (ReadVal == 'F')            //move forward(all motors rotate in forward direction)
   {
      Serial.println("motor forward");
      digitalWrite(13, HIGH);
      digitalWrite(11, HIGH);
   }

   else if (ReadVal == 'B')      //move reverse (all motors rotate in reverse direction)
   {
      Serial.println("motor reverse");
      digitalWrite(12, HIGH);
      digitalWrite(10, HIGH);
   }

   else if (ReadVal == 'R')      //turn right (left side motors rotate in forward direction, right side motors doesn't rotate)
   {
      Serial.println("motor right");
      digitalWrite(11, HIGH);
   }

   else if (ReadVal == 'L')      //turn left (right side motors rotate in forward direction, left side motors doesn't rotate)
   {
      Serial.println("motor left");
      digitalWrite(13, HIGH);
   }

   else if (ReadVal == 'O')
   {
      Serial.println("motor stop");
      digitalWrite(13, LOW);
      digitalWrite(12, LOW);
      digitalWrite(11, LOW);
      digitalWrite(10, LOW);
      delay (50);
   }

   else if (ReadVal == '1')
   {
      Serial.println("servo to 10");
      digitalWrite(13, LOW);
      digitalWrite(12, LOW);
      digitalWrite(11, LOW);
      digitalWrite(10, LOW);

      AimServo.write (10);
   }

   else if (ReadVal == '2')
   {
      Serial.println("servo to 20");
      digitalWrite(13, LOW);
      digitalWrite(12, LOW);
      digitalWrite(11, LOW);
      digitalWrite(10, LOW);

      AimServo.write (20);
   }

   else if (ReadVal == '3')
   {
      Serial.println("servo to 30");
      digitalWrite(13, LOW);
      digitalWrite(12, LOW);
      digitalWrite(11, LOW);
      digitalWrite(10, LOW);

      AimServo.write (30);
   }

   else if (ReadVal == '4')
   {
      Serial.println("servo to 40");
      digitalWrite(13, LOW);
      digitalWrite(12, LOW);
      digitalWrite(11, LOW);
      digitalWrite(10, LOW);

      AimServo.write (40);
   }

   else if (ReadVal == '5')
   {
      Serial.println("servo to 50");
      digitalWrite(13, LOW);
      digitalWrite(12, LOW);
      digitalWrite(11, LOW);
      digitalWrite(10, LOW);
      AimServo.write (50);
   }

   long duration, cm;
   pinMode(trigPin, OUTPUT);
   digitalWrite(trigPin, LOW);
   delayMicroseconds(2);
   digitalWrite(trigPin, HIGH);
   delayMicroseconds(10);
   digitalWrite(trigPin, LOW);
   pinMode(echoPin, INPUT);
   duration = pulseIn(echoPin, HIGH);
   cm = microsecondsToCentimeters(duration);
   delay(100);

   if (cm <= 10)
   {

      digitalWrite(13, LOW);
      digitalWrite(11, LOW);
      delay (500);
      digitalWrite(12, HIGH);
      digitalWrite(10, HIGH);
      delay (1000);
      digitalWrite(12, LOW);
      digitalWrite(10, LOW);
   }
}

Output: (I have no servo to test with)
servo to 10
servo to 50
motor forward
motor reverse
motor stop
servo to 20
servo to 30

How is the servo powered? How is it wired? Post a schematic showing how it should be wired. Post photos showing how it is wired.

consider the following which i include in almost all my programs to debug. in particular, instead of having specific cmds to move the servo to specific locations, you can add a command preceded by a value to move the servo to any position (e.g. 43s)

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

The code you have posted has no line
myServo.write (Serial.read())

Serial.read() reads a single byte

This means if you send the characters "20"

your code reads in

Direction = Serial.read();

and then Direction has value '2'
next iteration of your loop
and then Direction has value '0'

it is not as easy as
myServo.write (Serial.read()

Some of your commands are one byte some are two bytes.
Your code needs some kind of logic to determine if it is a one byte or a two byte command

This is possible. But I suggest something different
make your App send a command-start-character the command itself and a command-end-character
ussually command start is a '<'
and
command-end is a '>'

this means your commands look like this


<10>
<20>
etc.

for this you need a better receive-logic than just

Direction = Serial.read();

So read this tutorial to get familiar with serial receiving

best regards Stefan

Thank you everyone for your help!
does that mean this will work?

#include <Servo.h> 
int ReadVal;
const int trigPin = 7; 
const int echoPin = 6; 
Servo AimServo;



long microsecondsToCentimeters(long microseconds) {
   return microseconds / 29 / 2;
}

void setup() {
  
pinMode(13, OUTPUT);
pinMode(12,OUTPUT);   
pinMode(11,OUTPUT);   
pinMode(10,OUTPUT);   
AimServo.attach(9);
Serial.begin(9600);


}


void loop() {

if(Serial.available()){
  ReadVal = Serial.read();
}

if(ReadVal == 'F'){            //move forward(all motors rotate in forward direction)
  digitalWrite(13,HIGH);
  digitalWrite(11,HIGH);
}
 
else if(ReadVal == 'B'){      //move reverse (all motors rotate in reverse direction)
  digitalWrite(12,HIGH);
  digitalWrite(10,HIGH);
}
 
else if(ReadVal == 'R'){      //turn right (left side motors rotate in forward direction, right side motors doesn't rotate)
  digitalWrite(11,HIGH);
}
 
else if(ReadVal == 'L'){      //turn left (right side motors rotate in forward direction, left side motors doesn't rotate)
  digitalWrite(13,HIGH);
}

else if(ReadVal == 'O'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);
delay (50);   
}

else if(ReadVal == '1'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);
  
AimServo.write (10);
  
}

else if(ReadVal == '2'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);

AimServo.write (20);
}

else if(ReadVal == '3'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);

AimServo.write (30);
}

else if(ReadVal == '4'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);

AimServo.write (40);
}

else if(ReadVal == '5'){      
digitalWrite(13, LOW);
digitalWrite(12,LOW);   
digitalWrite(11,LOW);   
digitalWrite(10,LOW);
AimServo.write (50);
}

long duration, cm;
pinMode(trigPin, OUTPUT);
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
cm = microsecondsToCentimeters(duration);
delay(100);

if (cm <= 10) {

digitalWrite(13,LOW);
digitalWrite(11,LOW);
delay (500);
digitalWrite(12,HIGH);
digitalWrite(10,HIGH);
delay (1000);
digitalWrite(12,LOW);
digitalWrite(10,LOW);
}


}

Thanks

Why set the pinModes of trig and echo every time through that part of the code? Why not set them once in setup()? The pinModes do not change do they?

As for the serial reception, insert serial prints like I did and test the code.

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